SD/MMC problem on Embedded Artists baseboard with LPC1343

10 replies [Last post]
maticomp
Offline
Joined: 2010-10-26
Posts: 1

Hello!

I'm a newcomer to LPC Xpresso world and I've been trying to implement some test software using SD/MMC cards with LPC1343 seated on Embedded Artists LPCXpresso base-board.

I've downloaded examples from EA showcasing the features, but whereas all other examples work fine, the SD/MMC is giving me a headache.

Lib_MCU, Lib_FatFs_SD and Lib_EaBaseboard are provided in the examples.

The code is pretty much straightforward:

    GPIOInit();
    init_timer32(0, 10);

    SSPInit();

    SysTick_Config(SystemCoreClock / 100);

    if ( !(SysTick->CTRL & (1<SYSTICKCLKDIV = 0x08;
    }

    delay32Ms(0, 500);

    stat = disk_initialize(0);

    if (stat & STA_NOINIT) {
        UARTSendString((uint8_t*)"MMC: not initialized\r\n");
    }

    if (stat & STA_NODISK) {
        UARTSendString((uint8_t*)"MMC: No Disk\r\n");
    }

    if (stat != 0) {
        return 1;
    }
The problem is, that disk_initialize(0) always returns 1, meaning "NOT INITIALIZED". I tried to analyze this particular function looking for trouble.

DSTATUS disk_initialize (
    BYTE drv        /* Physical drive nmuber (0) */
)
{
    BYTE n, cmd, ty, ocr[4];

    GPIOSetDir( PORT1, 11, 1 ); /* CS */
    GPIOSetDir( PORT2, 10, 0 ); /* Card Detect */

    if (drv) return STA_NOINIT;            /* Supports only single drive */
    if (Stat & STA_NODISK) return Stat;    /* No card in the socket */

    power_on();                            /* Force socket power on */
    FCLK_SLOW();
    for (n = 10; n; n--) rcvr_spi();    /* 80 dummy clocks */

    ty = 0;
    if (send_cmd(CMD0, 0) == 1) {            /* Enter Idle state */
        Timer1 = 100;                        /* Initialization timeout of 1000 msec */
        if (send_cmd(CMD8, 0x1AA) == 1) {    /* SDHC */
            for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();        /* Get trailing return value of R7 resp */
            if (ocr[2] == 0x01 && ocr[3] == 0xAA) {                /* The card can work at vdd range of 2.7-3.6V */
                while (Timer1 && send_cmd(ACMD41, 1UL << 30));    /* Wait for leaving idle state (ACMD41 with HCS bit) */
                if (Timer1 && send_cmd(CMD58, 0) == 0) {        /* Check CCS bit in the OCR */
                    for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
                    ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;    /* SDv2 */
                }
            }
        } else {                            /* SDSC or MMC */
            if (send_cmd(ACMD41, 0) <= 1)     {
                ty = CT_SD1; cmd = ACMD41;    /* SDv1 */
            } else {
                ty = CT_MMC; cmd = CMD1;    /* MMCv3 */
            }
            while (Timer1 && send_cmd(cmd, 0));            /* Wait for leaving idle state */
            if (!Timer1 || send_cmd(CMD16, 512) != 0)    /* Set R/W block length to 512 */
                ty = 0;
        }
    }
    CardType = ty;
    deselect();

    if (ty) {            /* Initialization succeded */
        Stat &= ~STA_NOINIT;        /* Clear STA_NOINIT */
        FCLK_FAST();
    } else {            /* Initialization failed */
        power_off();
    }

    return Stat;
}
What I found is that line:

if (send_cmd(CMD0, 0) == 1) {            /* Enter Idle state */
fails, because send_cmd() here returns 255, and not 1. I have the feeling that this implementation of SD/MMC initialization does not follow the SD specification closely. What bugs me the most is the fact, that:

#define    FCLK_SLOW()                    /* Set slow clock (100k-400k) */
#define    FCLK_FAST()                    /* Set fast clock (depends on the CSD) */
These definitions are left blank, and SD specification clearly states that SPI clock must be set to approximately 400KHz for the initialization to work.

Have any of you encountered SD/MMC implementation problems using LPC1343 and EA XPresso base-board and could provide any clue how to approach this problem?

Every place I look at it is said that card should go into idle mode after issuing CMD0, but there is no evidence of 0xFF reply possible.

I'd appreciate any kind of help!

Best regards,
Mateusz

0
Your rating: None

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
raphaelh
Offline
Joined: 2010-10-12
Posts: 18

Hello,

Did anyone manage to run that example? I have the same problem.
I tried formatting 2 different sd cards different ways but I get always that same error message....

Is there only a certain type FAT being accepted???
As far as i understood from http://elm-chan.org/fsw/ff/00index_e.html Fat12, 16 and 32 should be supported.

thanks
raph

ktownsend
Offline
Joined: 2011-09-01
Posts: 250

I was able to get it working with FAT32, though I remember it took me a while messing around with the initialisation, etc. This code uses my own header file so it's of limited use as-is, but here's how I'm handling the different clock speeds myself:

/**************************************************************************/
/*! 
    Set SSP clock to slow (400 KHz)
*/
/**************************************************************************/
static void FCLK_SLOW()
{
    /* Divide by 10 (SSPCLKDIV also enables to SSP CLK) */
    SCB_SSP0CLKDIV = SCB_SSP0CLKDIV_DIV10;
 
    /* (PCLK / (CPSDVSR × [SCR+1])) = (7,200,000 / (2 x [8 + 1])) = 400 KHz */
    uint32_t configReg = ( SSP_SSP0CR0_DSS_8BIT    // Data size = 8-bit
                  | SSP_SSP0CR0_FRF_SPI       // Frame format = SPI
                  | SSP_SSP0CR0_SCR_8);       // Serial clock rate = 8
 
    // Set clock polarity
    configReg &= ~SSP_SSP0CR0_CPOL_MASK;    
    configReg |= SSP_SSP0CR0_CPOL_LOW;      // Clock polarity = Low between frames
    // Set edge transition
    configReg &= ~SSP_SSP0CR0_CPHA_MASK;
    configReg |= SSP_SSP0CR0_CPHA_FIRST;    // Clock out phase = Leading edge clock transition
 
    // Assign config values to SSP0CR0
    SSP_SSP0CR0 = configReg;
 
    /* Clock prescale register must be even and at least 2 in master mode */
    SSP_SSP0CPSR = SSP_SSP0CPSR_CPSDVSR_DIV2;  
}
/**************************************************************************/
/*! 
    Set SSP clock to fast (18.0 MHz)
*/
/**************************************************************************/
static void FCLK_FAST()
{
    /* Divide by 1 (SSPCLKDIV also enables to SSP CLK) */
    SCB_SSP0CLKDIV = SCB_SSP0CLKDIV_DIV1;
 
    /* (PCLK / (CPSDVSR — [SCR+1])) = (72,000,000 / (2 * [1 + 1])) = 18.0 MHz */
    uint32_t configReg = ( SSP_SSP0CR0_DSS_8BIT    // Data size = 8-bit
                  | SSP_SSP0CR0_FRF_SPI       // Frame format = SPI
                  | SSP_SSP0CR0_SCR_1);       // Serial clock rate = 1
 
    // Set clock polarity
    configReg &= ~SSP_SSP0CR0_CPOL_MASK;    // Clock polarity = Low between frames
 
    // Set edge transition
    configReg &= ~SSP_SSP0CR0_CPHA_MASK;    // Clock out phase = Leading edge clock transition
 
    // Assign config values to SSP0CR0
    SSP_SSP0CR0 = configReg;
 
    /* Clock prescale register must be even and at least 2 in master mode */
    SSP_SSP0CPSR = SSP_SSP0CPSR_CPSDVSR_DIV2;  
}


I'm using 4GB and 8GB microSD cards formatted as FAT32 for reference sake.

You can get rid of the polarity and edge transition lines ... in this case, they won't actually do anything since both values are 0.

ktownsend
Offline
Joined: 2011-09-01
Posts: 250

You'll also want to make sure that 'void disk_timerproc (void)' is being called by the systick timer or something similar. In my own case, I call it every 10ms in the systick ISR, which fires every ms:

#ifdef CFG_SDCARD
#include "drivers/fatfs/diskio.h"
volatile uint32_t fatTicks = 0;
#endif
 
volatile uint32_t msTicks;             // 1ms tick counter
 
/**************************************************************************/
/*! 
    @brief Systick interrupt handler
*/
/**************************************************************************/
void SysTick_Handler (void)
{
  msTicks++;
  #ifdef CFG_SDCARD
  fatTicks++;
  if (fatTicks == 10)
  {
    fatTicks = 0;
    disk_timerproc();
  }
  #endif
}

NXP_USA
Offline
Joined: 2009-11-30
Posts: 424

EA> It's the first time we see this comment. We have never internally had any problems. On the other hand, we always test with the same memory cards.

You may want to try another memory card.

The macros should be implemented, but they are not. If I remember correctly, the clock is set to slow in the spi-init function.
It can be a good thing to check spi clock frequency.

Second thing to check is that the jumpers are correctly set.
Third, what optimization settings is used on the compiler ?(I know for example that full optimization does not work - it is the spi driver and fat_fs library that are sensitive)

ktownsend
Offline
Joined: 2011-09-01
Posts: 250

NXP_USA wrote:
Third, what optimization settings is used on the compiler ?(I know for example that full optimization does not work - it is the spi driver and fat_fs library that are sensitive)


That surprises me ... I'm using FATFS and the MMC example with GCC 4.5.1 and -Os and haven't noticed any problems so far with the 1114 and 1343? Was there a specific issue? I'd be interested to confirm whether I have the same problem(s) with 4.5.1 and -Os (which I'm rather hopelessly dependent on with a 32KB part).

jimurai
Offline
Joined: 2011-04-07
Posts: 2

I had this exact same problem with my LPC1768. I eventually tracked it down not having set the jumpers correctly on the base-board. On J55 it is crucial that the "A" jumper is disconnected (see page 37 of the user manual - section 4.3.3).

Addtionally I used the following definitions to get the clock speed set up.

#define	FCLK_SLOW()		SSP_SetClock(LPC_SSP1, 100000)			
#define	FCLK_FAST()		SSP_SetClock(LPC_SSP1, 18000000)

Now just to tackle block sizes...

Jim

affonpign
Offline
Joined: 2011-04-07
Posts: 19

I still have the problem with a Lexar 1GB SD card. I use the LPC1769. I introduced the FCLK_SLOW() and FCLK_FAST() and the jumpers are on the right position.

Any other suggestions?

Regards,
Lucas

larryvc
Offline
Joined: 2011-02-08
Posts: 599

affonpign wrote:

Any other suggestions?


NXP_USA wrote:

You may want to try another memory card.


Have you tried a different memory card?

JojoS
Offline
Joined: 2011-05-17
Posts: 32

jimurai wrote:
I had this exact same problem with my LPC1768. I eventually tracked it down not having set the jumpers correctly on the base-board. On J55 it is crucial that the "A" jumper is disconnected (see page 37 of the user manual - section 4.3.3).

Addtionally I used the following definitions to get the clock speed set up.

#define	FCLK_SLOW()		SSP_SetClock(LPC_SSP1, 100000)			
#define	FCLK_FAST()		SSP_SetClock(LPC_SSP1, 18000000)

Now just to tackle block sizes...

Jim

The 'A' jumper was also a problem for me to get this example running. The documentation pg 37 drawing 38 is not clear, two jumpers are drawn red so you think that's it, but the A jumper pos is not shown.
Anyway, the documentation from EA is great.

Rob65
Offline
Joined: 2010-01-26
Posts: 681

jstratmann wrote:
The 'A' jumper was also a problem for me to get this example running. The documentation pg 37 drawing 38 is not clear, two jumpers are drawn red so you think that's it, but the A jumper pos is not shown.

It is a good thing to check the schematics also, there it is even more clear that J55 is a 3-position jumper block. Since the user manual only shows red jumpers on B and INH it follows that the A jumper should be removed.
Only the jumpers marked in red should be inserted, other jumpers in the jumper block described should be removed.

I've been using different boards from EA, some were given to me even before the user manual was available, so I am user to check the schematics for jumper configs.
This is a good thing to do - even with the UM at hand.
You can search the PDF file for e.g. PIO0_8, which is the MISO (Master In, Slave Out) pin of the SPI interface. You will discover that this pin is not only connected to J39 and the SD card connector but also to J38 (SPI Flash), J41 (7-segment LED) and J50 (I2C/SPI UART). The genuine SPI devices all have a tri-state output pin connected to MISO but the shift register at the 7-segment LED does not - so never connect 1-2 on J41 when using any other device.
Yes - this is stated in the user manual, but who is gonna check the 7-segment LED section of the manual while using SD, SPI Flash or anything else.

EA used a 4052 multiplexer (U26) to connect PIO1_11 to the SSEL lines of the different SPI blocks. Good thing is that they have jumpers on most pins so I made some jumper wires that I can insert between J39-2 and PIO3_0 etc. - having a few of those wires (with single female connectors at both ends) makes the board even more versatile.
The SPI UART already has its own SSEL pin (PIO2_8) so you can use one of the other 3 peripherals plus the SPI uart together Smile

Rob

feedback