Are there any examples for implementing an SD card with the LPC5411?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Are there any examples for implementing an SD card with the LPC5411?

3,154 Views
puddletowntom
Contributor III

I have been working with the SDK_2.2.1_LPCXpresso54114 development kit as i m using a LPC5411 processor. I wanted to try log data on an SD card but was having difficulty in getting this setup. It seemed like the fsl_sdspi_disk driver doesn't compile with a project. Additional files are needed and when i go to include additional drivers the errors are magnified. Even if I am able to compile this, I still don't have an example for using this driver. I found an example in the SDK_2.3.0_LPCXpresso54608-OM13588 kit for the sd card. However I m not sure if I can use this example in the LPCXpresso54114 kit. It again has problems compiling. 

Is it possible to use the sdcard driver example from the LPCXpresso54608-OM13588 kit with the LPC5411?

Labels (1)
0 Kudos
10 Replies

2,315 Views
puddletowntom
Contributor III

So I actually forgot that the blog you posted gave information on setting up the diskio.c file. I was able to make more progress with this. However I m now stuck on an issue which involves running the f_open() function. Its fails after returning the FR_NO_FILESYSTEM (no valid FAT volume) error. I tried formating the SD card in a number of variations of the FATFS but to no luck. Looking deeper into this problem, it seems as though the issue is caused when checking the boot record signature in the ff.c file. eg    if(ld_word(fs->win + BS_55AA) != 0xAA55) return 3;

When the boot record signature does not result with the value 0xAA55 it returns a 3 which in turn results in the no valid FAT volume error (FR_NO_FILESYSTEM ). My assumption is that this doesnt have anything to do with the I/O low level diskio stuff but has to do with the format. 

Does anybody know if the architecture of the LPC5411 is little endian or big endian? I couldnt find this on the datasheet. Reading the elm chan blog there is information about the FATFS being little endian and the need for conversion if using big endian architecture.

FAT Filesystem 

0 Kudos

2,315 Views
puddletowntom
Contributor III

Hi Kerry,

Sorry for the late response. I was busy working on other things so I parked aside the work I was doing on the SD card. I managed to get basic reading and writing to the sd card working (and initialisation of course). I ll probably post the code here for others if they want it. However, even though I can use what I have as a basic data logger, I would still like to have a file system set up so that I can download saved files from the SD card. It appears that I need to integrate what I have with the Fatfs. I just have a few questions on this. With my current set up it seems that I need to edit the diskio.c file for the low level I/O control using the functions 

disk_status(),

disk_initialize(),

disk_read(),

disk_write(),

disk_ioctl()

I did notice that in the middleware folder of the sdk (SDK_2.2.1_LPCXpresso54114\middleware\fatfs_0.12b\src\fsl_sdspi_disk) there is the file fsl_sdspi_disk.c. Can this be used as the diskio.c file with LPC5411?. I m having a little problem implementing the diskio.c file myself. The previous code you gave me which included the functions MMCInit(), MMCWriteCmd(), MMCReadSingleBlock(), MMCWriteSingleBlock(). Would these just be put into the disk functions disk_initialize(),disk_write(), disk_read()?

Thank you,

Ronan

0 Kudos

2,315 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Ronan,

   LPC54114 chip don't have SD/MMC peripheral, so you'd need to access the SDcard using a standard SPI port.

  You can't use the LPC54608 sdcard driver example, because LPC54608 have the SD/MMC peripheral.

  If you want to use the SD card in LPC54114, you need to write the SPI driver at first, then add the SD card driver based on the SPI interface.

  Here have a doc about the SPI SD card, although it is not the lpc code, but the sd card operation based on the SPI is the same, you still can refer to it:

Porting FatFs file system to KL26 SPI SD card code 

Wish it helps you!


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,315 Views
puddletowntom
Contributor III

Hi Kerry,

Thank you for the response. Do you know is it possible to write to the SD card without the fatfs? It seems like writing a the SPI driver is a big job. I m assuming it would take a long time to write, or do you think writing a basic SPI driver for a basic data logger can be done in a short time period? 

0 Kudos

2,315 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Kerry,

   Of course you can write the SD card without the fatfs.

    Actually, the post which I recommend you already contains the basic SD card initialization and the write, read.

  You just need to read the chapter: 3.3 SD I/O Layer

 Then, in the main file: you can call the write and read function directly, fatfs is based on the basic SD card code.

  About the SPI driver, you can refer to our LPC54114 sample code, both lpcopen and SDK is OK.

  When you write the code, if you meet the questions, just let me know! I will help you.


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,315 Views
puddletowntom
Contributor III

