K64 Baremetal SD Card Read behavior

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

K64 Baremetal SD Card Read behavior

Jump to solution
1,043 Views
JHinkle
Senior Contributor I

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 Read.png

[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]

 

Tags (1)
0 Kudos
1 Solution
775 Views
JHinkle
Senior Contributor I

I've moved to multi-block reads and timing is fine -- I just can't get the CMD12 to properly terminate CMD18.

I started another thread on that subject.

Joe

View solution in original post

0 Kudos
6 Replies
776 Views
JHinkle
Senior Contributor I

I've moved to multi-block reads and timing is fine -- I just can't get the CMD12 to properly terminate CMD18.

I started another thread on that subject.

Joe

0 Kudos
775 Views
JHinkle
Senior Contributor I

Mark -- sanity check for me.

The initial delay is getting the sd card's internal up to speed - makes sense.  

The remaining read times should be as fast as the card can do.

I know CMD18 would provide a short read time over many reads but I tested my app which uses a FAT32 file system and my read requests are never on sector boundaries - so there was little advantage to CMD18.

Now the sanity check - It seems my actual reads (after the first are still too slow.

I'm guessing the following math is close -- if not please correct me.

I currently see a read of 1 sector in 350usec

So that is 512 * 8 bits/byte = 4096 bits in the read package.

I'm using the 4-bit interface mode so that make 1024 bus events.

350 E-6 (usec) / 1024 = 3.42 E-7 bit timing == which equates to an bus event clock of 2.93 mhz.  My SDHC clock is 40 mhz.

THAT does not make sense!!!

Any ideas on why my reads are slow?

Just a note - my timing is AFTER issuing the CMD17 - so timing associated with is not included.

Thanks.

Joe

0 Kudos
775 Views
mjbcswitzerland
Specialist V

Joe

With 50MHz SD card clock a read can be performed in about 20us.
With 25MHz it is about 40us.
With a little SW overhead maybe 60us.

I use DMA for the read, which isn't that much faster since a tight loop gives about the same, but it helps if there are other interrupts that can disturb the loop.

Check that your read buffer is long word aligned - if it isn't it slow the process down since the Cortex has to split the write into multiple bus accesses and the overall operation may be > 4x slower.

Regards

Mark

0 Kudos
775 Views
JHinkle
Senior Contributor I

Mark:

Last time we communicated on the SDHC - you were only using the SPI interface.

Have you switched your code to using the SDHC controller in 4-bit mode?

Thanks.

Joe

0 Kudos
775 Views
mjbcswitzerland
Specialist V

Joe

I have used SDHC since 2011 and also SPI (a configuration, or by default if the Kinetis device has no SDHC interface).

There is a problem with multi-block operations and the Kinetis SDHC since it can't be paused, making it impractical in environments with multiple file users that need to interrupt each other. But when this is not an issue (eg. pure USB-MSD to SD card) it is OK.

Regards

Mark

0 Kudos
775 Views
mjbcswitzerland
Specialist V

Hi Joe

If you are reading linear sector from a card you need to use CMD18 (multiple block read) in order to get best performance. The single sector read CMD17 is slower. The first read of multiple sectors is however always slower (whichever command used) since the SD cards internal logic needs to get ready - subsequent linear sector reads are then faster.

The uTasker SDHC card interface reads an initial sector in about 450us and subsequent ones in about 50us (using CMD18). This allows HS USB-MSD operation (eg. on K66) to achieve around 20MByte/sec transfer from the SD card to the PC.

Regards

Mark

uTasker - for more performance and faster, cheaper product development

0 Kudos