AnsweredAssumed Answered

K64 Baremetal SD Card Read behavior

Question asked by joe hinkle on Jul 19, 2018
Latest reply on Jul 21, 2018 by joe hinkle

I'm seeing some performance differences between micro sd cards and have found a behavior I don't understand.

 

K64 running with 120mhz clock.

 

SDHC used in SD 4bit mode - clock 40mhz

 

Block read acquires 1 sector of 512 bytes - polling to complete.  I have included the code below.  I added an LED to the read code so that I could acquire the trace below using a logic probe.

 

Every 25msec my application acquires around 18 sectors for the sd card (sector is 512 bytes) - I turn on the LED during this acquisition period and the trace shows LOW during the read operation.  After the 18 sectors are acquired, the sd card is not accessed until the next 25msec tic occurs.

 

Behavior:

 

The first sector read following a non-use of the SDHC - that read takes over 3msec to acquire the data.  All other reads following the first only take 400usec - a factor of 10 difference.

 

I thought it might be due to the SDHC clocks gating off when no sd activity so I turned gating OFF - verified by scoping the SDHC clock line.  Disabling the clock gating operation makes no change in behavior.

 

Can someone please explain this?

 

Is this the SD card internally delaying?

 

Is there a SDHC parameter that I can look into to address this?

 

Thanks in advance for any and all comments.

 

Joe

 

SD Sector read timing trace

 

 

[CODE]

NOTE ... 95% of the delay is in the code loop
    while(0 == (SDHC_PRSSTAT  & SDHC_PRSSTAT_BREN_MASK))     
   {            
         __asm__ __volatile__ ("nop");    
   };     // wait until reset is done

Which is waiting for the SDHC to fill it's internal 512 buffer with data from the sd card

READ_Routine:
byte SDHC_ReadBlock(dword *pData, word Count)
{
    dword r = 0;

    word i;

    dword DD, DD1;

   

 

RED_LED = 1;

 

 

    while ((SDHC_PRSSTAT & SDHC_PRSSTAT_DLA_MASK) == 1)

    {

            __asm__ __volatile__ ("nop");

    };     // wait until reset is done

   

      

    SDHC_IRQSTAT |= SDHC_IRQSTAT_BRR_MASK;

   

    if (SDHC_IRQSTAT & (SDHC_IRQSTAT_DEBE_MASK | SDHC_IRQSTAT_DCE_MASK | SDHC_IRQSTAT_DTOE_MASK))

    {

        SDHC_IRQSTAT |= SDHC_IRQSTAT_DEBE_MASK | SDHC_IRQSTAT_DCE_MASK | SDHC_IRQSTAT_DTOE_MASK | SDHC_IRQSTAT_BRR_MASK;

       

        SDHC_CMD12_StopTransferWaitForBusy();

           

           SDHC_Error_Displayed = SDHC_Error_Read_Block;

 

RED_LED = 0;

        return RES_ERROR;

    }

           

 

    while(0 == (SDHC_PRSSTAT  & SDHC_PRSSTAT_BREN_MASK))

    {

            __asm__ __volatile__ ("nop");

    };     // wait until reset is done

 

   

    for(i = 0; i < Count; i++)

    {

        *pData++ = SDHC_DATPORT;

    }

 

 

 

        

    while(!(SDHC_IRQSTAT & SDHC_IRQSTAT_TC_MASK))      // wait for transfer to complete

    {

            __asm__ __volatile__ ("nop");

    };     // wait until reset is done

   

 

    

   SDHC_IRQSTAT = (SDHC_IRQSTAT_TC_MASK | SDHC_IRQSTAT_BRR_MASK | SDHC_IRQSTAT_AC12E_MASK);

   

    RED_LED = 0;

 

    return 0;

}

 

[/CODE]

 

Outcomes