cancel
Showing results for 
Search instead for 
Did you mean: 

Very slow SDMMC Read performance on STM32F746NGH6

anonymous.8
Senior II
Posted on January 26, 2017 at 20:12

Hi all. I am using the

STM32F746NGH6

 on the STM32F7 Discovery board to read from a micro-SD card through FATFS.

I am able to get only around 1MByte/sec read performance when reading blocks of 512 bytes. My application requires at least twice this read speed.

I am accessing a file through Chan's FATFS and the block size is fixed at 512 bytes. My SDMMC driver code is basically bare metal, so all the STD PERIPH and HAL crap has gone. It is pared down to the bone, as it were. I am using the 4 bit mode and the high speed clock mode and DMA mode reads. The clock speed, as verified by my logic analyzer, is indeed around 50MHz.

Given the above configuration, I should get blazing read performance, but the elapsed time to perform the 512 Byte read is sluggish, around 430 - 660 us. This is verified both by a hardware timer and an LED turning on, then off, after the block read and measuring that LED on time with my logic analyzer.

I am using a Class 4 micro-SD card.

I have attached a JPG showing a screen shot of the SD card clock. That image verifies the clock speed as about 50MHz, but interestingly it also shows that the clock comes in bursts of 7 clocks followed by a gap of 120ns. Thus the clock is not clocking in data continuously and therefore is losing about 1/2 of the available time to read the data in.

I have also attached a ZIP file with my SDMMC driver code.

Can anyone shed any light on why my SD MMC clock is so bursty and not continuous, or shed any other light on my poor read performance.

Thanks for any help you may be able to give.
14 REPLIES 14
Posted on February 08, 2018 at 03:43

With some more aggressive settings 7.62 MBps Write, 14.85 MBps Read

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
AVI-crak
Senior
Posted on February 08, 2018 at 09:21

Many thanks for the program code on direct access to the registers. This code is flexible enough for further processing with a sledgehammer.

As for the speed of the SD card.

Modern SD cards have two sets of instructions: standard and advanced user functions. Standard instructions have high-quality documentation, they are easy to use.

Advanced user functions do not have a standard, every SD card manufacturer has its own set of fast commands. And this is the problem. Access to documentation is limited, or difficult in search mode.

But there is another solution - card reader drivers for Linux. If you try hard - you can get the codes of the manufacturer's id and command sets.

All additional commands are reduced to an asynchronous transfer mode. When the card responds with a significant delay about the success of operations, without interrupting the main data stream.
AVI-crak
Senior
Posted on February 09, 2018 at 00:34

Harrison.David.002

Function SDLowLevelDMARxConfig, DMA2_Stream3-> CR = DMA_Channel_4

Function SDLowLevelDMATxConfig, DMA2_Stream3-> CR = DMA_Channel_6

That is how it should be?

Poonam Deoghare
Associate III
Posted on March 21, 2018 at 12:49

Hi folks,

I have read/written in to micro sd card using sdmmc driver and polling mode on stm32f4 disco kit.

Now I am trying to read/write using DMA mode. I am able to read write 1 block[ 512 bytes] successfully but when I am trying to read/write more thatn one block, it's not working without printf. If I add delay of 1 msec, then it works fine but I dont want to add delay.

Below is my code snippet to read/write 10 blocks . Please let me know what is going wrong.

 MX_DMA_Init();

....

void SD_Write_Data(void)

{    

       for(int i = 0; i<10; i++)

    {

    while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)

    {}

    //printf(' Write_addr is 0x%x \n' ,addr);    

    //    HAL_Delay(1);    

      HAL_SD_WriteBlocks_DMA(&hsd, Tx, addr, 1);

        addr += 0x200;     

  }

    CardState = HAL_SD_GetCardState(&hsd);

    printf('\n CardState after write is %d \n', CardState);

}

void SD_Read_Data(void)

{    

    static int k =0;

     for( k = 0; k<10; k++)

    {

    while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)

    {}

    HAL_SD_ReadBlocks_DMA(&hsd, Rx, read_addr, 1);

        read_addr += 0x200;    

      printf('\n RX is %s , k is %d \n',Rx,k);        

        }   

    CardState = HAL_SD_GetCardState(&hsd);

    printf('\n CardState after read is %d \n', CardState);     

}   

Thanks,

Poonam

Posted on March 21, 2018 at 17:14

>>

Please let me know what is going wrong.

You need code to spin on DMA completion.

\STM32Cube_FW_F4_V1.19.0\Projects\STM32F412G-Discovery\Applications\USB_Host\AUDIO_Standalone\Src\sd_diskio_dma.c

Also want to read/write as many sectors as possible, writing 10 sectors 1 at a time will be the slowest possible method, a lot of command/interaction overhead.

If you don't like polling loops, you're going to need to use a multi-threaded approach.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..