Hi Kerry,

This sounds good. I will try implement this next week when I get the chance. However, I was trying to understand some of the functions from the link. I see that the KL26 is using MDK5.1 software. I was trying to relate this to the SDK_2.2_FRDM-KL26Z for porting to NXP MCUXpresso code. However, I m not sure what the equivalent functions for the following are?

SSP0LowSpeed();
MMCDelayUs();
Send_Byte();
MMCWriteCmd();
MMCCS();
Get_Byte();
SSP0HighSpeed();
System_init();
spiInit();
Once I understand these functions I can try it out.
Thank you for the response.
Ronan
0 Kudos

2,315 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Ronan,

  I will post this function out directly, just for your reference.
1, SSP0LowSpeed();
/**************************************************************************************
* FunctionName   : SSP0LowSpeed()
* Description    : SSP0 low speed = 400K
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void SSP0LowSpeed(void)
{
    SPI0_BASE_PTR->BR = 7;
}
Actually, just configure the SPI clock speed to 400K, as you know the SD card configuration have the different speed.
In LPC, you also can configure the low clock speed to 400K.

2, MMCDelayUs();
void MMCDelayUs(uint16 tt)
{
    uint8 i;

    while (tt--)
    {
        for (i=0; i<250; i++)
        {
            ;
        }
    }
}
Just a software delay.

3, Send_Byte();
uint8 Send_Byte (uint8 ucdata)
{
    uint8 ucTemp;
    while((SPI0_S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK);             
    SPI0_DL = ucdata;
    
    while((SPI0_S & SPI_S_SPRF_MASK) != SPI_S_SPRF_MASK);               
    ucTemp = SPI0_DL;                                                    
    ucTemp = ucTemp;
    return ucTemp;
}

Just send one byte SPI data.


4. MMCWriteCmd();
uint8 MMCWriteCmd( uint8 cmd, uint32 arg, uint8 crc )
{
 uint16 cnt=512;
 uint8  sta;
     MMCCS(1); //SEL high
    Send_Byte( 0xff ); //delay
    
    MMCCS(0); //SEL low
 if ( sd_Enable_Select() )
 {
  return 0xff;  
 }
 
    
    Send_Byte( cmd | 0x40 );
    Send_Byte( (uint8)(arg>>24) );
    Send_Byte( (uint8)(arg>>16) );
    Send_Byte( (uint8)(arg>>8) );
    Send_Byte( (uint8)(arg) );
    Send_Byte( crc );   // CRC

 do
 {
  sta = Send_Byte( 0xff );
  cnt--;
 } while ( (cnt)&&(sta==0xff) );

 return sta;
}


__inline static void sd_Disable_Select( void )
{
 MMCCS(1);    //
 Send_Byte( 0xff ); //
}

__inline static uint8 sd_Enable_Select( void )
{
 MMCCS(0);     //
 if ( sd_WaitRead() == 0 ) // ??SD/MMC??
 {
  return 0;
 }
 sd_Disable_Select();  

 return 1;     
}


uint8  sd_WaitRead( void )
{
 uint32 cnt = 0x00fffff;
 uint8  sta;
 do
 {
  sta = Send_Byte( 0xff );;
  if ( sta == 0xff ) //
  {
   return 0;
  }
  cnt--;
 } while ( cnt );

 return 1;

}

5. MMCCS();
void MMCCS(uint8 cs)
{
    if (cs == 1)
    {
       MMC_CS_SET();                                   // SS=1
    }
    else
    {
       MMC_CS_CLR();                                   // SS=0
    }
}

Just control SPI_SEL pin high or low level.

6 Get_Byte();
uint8  Get_Byte (void)
{
    uint8 ucTemp;
    while((SPI0_S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK);            
    SPI0_DL = 0xff;                                                     

    while((SPI0_S & SPI_S_SPRF_MASK) != SPI_S_SPRF_MASK);               
    ucTemp = SPI0_DL;
    return (ucTemp);                                             
}
Read one SPI byte data.

7. SSP0HighSpeed();
void SSP0HighSpeed(void)
{
    SPI0_BASE_PTR->BR = 2;
}
Set high clock speed, to 24Mhz.

8. System_init();
MCU chip system initial, you just use the LPC system initial code is OK.

9. spiInit();

You just need to use the LPC SPI initilization code.

Wish it helps you!


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,315 Views
puddletowntom
Contributor III
Hi Kerry,
I just have a few more questions. For the MMCWriteCmd() function you have
 MMCCS(1); //SEL high
 Send_Byte( 0xff ); //delay
 MMCCS(0); //SEL low
Should this not be
 MMCCS(0); //SEL high
 Send_Byte( 0xff ); //delay
 MMCCS(1); //SEL low
I thought the Chip Select needed to be pulled low when sending a byte over SPI?
I was also trying to figure out what the CMD values are for the SD card. I found a source(http://www.dejazzer.com/ee379/lecture_notes/lec12_sd_card.pdf) on some of the CMD values, eg
CMD0 (40 00 00 00 00 95) --> 01000000 00000000 00000000 00000000 00000000 10010101
CMD8 (48 00 00 01 AA 0F)--> 01001000 00000000 00000000 00000001 10101010 00001111
CMD58 (7A 00 00 00 00 75)--> 01 111010 00000000 00000000 00000000 00000000 0111010 1
The blog post that you directed me towards has the following,
MMCWriteCmd(CMD0,0x00,0x95);
MMCWriteCmd( CMD8,0x1AA,0x87 );
MMCWriteCmd(CMD58, 0, 0 );
I m assuming the function sends 48bits? Does this mean that CMD0 = 0x40, CMD8 = 48 and CMD58 = 7A?
I m not sure where I can find the values for the following definitions,
#define CMD0 0x40 //Use SPI interface
#define CMD8 0x48 //Get SD card version
#define CMD9 ? //Read CSD, get other information,
#define CMD12 ?
#define CMD16 ? //Set SD card block size to 512Byte.
#define CMD17 ?//For reading the SD card send to this
#define CMD18 ?
#define CMD24 ? //For writing to the SD card send to this
#define CMD41 ? //Activate SD card
#define CMD55 ? //Activate SD card
#define CMD58 ?
#define CMD59 ?//Read OCR data
Thank you,
Ronan
0 Kudos

2,315 Views
puddletowntom
Contributor III

In addition, I m not entirely sure how the Send_Byte() and Get_Byte() functions are implemented. Previously using SPI, I have been using something similar to the examples for sending and receiving byte values. eg if I implemented my Send_Byte() in the same way it would look something like this.

uint8_t Send_Byte(uint8_t byte_val){
    spi_transfer_t xfer = {0};
    status_t xferStatus = kStatus_Success;
    uint8_t ucTemp;
 srcBuff[0] = byte_val;
    xfer.txData = srcBuff;
    xfer.rxData = destBuff;
    xfer.dataSize = sizeof(destBuff);
 SPI_CS_Low();
 xferStatus = SPI_MasterTransferBlocking(EXAMPLE_SPI_MASTER, &xfer);
 SPI_CS_High();
 ucTemp = destBuff[0];
 return ucTemp;
}
However, I m not sure if this is right. 
 xferStatus = SPI_MasterTransferBlocking(EXAMPLE_SPI_MASTER, &xfer);
Could you explain where you got the values in the following function
uint8 Send_Byte (uint8 ucdata)
{
    uint8 ucTemp;
    while((SPI0_S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK);            
    SPI0_DL = ucdata;
   
    while((SPI0_S & SPI_S_SPRF_MASK) != SPI_S_SPRF_MASK);              
    ucTemp = SPI0_DL;                                                   
    ucTemp = ucTemp;
    return ucTemp;
}
I don't understand the definition of SPI0_S, SPI_S_SPTEF_MASK, SPI_S_SPTEF_MASK and SPI0_DL?
Thank you,
Ronan
0 Kudos

2,315 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Ronan,

    Sorry for my later reply, really a little overloaded recently.

    Because that code is for kinetis, the register is not the same, may make you feel confused.

     SPI0_S is the status register, SPI_S_SPTEF_MASK is the SPI transfer status, SPI0_DL is the data register.

    I find you already create the new post:

Talk to an SD card via SPI? 

   You mentioned, you already send the according SD command to the SD card via the SPI interface.

  Please reply me in your new post, send me your test project, I will test it on my LPC5411X and SD card.


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos