Доброго времени суток!

Данная статья будет посвящена управлению micro sd с помощью sdio + fatfs под freertos. я использую микроконтроллер семейства STM32, в частности STM32F407VGT6, купленный на али, приложу фотографии ниже. Этот МК имеет максимальную частоту 168 Мгц, SRAM 192 кб, FLASH 1 Мб, ядро - ARM Cortex-M4.

stm32f407vgt6
stm32f407vgt6

Использовать я буду среду разработки STM32CubeIDE с конфигуратором STM32CubeMX. Если вы наткнулись на эту статью, то скорее всего либо хотите подружить SD с FreeRTOS, как сделаю я, либо наоборот подключаете FreeRTOS к уже работающему проекту, где у вас работает карточка. Но сразу скажу, что запись на карту все равно где производить, об этом далее. Стоит отметить, что fatfs на данном микроконтроллере поддерживает карточки второй версии, до 32 Гб, формат FAT32. Но есть возможность использовать карточку на 64 Гб, форматированную exfat, но данная статья не об этом.

Приступим к инициализации периферий. Первым делом идет systick - выставляем serial wire для отладки.

sdio выбираем 1-wire для упрощения, ножки подтягиваем к питанию, кроме ножки клока, делитель частоты выставляем пониже, чтобы получилось проинициализировать карту памяти, некоторые карточки иначе не инициализируются. Заходим в раздел dma, без dma и прерываний работать не будет, добавляем два события по приему и отправке, ставим галочку напротив включения глобальных прерываний по шине sdio

fatfs - ставим галочку напротив SD card, в вкладке set defines увеличим максимально возможный размер сектора, так как иногда они могут биться, это нормально, остальное оставляет по дефолту. Нужно предварительно проинициализировать любой пин на выход, подтянуть к земле, выбрать его в вкладке platform settings - он будет сигнализировать, что карточка на плате.

freertos - в верхнем окошке выбираем последнюю версию cmsis_v2, выбираем вкладку tasks and queue, нажимаем add, называем хендл задачи и функцию выполнения, в задаче для карточки выделим побольше памяти, добавляем очередь, называем не sd_que например.

Больше нам ничего не понадобиться для того, чтобы запустить проект и попробовать записать что-нибудь. Собираем проект и переходим в среду разработки для написания кода.

В самом начале перед добавлением дефолтных библиотек, которые нам подключил сам куб, впишем следующее.

#include <string.h>

Один из самых важных моментов, монтирование карточки должно быть произведено после инициализации FREERTOS, иначе будет выпадать ошибка и ничего не получится. Должно быть это самый ключевой момент, который может вас запутать. Потому что все инициализации производятся чаще всего в главной функции проекта до создание хендлов на задачи. Также в частности FREERTOS также есть небольшой момент, что вам необходимо создать как минимум 2 задачи. Я столкнулся с тем, что при всего лишь одной задаче, после ее выполнения и срабатывания переходу в другую задачу, проект зависает. Для наглядности я создал две задачи, одна будет мигать светодиодом, который у меня встроен на плату, а вторая задача монтирует карточку, и если все хорошо, запишет что-нибудь. Также для будущих проектов, зациклить задачу можно приемом xQueueReceive, с таймаутом в 1мс, что позволит сработать условию, когда вы что-нибудь засунете в очередь.


Ниже представлена задача мигания светодиодом. Каждые полсекунды светодиод будет мигать.

void led_func(void *argument)

{

	for(;;)

	{

		HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);

		osDelay(250);

	}

}

Далее переходим к вишенке на торте. Пробуем смонтировать карточку памяти и написать в нее предложение.

void sd_func(void *argument)

{

	int flag;

	extern char SDPath[4]; /* SD logical drive path */

	extern FATFS SDFatFS; /* File system object for SD logical drive */

	extern FIL SDFile; /* File object for SD */

	FRESULT res;

	UINT bytes;

	res = f_mount(&SDFatFS, (const TCHAR*)SDPath, 1);

	if(res == FR_OK){

		res = f_open(&SDFile, "log.txt", FA_WRITE | FA_CREATE_ALWAYS);

		if(res == FR_OK){

			f_write(&SDFile, "HABR hello!", strlen("HABR hello!"), &bytes);

			f_close(&SDFile);

		}

	}

	for(;;)

	{

		if(xQueueReceive(sd_queHandle, &flag, pdMS_TO_TICKS(1))){

			f_open(&SDFile, "log.txt", FA_WRITE | FA_OPEN_APPEND);

			f_write(&SDFile, "get queue", strlen("get queue"), &bytes);

			f_close(&SDFile);

		}

		osDelay(1);

	}

}

Добавляем ��еглобальные переменные, которые были инициализированы в fatfs. Я так сделал для удобство, мне не принципиально как названы переменные, но вы можете назвать их как захотите. С помощью функции f_mount производится монтирование карточки, входные параметры в принципе понятны, указатель на файловую систему, путь к ней, этот параметр должен содержать "0:/" либо "1:/", в зависимости сколько у вас карточек. Если используете одну, должен быть путь с нулем. Функция должна вам вернуть fr_ok, если все четко, то дальнейший код у вас выполнится и в файлике появится следующая надпись.

Ну вот и все :-) А далее на ваше усмотрение в зависимости от проекта можно настроить создание файлов на проверку наличия на карточке памяти; отправлять данные по очереди и записывать их на карточку памяти; реализовать различные вариации записи и стирания, создание кластеров, форматирования. Надеюсь данная статья поможет тем, кто столкнулся с проблемами инициализации sdio и работы с карточкой памяти micro sd в проекте с freertos. Удачи!