cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L496 - SD Card SDIO write speeds (FreeRTOS, FATFS and USB), how to get "fast" (> 100kbytes/sec) throughput?

AFahr.1
Associate III

Hi all,

I need to stream data into an SD card, at about 25KBytes/sec max. Currently I'm stuck at 11kBytes/sec, but the SDIO data transfer works, kind of. I'm using an STM32L496 board, FATFS and FreeRTOS, as well as USB.

The USB part works actually really well. Every time I plug in I'm able to download at ~400kBytes/sec and copy to the SD card at say ~200Kbytes/sec. I don't need more than that.

When the USB is unplugged, I copy data from different sensors onto a StreamBuffer (FreeRTOS), and once I get 512 bytes, I copy them over to the SD card using f_write(...) through an additional buffer. I have several issues with this:

  • If I set the clock on the SD card to be less than 2, it fails very often, seconds after it starts
hsd1.Init.ClockDiv = 2;

  • If I set the bus to be 4 bits wide with the clock 2 or more, f_write returns 1 (DISK ERROR) after about 6 seconds.
  • If I set the bus to be 1 bit wide with clock 2 or more, f_write returns 1 after a few minutes, 3-5.
  • My SD write function for FatFS is below:
DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
	DRESULT res = RES_ERROR;
	uint32_t timeout;
	uint32_t time;
	HAL_StatusTypeDef retval;
	HAL_SD_CardStateTypedef cardState;
	bool sd_wait = true;
 
 
	timeout = count * 500; //Timeout in MS per block
	sd_wait = true;
 
	if(true == sd_card_ready)
	{
	  	retval = HAL_SD_WriteBlocks(&hsd1, (uint8_t *)buff, sector, count, timeout);
	  	cardState = HAL_SD_GetCardState(&hsd1);
 
	  	if (HAL_OK == retval)
		{
			time = HAL_GetTick();
			while(true == sd_wait)
			{
				cardState = HAL_SD_GetCardState(&hsd1);
 
				if(HAL_SD_CARD_TRANSFER == cardState)
				{
					sd_wait = false;
					res = RES_OK;
				}
 
				if((HAL_GetTick() - time) > timeout)
				{
					sd_wait = false;
					HAL_SD_Abort(&hsd1);
				}
			}
		}
	}
 
    return res;
}

The above code is the same for the USB transfer.

I'm at a loss a bit, I thought writing a block (512bytes) of data would increase the data throughput to the SD card, and I have a lot of contiguous data blocks, all the time. Data is constantly read in at about 11 KBytes/sec.

I read somewhere else that doing a pre-check on the data alignment before the "HAL_SD_WriteBlocks" call would help. I might need to try that out.

If anyone can point me in the right direction with examples, links, explanations, etc, I'd really appreciate it. I am able to buffer up to ~500ms of data if necessary... maybe more, how can I detect or recover from a slow (250ms or so) write cycle?

Cheers,

Alberto

28 REPLIES 28
Jtron.11
Senior

Alberto,

Did you have a chance to throw in the logic analyzer to capture the signal of the USB detection pin at the power up? Chance there are periods of times the signal was not stable because the STM32 going thru the reset and GPIOs going thru the initialization? I learned the hard way before when I took think for granted and think the signal is on the level that I think it is, but as soon as I got the capture, my signal went up and down and vice versa for so many time especially when I utilize the reset pin input to STM32 mcu.

No, we didn't. The USB port (the host PC) provides our board with 5V over a 4.7K resistor in series into pin PA9 (I believe). The power to the board is generated independently. PA9 is read in the background at a frequency of 50 Hz or so, and that starts or stops the USB peripheral accordingly.Cheers,

Alberto

Sorry, images missing...

0693W00000BbCtkQAF.png0693W00000BbCtfQAF.png

Jtron.11
Senior

I believe if you have the pull low in the USB_VBUS it will help to prevent those glitches, in my case VBUS_SENSE is the same as your USB_ VBUS

Jtron.11
Senior

0693W00000BbDUbQAN.png

Jtron.11
Senior

Alberto,

Just a quick updates, so my SDIO adapter came, and I am successfully implemented SDIO 4 bit DMA FatFS. So I already checkout SDMMC, SPI and before was the USB device MSC.

When I put the 2 USB MSC and SDIO together, nothing work so I back out everything and just try to implement USB device MSC only. I successfully test the SRAM and SPI uSD before.

The matter is getting worse now my uUSB won't even get detection when I plug in the USB cable.

I tried on my eval Nucleo-F722ZE (2 different boards) the tutorial from STM

https://www.youtube.com/watch?v=dC0d8CVEPrQ

Or from another instruction

https://www.youtube.com/watch?v=Us_sTdGGcOQ

But both of them not working on my eval board regardless.

I just want to have the SRAM USB MSC working. Do you have any suggestion or pointers? By the way, if we use the eval, we don't need to enable PA9 for USB_VBUS enable correct?

Thank you so much for your helps.

Jtron.11
Senior

Alberto,

Please disregard the question. I got it work, but I still don't understand. I am using the power USB hub to the PC. If I switch the power on for the USB port that plugged the USB MSC in, the PC will have the issue to recognize the USB MSC; however, when I switched of the power on the port, the USB MSC is recognize and working.

Jtron.11
Senior

Alberto,

So sorry to bother you. Can you please give me some pointers?

Now I got the USB MSC and SDMMC is partially working. At the time I plug in the USB to PC, the PC is recognize and register the drive, and asked me to format the drive. When I performed the format, it got error (I think the time out) and said Window couldn't perform the format.

I believe it is related to the SDMMCCLK clock divide factor. I have my USB and SDMMC1 configure at 48MHz, the USB MSC set up is 12Mbits/s and my SDMMCCLK divide factor is 4 (to match 12MHz with USB).

When I tried to use 5, the PC won't even recognize the USB MSC since there was a query for descriptor error.

Questions:

  1. What tis the SDMMCCLK you set for your system? What is the speed you set for your USB CDC MSC and what is the setting for your SDMMCx?
  2. How do you prevent the PC asking you to format the uSD everytime you plug in the USB cable?

Sorry, in your sentence above it's not clear which is on or off? You mention 'on' twice. Do you power your board with the USB port?

Maybe it has to do with the fact that you are using VBUS sense and I'm not. I'm only using the pin as GPIO to sense the input. If you are using VBUS (maybe the dev kit uses VBUS), then that might be the issue.