Найти тему

SD-карта. Как ее подружить с STM32? В роли свахи: HAL

Информация в современном мире вышла на первый план, переоценить ее значение почти невозможно. А уж ее сохранение - одна из главных задач, которая стоит перед многими компаниями. Что же делать, если ваш крохотный микроконтроллер иногда бывает не подключен к интернету? Как сохранить информацию о том, что же он тогда делал?

Логично же, подключить к SD карте и сохранять на нее.

В прошлых частях неоднократно упоминалось, что STM32CubeMX может бережно изменять программный код, не затирая ваши правки. Сейчас мы воспользуемся этой "фишкой".

Инициализация SDIO

Откроем ранее сохраненный проект и включим поддержку SDIO.

В пункте SDMMC1 в подпункте Mode надо выбрать SD 4 bits Wide bus
В пункте SDMMC1 в подпункте Mode надо выбрать SD 4 bits Wide bus

Включение поддержки, активизирует несколько пинов стандарта SDIO.

Пины, включенные STM32CubeMX
Пины, включенные STM32CubeMX

Описание, как соотносятся конкретные пины со стандартом SD можно найти здесь. Ниже также привожу выдержку из этого описания.

Архитектура карты памяти типа SD
Архитектура карты памяти типа SD

Напряжение питания можно подавать в 3.3 Вольта, которые доступны на плате.

Напряжение питания из Даташита
Напряжение питания из Даташита

Продолжаем читать Даташит.

Дополнительное описание пинов
Дополнительное описание пинов

Пины D0, D1, D2, D3 и CMD требуют для себя push-pull драйверы. Необходимо для этих пинов включить pull-up,так как у меня нет подтяжки.

Включаем подтяжку во вкладке GPIO Settings пункта SDMMC1
Включаем подтяжку во вкладке GPIO Settings пункта SDMMC1

На этом настройка SDIO окончена

Проблема тактирования

После инициализации SDIO в STM32CubeMX возникает проблема в тактировании. Единственный способ решения, который я нашел - это переключение источника тактирования.

Эту проблему можно решить через переключение тактирования на PLL48CLK, куда указывает стрелка
Эту проблему можно решить через переключение тактирования на PLL48CLK, куда указывает стрелка

Включение FATFS

Теперь включим поддержку файловой системы.

Во вкладке Middleware пункте FATFS выбираем пункт SD card
Во вкладке Middleware пункте FATFS выбираем пункт SD card

Единственный параметр, который я изменил: увеличил значение MAX_SS до 4096.

Один из непонятных моментов -- это вкладка Platform settings, оставил значения по умолчанию. Посмотрим как это отразится в дальнейшем.

Настройки по умолчанию
Настройки по умолчанию

Генерация кода

Настало время нажать кнопку "Генерировать"!

Открываем проект в STM32CubeIDE, ничего не должно пропасть, а должно добавиться новое:

static void MX_USB_OTG_FS_PCD_Init(void);
static void MX_SDMMC1_SD_Init(void);

Сразу компилируем и... Лично я получил ошибки, так как Куб скопировал все файлы, но не прописал настройки в проект. Пришлось вручную указывать пути.

-10
-11

Код управление SD

Сам код взят из примеров, у меня они загрузились кубок по следующему пути:

STM32Cube\Repository\STM32Cube_FW_F7_V1.15.0\Projects\STM32F722ZE-Nucleo\Applications\FatFS\FatFs_uSD

Исходный код лежит тут: GITHUB

Подключаем плату к компьютеру, запускаем тестовый код и... ничего не получается.

f_mount возвращает FR_OK как и надо, однако f_mkfs возвращает FR_NOT_READY

res -- переменная, содержащая ответ функции f_mkfs
res -- переменная, содержащая ответ функции f_mkfs

Что не так, док?

Может не работать:

1. Спаянный мною модуль подключения

2. Связка FATFs SD, сгенерированная HAL

3. Сама uSD карта

Проверяем:

1. Видит ли uSD компьютер? Да, видит

2. Что возвращают функции проверки HAL_SD_init и HAL_SD_GetCardState? Первая возвращает HAL_OK, вторая HAL_SD_CARD_TRANSFER. Что это может значить: карта зависает в режиме передачи данных, на что и реагирует дальнейшая команда f_mkfs.

3. Что вернут эти же функции, если карта не будет установлена? Первая возвращает HAL_OK, вторая ноль. Дополнительно проверяем HAL_SD_GetError, который возвращает HAL_SD_ERROR_CMD_RSP_TIMEOUT. То есть достучаться до карты программа не может.

4. Инициализация? Куб добавил bsp_driver_sd.c, в котором объявлена функция BSP_SD_Init. Как раз в ней, если порыться, есть вызов функции BSP_PlatformIsDetected. И в этой функции обращаются к тому самому пину, заданному по умолчанию. Он никоем образом не связан с нашей картой, поэтому дописываем:

/* USER CODE BEGIN 1 */
/* user code can be inserted here */
status = SD_PRESENT;
/* USER CODE END 1 */

Теперь, работа программы оканчивается fr_disk_err. Какой-то не очень позитивный прогресс...

Ищем помощи у Вселенной в Интернете

Англоязычные товарищи написали, что есть такая ошибка: FATFS настроен работать с DMA, и, если подключать его без DMA, он работать не будет. Что ж подключаем... Однако сейчас разбирать, что такое DMA не будем.

Дважды нажимаем на эту кнопку, чтобы создать функции запроса DMA
Дважды нажимаем на эту кнопку, чтобы создать функции запроса DMA

Также там предлагают инициализировать SD перед FATFS, поэтому вписываем:

MX_SDMMC1_SD_Init();
BSP_SD_Init();
HAL_Delay(200);
MX_FATFS_Init();

Дополнительно, заставляем монтировать диск сразу:

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

Однако все это содержится в "небезопасной" области, поэтому будет затерто. Впрочем, для тестов подойдет.

Странные результаты

f_mkfs, f_write возвращают FR_DISK_ERR.

Теперь f_mount, f_open возвращают FR_OK. Да, файл на карте создается, но в него не записать...

Ну как бы... Продолжение следует

А ларчик открывался просто... Надо было дополнительно включить прерывания SDMMC1

-14

После чего произошла запись на SD карту.

Исходный код

Лайк?