Jump to content

    
etoja

скорость записи на uSD

Recommended Posts

Пишу на карточку uSD кодом, сгенерированным в CubeMX,FatFS,SDIO 4 бита,DMA. 

Компилятор gcc, опция компилятора  -Ofast.

Максимальная скорость записи 750 Кбайт/сек. 

У кого-нибудь получилось больше ?

Сама карточка позволяет 10 Мбайт/сек.

Share this post


Link to post
Share on other sites
On 2/28/2021 at 9:50 AM, etoja said:

Пишу на карточку uSD кодом, сгенерированным в CubeMX,FatFS,SDIO 4 бита,DMA. 

Компилятор gcc, опция компилятора  -Ofast.

Максимальная скорость записи 750 Кбайт/сек. 

У кого-нибудь получилось больше ?

Сама карточка позволяет 10 Мбайт/сек.

Вы не смогли повысить скорость записи?

Share this post


Link to post
Share on other sites
On 2/28/2021 at 11:13 AM, GenaSPB said:

Попроюуйте писать блоками по 16 килобайт например

Можно хоть мегабайтными блоками писать, у FatFS буфер всё равно только на один сектор.

0. Убедитесь, что автодетект сработал, и карта работает на 50МГц.

1. Форматируйте в exFAT.

2. Поэкспериментируйте с размером кластера. При слишком большом кластере f_mkdir начнёт тормозить, так как он заполняет весь кластер (по одному сектору). Если вам это не нужно, то сделайте кластер размером с AU используемой карты. Проследите, что после форматирования файловая система легла по границе AU.

3. Используйте f_expand. 

4. Рассмотрите переход на Microsoft Azure.

Share this post


Link to post
Share on other sites
53 minutes ago, DmitryR said:

Можно хоть мегабайтными блоками писать, у FatFS буфер всё равно только на один сектор

Если начало/конец записываемого блока кратны сектору, то буферизация в FATFS не используется - все идет "мимо" нее.

Да, хорошо бы чтобы в драйвевере карты использовалась команда резервирования блоков (ACMD23).

 

Кусочек моего кода (живет в открытом гитхабовском репо):


		// write multiblock
		//PRINTF(PSTR("write multiblock, count=%d\n"), count);

		// Pre-erased Setting prior to a Multiple Block Write Operation
		// Setting a number of write blocks to be pre-erased (ACMD23)
		if (sdhost_short_acmd_resp_R1(SD_CMD_SD_APP_SET_NWB_PREERASED, count & 0x7FFFFF, & resp, DEFAULT_TRANSFER_MODE) != 0) // ACMD23
		{
			PRINTF(PSTR("SD_CMD_SD_APP_SET_NWB_PREERASED error\n"));
			return RES_ERROR;
		}
		//PRINTF(PSTR("SD_CMD_SD_APP_SET_NWB_PREERASED okay\n"));

		if (sdhost_use_cmd23 != 0)
		{
			// set block count
			sdhost_short_resp(encode_cmd(SD_CMD_SET_BLOCK_COUNT, DEFAULT_TRANSFER_MODE), count, 0);	// CMD23
			if (sdhost_get_R1(SD_CMD_SET_BLOCK_COUNT, & resp) != 0)	// get R1
			{
				PRINTF(PSTR("SD_CMD_SET_BLOCK_COUNT error (count=%u)\n"), (unsigned) count);
				return RES_ERROR;
			}
		}

		// write multiblock
		// Сперва настраивается DMA, затем выдается команда SD_CMD_WRITE_MULT_BLOCK
		// Работает и на STM32Fxxx
		DMA_SDIO_setparams((uintptr_t) buff, 512, count, txmode);
#if CPUSTYLE_STM32H7XX || CPUSTYLE_STM32MP1
		// H7 need here: 
		sdhost_dpsm_prepare((uintptr_t) buff, txmode, 512 * count, 9);		// подготовка к обмену data path state machine - при записи после выдачи команды
#endif /* CPUSTYLE_STM32H7XX */

		// write blocks
		sdhost_short_resp(encode_cmd(SD_CMD_WRITE_MULT_BLOCK, getTransferMode(txmode, count)), sector * sdhost_getaddresmultiplier(), 0);	// CMD25
		if (sdhost_get_R1(SD_CMD_WRITE_MULT_BLOCK, & resp) != 0)
		{
			DMA_sdio_cancel();
			PRINTF(PSTR("SD_CMD_WRITE_MULT_BLOCK error\n"));
			return RES_ERROR;
		}

#if ! (CPUSTYLE_STM32H7XX || CPUSTYLE_STM32MP1)
		// other then H7 need here
		sdhost_dpsm_prepare((uintptr_t) buff, txmode, 512 * count, 9);		// подготовка к обмену data path state machine - при записи после выдачи команды
#endif /* ! CPUSTYLE_STM32H7XX */

		if (sdhost_dpsm_wait((uintptr_t) buff, txmode, 512 * count) != 0)
		{
			PRINTF(PSTR("SD_disk_write: sdhost_dpsm_wait error\n"));
			DMA_sdio_cancel();
			if (sdhost_stop_transmission() != 0)
				PRINTF(PSTR("SD_disk_write 2: sdhost_stop_transmission error\n"));
			return RES_ERROR;
		}
		else if (DMA_sdio_waitdone(txmode) != 0)
		{
			DMA_sdio_cancel();
			PRINTF(PSTR("SD_disk_write 2: DMA_sdio_waitdone error\n"));
			return RES_ERROR;
		}
		else
		{
			sdhost_dpsm_wait_fifo_empty();
			DMA_sdio_cancel();

			#if ! CPUSTYLE_R7S721 && ! CPUSTYLE_XC7Z
			// В процессоре CPUSTYLE_R7S721 и CPUSTYLE_XC7Z команда CMD12 формируется аппаратурой
			if (sdhost_use_cmd23 == 0)
			{
				if (sdhost_stop_transmission() != 0)
					PRINTF(PSTR("SD_disk_write 3: sdhost_stop_transmission error\n"));
			}
			#endif /* ! CPUSTYLE_R7S721 */
		}
		//PRINTF(PSTR("write multiblock, count=%d okay\n"), count);
		return RES_OK;
	

 

Edited by GenaSPB

Share this post


Link to post
Share on other sites
19 часов назад, DmitryR сказал:

Можно хоть мегабайтными блоками писать, у FatFS буфер всё равно только на один сектор.

Сектор-то один, но ФС может писать блоками вплоть до размера кластера, по умолчанию размер блока=размеру сектора 512байт, можно задать 4Кб, т.к. размер кластера меньше точно не будет...

Share this post


Link to post
Share on other sites
19 часов назад, DmitryR сказал:

Можно хоть мегабайтными блоками писать, у FatFS буфер всё равно только на один сектор.

И кто мешает сделать буфер любого желаемого размера в своём middle-ware слое?

Share this post


Link to post
Share on other sites
18 часов назад, GenaSPB сказал:

использовалась команда резервирования блоков (ACMD23).

А что она дает?

1 минуту назад, jcxz сказал:

И кто мешает сделать буфер любого желаемого размера в своём middle-ware слое?

Наверно то, что это надо делать самому...

Share this post


Link to post
Share on other sites
5 минут назад, mantech сказал:

Наверно то, что это надо делать самому...

Если способности к рытью в помойках поиску на гитхабах (и т.п.) развиты лучше чем способности к "деланию самому", то можно попробовать поискать готовое.

Задача такая типичная, то почти наверняка хотя-бы одна из миллиона мух один из пользователей FatFS это уже реализовывал.

Share this post


Link to post
Share on other sites
4 минуты назад, jcxz сказал:

один из пользователей FatFS это уже реализовывал.

Возможно, хотя поискать придется, ибо 90% делателей удовлетворяется черепашьей скоростью, т.к. много чего писать и не надо. Мне как-то захотелось побыстрее - увеличил размер блока до 4К, скорость стала в 5 раз быстрее, больше, чем мне было нужно. Дальнейшее ускорение счел нецелесообразным, думаю, что еще многие так же поступили)))

Share this post


Link to post
Share on other sites

Я код привел...
Алгоритм - говорим карте, что сейчас будем писать воот-такой кусок - если нет в наличии - начинай стирать и готовить к записи

 

Share this post


Link to post
Share on other sites

Думаю - действие её аналогично команде TRIM на SSD. Которая указывает контроллеру какие сектора можно тереть в фоновом режиме, пока они ещё не нужны. Чтобы потом, когда они понадобятся для записи, они были уже стёртые и не требовали времени на стирание.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.