STM32. CubeMX+FatFs+SDIO+DMA
Часть 2.
Александр Левчук dslev@yandex.ru
STM32. Работаем в среде VisualStudio+VisualGDB+ CubeMX
Виртуальный USB СОМ порт. Часть 1
Виртуальный USB СОМ порт. Часть 2
В нескольких статья описывается применение FatFs совместно с CubeMX для режима работы SDIO+DMA. В качестве носителя используется карта памяти микро SD HC 16 гигабайтов. Рассмотрены проблемы использования режима длинных имен для русского языка.
Во второй части статьи описывается настройка проекта CubeMX и файлы, созданные CubeMX.

Карта памяти uSD подключатся к модулю SDIO микроконтроллера, поэтому настройку проекта в CubeMX следует начинать с этого модуля. Настройки иллюстрируются картинками.
Примечание
Жёлтый треугольник на строке SDIO не должен вас беспокоить. SDIO может работать также в режиме 8 бит, карта uSD подключается в режиме 4 бита, остальные контакты SDIO могут использоваться для других целей, что вызывает предупреждение в виде жёлтого треугольника и пояснение конфликта.

Здесь устанавливается режим 4 бита и ещё следует установить параметр SDIOCLK clock divide factor – делитель рабочей частоты карты. Это значение может быть в диапазоне от 0 до 255. Частота вычисляется по формуле SDIO_CK = SDIOCLK / (ClockDiv + 2). Посмотрим на картинку ниже, выход генератора частот.

Как видим, SDIO тактируется двумя частотами, какая из них используется для тактирования карты неизвестно. Тактовая частота карт может быть разной, для выбранной карты частота равна 12,5 МГц. Считаем, что используется частота 72 МГц, тогда при установке параметра равного 3 получаем частоту 72 / (3+2)=14,4 МГц. Это несколько больше чем 12,5 МГц, но карта работает устойчиво и проверка осциллографом показала значение 14,4 МГц. При установке параметра равного 2, карта работать отказывается.
Далее производим установки, показанные на картинках ниже.

Установка прерываний, учтите, что прерываний два типа, от модуля SDIO и от модуля DMA.

Здесь ничего не меняем.

На этой вкладке можно задать свои метки для контактов, остальное по умолчанию.

Последний штрих – задать режим для предопределённого контакта PC5, который будет отвечать за опознание установленной карты.
Настройки FatFs в Cube лучше оставить по умолчанию, а все изменения производить в файле ffconf.h, который будет создан в проекте после компиляции, поскольку пунктов много и поначалу они не все понятны, а в файле есть подробные комментарии по каждому пункту. Для примера изменен пункт MFX_LEN = 32, это изменение будет отражено в файле ffconf.h. На картинках ниже показаны настройки FatFs.

На этой картинке показаны только часть настроек.

На этой картинке ничего не изменяем. Выбор SD Card появится автоматически, если сначала была проведена настройка модуля SDIO.

На этой картинке происходит настройка в пункте Platform Settings. Этот пункт часто ставит в тупик, если не назначить контакт ответственный за опознавание установленной карты (PC5). В таком случае появляется предупреждение и после компиляции не будет сформирована функция опознавания карты.
После создания проекта в Visual Studio+VisualGDB и подключения проекта CubeMX, как описано в первой статье, появится ряд файлов ответственных за функционирование модулей SDIO, DMA и FatFs.
Файлы SDIO:
1. sdio.h
2. sdio.c
Указанные файлы содержат одну функцию инициализации MX_SDIO_SD_Init.
Файлы DMA:
1. dma.h
2. dma.c
Эти файлы содержат функцию инициализации MX_DMA_Init, в которой позже будут произведены некоторые изменения.
Файлы FatFs:
1. fatfs.h
2. fatfs.c
3. fatfs_platform.h
4. fatfs_platform.c
5. ffconf.h
6. bsp_driver_sd.h
7. bsp_driver_sd.c
Перед тем, как перейти к рассмотрению назначения файлов FatFS, обратим внимание на некоторые приемы работы в IDE (Visual Studio+VisualGDB), позволяющие сильно упростить и ускорить изучение кода. На момент написания статьи CubeMX использует FatFS версии R0.11. Версия несколько устарела, однако не следует делать попытки заменить ее на более свежую, CubeMX не позволяет сделать такой переход. Можно отказаться от CubeMX и устанавливать FatFS вручную, в Интернете некоторые источники говорят, что это просто и легко. Однако лучше сначала установить FatFS с помощью CubeMX, оценить трудоемкость, а уже потом попробовать установку новой версии вручную. Что-то мне подсказывает, что делать это не следует, большого эффекта не получить.

