cancel
Showing results for 
Search instead for 
Did you mean: 

Slow block read with SPI fatfs

frnt
Senior

Hello,

I measured the performance of uSD card connected through the SPI on Read/Write operation.

The weird thing is that the Block read speed is 3x to 4x slower than the write speed.  I'm writing/read 4kB of data and the SD card is formatted with 4kB allocation unit.

The SPI transaction of the 4k write is about 5-7ms, when considering the SPI transaction of the block read it takes about 20ms.

Does someone have an idea of what the issues can be?

12 REPLIES 12
FBL
ST Employee

Hello @frnt 

Which stm32 product are you using?

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hello @FBL,

STM32WLEx SPI bus is 16MHz

ONadr.1
Senior III

I would look directly at the SPI bus with a logic analyzer, where the slowdown occurs.

Are there some important aspects to be considered in the block read except for the CMD18 command and CMD12 for stopping? I do not have a logic analyzer, I could have a look with the oscilloscope at one block transfer.

Try to Saleale USB analyzer. Is cheap and for this work is sufficient.

Sorry, Saleae.

frnt
Senior

Ok, I'll have a look at the Saleae.

Could it be that fatfs does not use DMA for receiving data and using blocking calls?

I think reading a 4k block in 20ms is way too slow, even for a blocking function. I suggested using the analyzer to find out how the delay is spread and what could be causing it.
 
frnt
Senior

@ONadr.1 I'll wait for the purchase. In the meantime, I have tried other micro-SD cards, but same slow speed in block read. 

I'm sharing the block read code, but to me it seems correct:


 

static bool SD_RxDataBlock(BYTE *buff, UINT len)
{
	uint8_t token;
	Timer1 = 200;
	/* loop until receive a response or timeout */
	do {
		token = SPI_RxByte();
	} while((token == 0xFF) && Timer1);

	/* invalid response */
	if(token != 0xFE) return FALSE;

	/* receive */
	do {
		SPI_RxBytePtr(buff++);
	} while(--len);

	/* discard CRC */
	SPI_RxByte();
	SPI_RxByte();
	return TRUE;
}​