SD card sector writes

MateusGL
Posts: 17
Joined: Sun Feb 23, 2020 5:18 am

SD card sector writes

Postby MateusGL » Wed Apr 29, 2020 11:09 pm

Hi,

I'm doing a project where I receive data from SPI and write it to the sd card. I need to write blocks of 13824 bytes at a rate of 62.5 Hz (total of 6.59 Mbps). When I test sector writes writing as fast as I can, I achieve more than 40 Mbps, but when I try to write only 13824 bytes blocks at a rate of 62.5 Hz, almost all blocks are sent at time, but periodically (like 1 block each second) there is a delay writing a block and a sequence of blocks is not written at time. I debugged the code and found that this delay is caused when the function sdmmc_host_wait_for_event() (at sdmmc_host.c) calls xQueueReceive.

Someone knows why this delay is periodically occurring and what I can do to avoid it?

The code of the task that does the SD writes is:

Code: Select all

static void IRAM_ATTR vDataSendTask(void *pvParameters)
{
	uint32_t ulNumberOfSamples = (((sample_args_t*) pvParameters)->t_sec->ival[0])*4000;
	uint8_t ucBufferToRead = 0;
	uint32_t ulSamplesCounter = ulNumberOfSamples;
	size_t sector_size = xGetSDSectorSize();
	size_t start_block = 0;

	while(ulSamplesCounter>0)
	{
		configASSERT(xSemaphoreTake(xMutexBuffer[ucBufferToRead],portMAX_DELAY) == pdTRUE);
		xWriteSDSector(ppucBuffer[ucBufferToRead], start_block, BUFFER_SIZE/sector_size);
		ulSamplesCounter-=BUFFER_N_FRAMES;
		start_block+=BUFFER_SIZE/sector_size;
		configASSERT(xSemaphoreGive(xMutexBuffer[ucBufferToRead]) == pdTRUE);
		ucBufferToRead = (ucBufferToRead+1)%N_BUFFERS;
	}

	vTaskDelete(NULL);
}
Other task writes the buffer and gives the mutex of that buffer at the specified rate. At each iteration I change the buffer to be read and the buffer to be written.

ESP_Sprite
Posts: 9577
Joined: Thu Nov 26, 2015 4:08 am

Re: SD card sector writes

Postby ESP_Sprite » Thu Apr 30, 2020 9:44 am

That's probably the SD card performing internal tasks like sector erasing, internal wear leveling, etc. Not much you can do about that, except perhaps pick a different SD card. You can perhaps work around it by having a buffer somewhere that can fill up with data while the SDcard is otherwise occupied.

MateusGL
Posts: 17
Joined: Sun Feb 23, 2020 5:18 am

Re: SD card sector writes

Postby MateusGL » Fri May 01, 2020 6:11 am

Thanks for answering, I tested with other SD card and the pattern changed, so I think you are right!

I'm doing what you said: while one buffer is written in the SD card, other task is receiving new data and writing in a second buffer that will be written to the SD card when it is full. The problem is that when occur a big write delay, the buffer being written gets full before the completion of the other buffer write to the sd card and I don't have more memory to create bigger buffers.

Yesterday I modified my code to use queue instead of buffers+mutex to transfer data between the tasks. I created a big queue that reduced the number of lost samples, but a few samples are still lost. One problem I saw is that although there is free memory to approximately 900 samples (I've called heap_caps_get_free_size(MALLOC_CAP_8BIT) just before queue creation and printed the result), I can't create a queue with more than 520 samples (each sample is 216 bytes). Do you know why it is happening?

ESP_Sprite
Posts: 9577
Joined: Thu Nov 26, 2015 4:08 am

Re: SD card sector writes

Postby ESP_Sprite » Fri May 01, 2020 6:19 am

520*216 bytes is 112K - could be that the memory allocator can't find one contiguous block to return to you. If you're using psram, you could perhaps get around it by allocating the memory there and using xQueueCreateStatic to buid a queue around that - if I'm remembering correctly queues don't allocate in psram by themselves. Alternatively, allocate all the buffer elements manually and feed the queue pointers to those; that's likely more efficient as well as it doesn't involve copying all the data.

Who is online

Users browsing this forum: No registered users and 374 guests