Как отмечалось в предыдущей статье, изменения, вносимые в файлы CubeMX вне комментариев /* USER CODE BEGIN … */, исчезают при повторной компиляции проекта CubeMX. Приходится тщательно следить и отдельно указывать какой файл переписывать, а какой не переписывать. В тоже время бывает необходимо внести некоторые небольшие изменения вне комментариев или при отсутствии таковых для оптимизации кода. В таком случае лучшим решением является установка атрибута файла ReadOnly средствами системы. Это делается прямо из Visual Studio правой кнопкой мыши на вкладке файла.
Далее открывается папка с файлом (Open…) и вызываются свойства файла. Устанавливается галочка ReadOnly, затем на имени файла отобразится замок. Файл переписываться не будет.
![]()
Обратите внимание, в правом верхнем углу окна IDE есть несколько иконок. Иконки появляются при установка в окне свойств (Project/ VisualGDB Project Properties) в пункте IntelliSence Setting расширенных свойств (advanced …). Картинка динамическая, число иконок изменяется. Наиболее интересная иконка четвертая слева, похожая на погон. При ее включении над именем каждой функции появляется текст.
![]()
При нажатии на этот текст (5 reference) открывается окно, в котором можно в интерактивном режиме исследовать код.

Если в этом окне перейти на вкладку Calls, то увидим входящие и исходящие вызовы исследуемой функции.

Если в этом окне нажать на имя любой функции, то откроется соответствующий файл с прокруткой до текста функции. Остальные вкладки также весьма информативны и хорошо помогают и ускоряют изучение кода. В дополнение, иконка Go (или F12) позволяет быстро перейти на определение любого элемента кода с открытием соответствущего файла.
Файл ffconf.h хорошо документирован, все настройки понятны из комментариев. Если не использовать длинные имена, то можно просто ознакомиться с настройками и продолжить работу.
Поскольку длинные имена, даже не столько имена, сколько использование русского текста представляют значительный интерес, следует изучить настройки файла, относящиеся к длинным именам и Юникоду.
В процессе работы может понадобиться оперативное переключение из режима длинных имён в режим коротких имён. Режим длинных имён обозначим UTF16LE, будем использовать эту разновидность Юникода, а режим коротких имён обозначим как UTF8, поскольку компилятор Clang использует многобайтную версию Юникода UTF8 и все строки пишутся в UTF8. Соответственно и при отладке кода символы русского языка отображаются в UTF8, то есть либо числами в окне отладчика, либо мусорными символами.
Далее будет подробно рассмотрено, какие особенности в определении символьных переменных и констант вызывает смена режима имён. Если вы не недостаточно знакомы с Юникодом, следует ознакомиться подробней, хотя бы в рамках отличия UTF16LE от UTF8. В целом тема кодировок напоминает детективный роман с лихо закрученным сюжетом.
Для оперативной смены режима внесем следующие изменения в файл. В начале файла (эти определения должны быть обязательно в файле ffconf.h):
#define UTF8 0 /*use short LFN*/
#define UTF16LE 1 /*use long LFN*/
#define UNICODE UTF8 /*set mode*/
Далее изменяем пункт _CODE_PAGE.
#if UNICODE == UTF16LE
#define _CODE_PAGE 1251
#elif UNICODE == UTF8
#define _CODE_PAGE 1
#endif
Можно и не изменять, оставить таблицу 1251, разница в 150 байт не существенна. Почему так можно поступить поясню далее. Следующие изменения для трех пунктов.
#if UNICODE == UTF16LE
#define _USE_LFN 2 /* 0 to 3 */
#define _MAX_LFN 32 /* Maximum LFN length to handle (12 to 255) */
#elif UNICODE == UTF8
#define _USE_LFN 0 /* 0 to 3 */
#define _MAX_LFN 32 /* Maximum LFN length to handle (12 to 255) */
#endif // UNICODE
#if UNICODE == UTF16LE
#define _LFN_UNICODE 1 /* 0:ANSI/OEM or 1:Unicode */
#elif UNICODE == UTF8
#define _LFN_UNICODE 0
#endif // UNICODE
#if UNICODE == UTF16LE
#define _STRF_ENCODE 1
#elif UNICODE == UTF8
#define _STRF_ENCODE 0
#endif // UNICODE
Последнее изменение в файле, временно отключаем использование времени RTC для установки даты файла.
#define _FS_NORTC 1
Примечание
Для работы с длинными именами в файл main.c необходимо добавить строки
#if UNICODE == UTF16LE
#include "unicode.c" // for unicode and long names
#endif // UTF16
Файлы fatfs.h и fanfs.c также потребуется слегка исправить, если используются длинные имена. Дело в том, что FatFs для длинных имен использует тип TCHAR (16 бит) в символьных переменных и константах. Если длинные имена не используются, TCHAR становится типом char. Разработчики CubeMX это не учли и в данных файлах файловые имена везде имеют тип char, что вызывает ошибку при компиляции. Файлы fatfs описывают файловые объекты и имеют только две функции для связи с драйвером, поэтому изменений немного.
В fatfs.h меняем char
extern TCHAR SDPath[4]; /* SD logical drive path */
В fatfs.с меняем char
TCHAR SDPath[4]; /* SD logical drive path */
В этом же файле жмем F12 на имени функции FATFS_LinkDriver, откроется файл ff_gen_drv.c, в котором есть функции FATFS_LinkDriver, FATFS_UnLinkDriverEx, FATFS_UnLinkDriver, FATFS_LinkDriverEx. Для этих функций и их обявлений в файле ff_gen_drv.h также выполняем замену char на TCHAR.
uint8_t FATFS_LinkDriverEx(Diskio_drvTypeDef *drv, TCHAR *path, uint8_t lun);
uint8_t FATFS_LinkDriver(Diskio_drvTypeDef *drv, TCHAR *path);
uint8_t FATFS_UnLinkDriver(TCHAR *path);
uint8_t FATFS_UnLinkDriverEx(TCHAR *path, BYTE lun);
Файлы bsp_driver_sd являются файлами драйверов BSP (Board support package) для поддержки различных модулей микроконтроллера. В начале файла bsp_driver_sd.c, в комментариях, есть подсказка для поиска документа с описанием драйвера BSP. В этой же подсказке сказално, что многие функции в файле выполнены как функции со слабой связью (_weak) и могут быть перегружены или заменены кодом, который приводится в описании драйвера.
Документ находится в директории …\CubeMX\Repository\STM32Cube_FW_F1_V1.xx\Drivers\BSP\STM3210E_EVAL\ STM3210E_EVAL_BSP_User_Manual.
Некоторые функции в этом файле нуждаются в перегрузке, другие нужно будет скопировать из документа STM3210E_EVAL_BSP_User_Manual и модернизировать. Файл bsp_driver_sd.c имеет вставки комментариев USER CODE BEGIN, но всегда лучше написать свой файл, в котором расположить перегруженные функции и собственные по теме. В таком случае вы застрахованы от перезаписи файлов CubeMX и в тоже время функции вашей разработки не путаются с функциями CubeMX.
Продолжение следует…