Top.Mail.Ru

STM32 и SD-карта. Настройка FatFs в STM32CubeMx.

Наш учебный курс по программированию микроконтроллеров с использованием новейших инструментов от ST, а именно STM32CubeMx, в самом разгаре. И на очереди у нас работа с SD-картой и файловой системой FatFS. В этот раз я буду использовать плату с микроконтроллером STM32F103VET6 (в отличие от предыдущих статей цикла, в которых использовалась STM32F4Discovery). В остальном все точно так же - запускаем CubeMx, создаем новый проект и начинаем разбираться.

Работать с файловой системой мы будем при помощи внешней SD-карты, подключенной к микроконтроллеру по интерфейсу SDIO, с которого мы и начнем настройку нашего проекта. Итак, осуществляем включение:

Активация интерфейса SDIO.

Собственно, активация SDIO происходит путем задания требуемого режима работы. В данном случае используем 4-х битный режим, именно так подключена карта памяти на моей плате:

Схема подключения карты памяти к STM32.

В результате CubeMx активировал и необходимые выводы контроллера, в общем, как и обычно, не будем на этом останавливаться. Из настроек SDIO в текущем базовом проекте изменим только значение предделителя частоты:

SDIO в STM32CubeMx

Следующим шагом включаем поддержку FatFs в соответствующем разделе и задаем режим работы, конечно, "SD Card":

Настройка FatFs в STM32CubeMx

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

В общем-то, на этом работа с STM32CubeMx заканчивается, осталось только сгенерировать исходный код и перейти к работе с проектом. Так и поступаем, а затем открываем проект и анализируем. CubeMx уже позаботился о том, чтобы вызвать необходимые функции инициализации, а кроме того осуществил связь файловой системы с SD-картой. То есть драйвер уже сконфигурирован так, что при вызове функций FatFs произойдет взаимодействие с картой по SDIO.

С этим все понятно, давайте добавим в функцию main() тестовый код, который создаст новый файл на SD-карте и запишет в него некоторые данные:

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
extern char SDPath[4];

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SDIO_SD_Init();
  MX_FATFS_Init();
  /* USER CODE BEGIN 2 */
  
  FATFS fileSystem;
  FIL testFile;
  uint8_t testBuffer[16] = "SD write success";
  UINT testBytes;
  FRESULT res;

  if(f_mount(&fileSystem, SDPath, 1) == FR_OK)
  {
    uint8_t path[13] = "testfile.txt";
    path[12] = '\0';

    res = f_open(&testFile, (char*)path, FA_WRITE | FA_CREATE_ALWAYS);
    res = f_write(&testFile, testBuffer, 16, &testBytes);
    res = f_close(&testFile);
  }

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Здесь мы последовательно:

  • монтируем объект файловой системы - f_mount()
  • открываем файл - f_open()
  • записываем данные в файл - f_write()
  • закрываем файл - f_close()

Максимально простой базовый пример для проверки работоспособности связки SDIO и FatFs 👍 В переменной res можно увидеть, возникли ли ошибки при выполнении той или иной операции. Так что собираем проект и прошиваем контроллер. После выполнения программы на карте должен появиться новый файл, проверяем это, подключив SD к ПК:

STM32 SD-карта.

На карте памяти обнаруживается файл testfile.txt с тем содержимым, что мы и планировали, а именно со строкой, сигнализирующей о том, что запись проведена успешно. Таким образом, задача решена.

Резюмируем ) В этой статье мы разобрались, как при помощи STM32CubeMx реализовать поддержку FatFs в нашем проекте. Собственно, большую часть работы CubeMx взял на себя, так что на сегодня на этом заканчиваем, обязательно следите за обновлениями нашего сайта!

Подписаться
Уведомить о
guest

108 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
Elis
Elis
8 лет назад

Спасибо за статью )

Ars
Ars
8 лет назад

Это просто класс! ^_^_^ Спасибо большое!

MikeNT
MikeNT
8 лет назад

Спасибо за статью! Непонятно какую частоту мы получаем при SDIOCLK clock divide factor=3? 72/3?

Алексей
Алексей
8 лет назад

Такой вопрос, как подключен карт-ридер, к каким портам, может есть принципиальная схема, хотелось бы его использовать на своей плате STM32F429 discovery

Roman
Roman
8 лет назад

К сожалению, не получилось воспроизвести этот пример на STM32F4Discovery. Очень нужен, но пока ... 🙁 пробовал и 1битную и 4битную версию и подтяжки и без. Очень мало подробностей и нет промежуточного контроля процесса. не понятно куда рыть. Но спасибо за Вашу работу в любом случае. Все остальные примеры заработали и полезны.

Roman
Roman
8 лет назад

А как мне посмотреть процесс? я только учусь, вот в руки попала STM32F4Discovery. Судя по тому что я добавил зажигание светодиода в ELSE то не выполняется первое условие if(f_mount(&fileSystem, SD_Path, 1) == FR_OK). Как то можно заглянуть внутрь работы?

Roman
Roman
8 лет назад

Монтирует, но не открывает файл и не создает (пробовал с уже созданным). Делитель увеличивал. А какая формула вычисления делителя, что делится на 2+3?
if(f_open(&testFile, (char*)path, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) //открыли файл или создали если нет
{HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);//LED ORANGE }
else { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);//red led
while (1) { }
И вот получаю красный. Когда задачи выполняются одна за другой как будто все проходит хорошо но файла в результате нет.
И не могли бы Вы посвятить статью отладке программ?

Alexey
Alexey
8 лет назад

Добрый вечер! Спасибо за статью! И у меня есть к Вам вопрос? Как организовать запись на SD карту оцифрованных значений, можно ли напрямую из функции main() забирать значения из ADC и писать их на флешку в вашем примере?

Alexey
Alexey
8 лет назад

Спасибо за ответ! А можно ли делать запись оцифрованных значений в виде бинарного файла?

Sergey
Sergey
8 лет назад

Напишите аналогичный пример работы с FATFS на примере подключения SD по SPI

Ioann_II
Ответ на комментарий  Sergey
7 лет назад

У Вас получилось в Кубе сделать FATFS по SPI? Если да, то подскажите.
Если можно.
Спасибо.

Sergey
Sergey
Ответ на комментарий  Ioann_II
7 лет назад

Да, у меня все получилось и по SPI и по SDIO. По SDIO вообще ничего делать не надо CUBE сам все за вас сделает, а после генерации проекта просто используем функции из драйвера. По SPI необходимо прописать низкоуровневые функции в файле \Middlewares\Third_Party\FatFs\src\diskio.c
Единственная проблема, Keil не всегда корректно работает с распределением памяти под массивы (буферы) при настройках, заданных по умолчанию в кубе. У меня эта проблема периодически появляется. Я далеко не профессиональный программист, развлекаюсь так для себя. Проблемы решаются методом "тыка" поэтому когда занимался с FATFS все решилось использованием IAR вместо KEIL. Сейчас работаю над другим проектом, тоже столкнулся с аналогичной проблемой, переезжать на IAR лень. Вопрос решился, когда снял галочку в разделе оптимизации Options for target - C/C++ ..One ELF Section per Function.

Sergey
Sergey
Ответ на комментарий  Ioann_II
7 лет назад

если что пишите - freesty777@ya.ru

Sergey
Sergey
8 лет назад

Добрый день, попробовал реализовать FTFS на плате STM32VLDISCOVERY с подключенной SD к SPI1 (РА5-РА7). Использовал CUBE. Прошла инициализация, создался файл на SD, а вот прочитать и записать в файл не получилось. В некоторых случаях переставал инициализироваться дисплей (висит на SPI2). В отладчике видно, что выкидывает в HardFault_Handler. Думаю проблемы с распределением памяти.

Sergey
Sergey
8 лет назад

Добрый день. Попробовал без дисплея, не помогло. А так же много других вариантов. Наверно проблема в криво написанных функциях обмена с SD по SPI. Поэтому остается актуальной просьба написать статью об этом. 🙂
Ну а если не получится, перепаяю STM32F100RB на STM32F415RG и буду использовать ваш проверенный вариант.

Sergey
Sergey
8 лет назад

Думаю надо отписаться по результатам дальнейших экспериментов с FATFS. Перепаял таки STM32F100RB на STM32F405RG, ошибки повторились. Затем попробовал Ваш пример уже с использованием SDIO - НЕ РАБОТАЕТ!!!!!. Сломал не одни бубны в адском танце. Оказалось проблема совсем в неожиданном месте - в компиляторе. Я использовал KEIL. После сборки проекта в IAR все заработало. Теперь снова буду пробовать SPI.

Sergey
Sergey
8 лет назад

Я пробовал в двух версиях 4.73 и 5.13.

Sergey
Sergey
8 лет назад

До попытки работы с FATFS меня полностью устраивала пара KEIL + CUBE.
Кстати только что запустил FATFS по SPI - тоже работает.

Андрей
Андрей
8 лет назад

У меня в связке CubeMX + KEIL5 все работает. Но правда пришлось пройти следующие шаги. Чтобы убедиться в работе SDIO сперва настроил работу функций HAL_SD_WriteBlocks. И при попытке записи FIFO буфер вернул ошибку SD_TX_UNDERRUN. Помогло увеличение значения делителя. Затем отформатировал SD в FAT и попробовал функции FAT. f_open вызвал ff_memalloc((_MAX_LFN+1)*2) , которая вернула ошибку. Помогло уменьшение _MAX_LFN в ffconf.h.
Что это за LFN и почему при родном значении 255 память не смогла выделиться? Контроллер stm32f429ni , плата eval.

Рамиль
Рамиль
Ответ на комментарий  Андрей
4 лет назад

Тоже столкнулся с такой проблемой, а решение оказалось простым. Надо всего лишь перед записью или чтением блока надо узнавать текущее состояние карты:
uint8_t sdBlock[512];
sprintf(sdBlock, "Текст который пишем в блок\r\n");
while(BSP_SD_GetCardState() == SD_TRANSFER_BUSY); // ждем освобождения карты
if(MSD_OK == BSP_SD_WriteBlocks((uint32_t *)sdBlock, i, 1, 1000)){ // Пишем данные
SendStr("Записалось\r\n");
}else{
SendStr("Ошибка записи\r\n");
}
memset(sdBlock, 0 , sizeof(sdBlock)); // очищаем буфер для правдивости
while(BSP_SD_GetCardState() == SD_TRANSFER_BUSY); // ждем освобождения карты
if(MSD_OK == BSP_SD_ReadBlocks((uint32_t *)sdBlock, i, 1, 1000)){
SendStr(sdBlock); // Выводим в терминал считанный блок (до первого нуля) в виде текста
}

Сергей
Сергей
8 лет назад

А когда ожидается пример с SPI ?

Сергей
Сергей
8 лет назад

Если не сложно подскажите в каком файле user_diskio.c или diskio.c мне нужно вписать низкоуровневые функции по работе с картой ? заранее благодарен.

Ioann_II
Ответ на комментарий  Сергей
7 лет назад

У Вас получилось?
Поделитесь, что где меняли.
Спасибо.

Сергей
Сергей
Ответ на комментарий  Ioann_II
7 лет назад

Здравствуйте, CubeMX создает файл user_diskio.c в нем требуется заполнить функции работы с картой SD.

RiseOfDeath
RiseOfDeath
8 лет назад

Маленькое замечание:

uint8_t path[13] = "testfile.txt";
path[12] = '';

Последняя строчка не имеет смысла т.к. текст в ковычках (в первой строке) так и так будет с нулевым символом в конце (согласно стандарту).

RiseOfDeath
RiseOfDeath
8 лет назад

К стати, еще забавный факт. В кейле (5 версия) не работает пример с оптимизацией -O3 (поумолчанию ставится кубом), но без оптимизации работает.

Алексей
Алексей
8 лет назад

скинь проект плиз сюда или на почту плиз. постоянно ошибка вываливается FR_NOT_ENOUGH_CORE. неделю мучаюсь...:(

Алексей
Алексей
8 лет назад

Да, спасибо. в кубе поправил эту опцию-заработало... но замечаю странную особенность - под отладкой через раз работает... бывает зайдёт в какую-то функцию и сидит там где-то в цикле крутится, зато если просто зашить и вставить флэшку пишет в неё просто великолепно.

Сергей
Сергей
8 лет назад

Если делать все как написал автор - работать НЕ будет. Даже удивительно, как у автора заработало. Автор забыл указать еще несколько пунктов.

Сергей
Сергей
8 лет назад

Я по началу тоже долбался. Но потом увидел, что Stack_Size и Heap_Size очень маленькие!

В общем 99.9% у тебя рабочее, но может у тебя стек и heap уже стояли больше, чем создает CubeMX.

На моем случае STM32F103RCT они стоят недостаточно большие 400 и 200 соответственно. По официальному описанию на FatFS их надо ставить 800 и 400. У меня меняется все это дело в startup_stm32f103xe.s файле.
.....
.....
Stack_Size EQU 0x00000800
.....
.....
Heap_Size EQU 0x00000400

Кстати с оптимизацией O3 работает отлично! В связке Keil 5 и CubeMX работает тоже отлично!

Вот ссылка на полный проект:
https://yadi.sk/d/ghDIpwZKk7rvL

Сергей
Сергей
8 лет назад

и еще, после каждой регенерации CubeMX сбрасывает стек и heap!

Stack_Size EQU 0×00000400
…..
…..
Heap_Size EQU 0×00000200

и приходится выставлять назад в

Stack_Size EQU 0×00000800
…..
…..
Heap_Size EQU 0×00000400

Сергей
Сергей
8 лет назад

Обновил ссылку на скачку проекта https://yadi.sk/d/f0k7WK4Hk7uez

Фдуч
Фдуч
8 лет назад

Какая получилось скорость чтения\записи на карту?

Александр
Александр
8 лет назад

Aveal большое спасибо за статью, Сергей большое спасибо за дополнение, мне это очень помогло так как использовал STM32F103RCT. В файле startup_stm32f103xe.s изначально было:
Stack_Size EQU 0×00000200
…..
…..
Heap_Size EQU 0×00000400
поменял на:
Stack_Size EQU 0×00000800
…..
…..
Heap_Size EQU 0×00000400
и в кубе выставил SDIOCLK clock divide factor=6.
В связке CubeMX + KEIL5 всё заработало!

Александр
Александр
8 лет назад

Ещё вопрос, каков максимальный объём массива uint8_t testBuffer[ ] который можно записать в файл?

Андрей
Андрей
7 лет назад

Aveal, замечательная статья и замечательные уроки.
Помогите разобраться с чтением с карты. Монтирование, открытие и запись проходят успешно, а прочитать не могу. Уже весь мозг сломал. Код был сгенерирован под Keil4.74
uint8_t mas[6]="qwerty";
uint8_t mas2[6];
if (f_mount(&fileSystem, SD_Path, 1) == FR_OK)
{
Led_Red_On;
if (f_open(&testFile, (char*)"my_file_017.txt", FA_WRITE | FA_CREATE_ALWAYS)==FR_OK) Led_Green_On;
if (f_write(&testFile, mas, 6, &testBytes)==FR_OK) Led_Yellow_On;
if (f_read (&testFile, mas2, 6, &testBytes)==FR_OK) Led_Blue_On;
if (f_read (&testFile, &mas2, 6, &testBytes)==FR_OK) Led_Blue_On;
Тут я пробовал прочитать с записью в массив по указателю и без него. все равно ничего на получается.
Красный, зеленый, желтый диоды включаются, когда пошагово отлаживаю, а синий нет.
Подскажите плииииз, в чем дело, почему не читается?
Спасибо заранее всем, кто ответит.

Андрей
Андрей
7 лет назад

Спасибо большое. Все заработало.
У меня еще 1 вопрос:
если в .тхт файле есть строки, то как мне их выводить последовательно друг за другом?
например:
1.aaaaaaaa
2.bbbbbbbb
3.ccccccccc
4.dddddddd
и т.д.
Спасибо за ответ.

Андрей
Андрей
7 лет назад

я имел в виду, что на карте уже записаны строки и мне их нужно последовательно считывать.
конкретнее. у меня на карте записана картинка, много 320 строк длиной 240 символов.
я хочу брать строку, выводить на дисплей, потом брать следующую, опять на дисплей и так 320 раз.
как мне каждый раз переходить на новую строку для считывания?

Андрей
Андрей
7 лет назад

иными словами, если я сделаю в цикле:
while(counter<320)
{
f_read (&testFile, mas, 240, &testBytes);
вывод на дисплей;
counter++;
}
то каждый раз я буду выводить на дисплей новую строку (1-320)?
до или после функции f_read (&testFile, mas, 240, &testBytes) надо что-то дописать?

Андрей
Андрей
7 лет назад

Спасибо большое за помощь

v1
v1
7 лет назад

Помогите люди добрые!
Написал инициализацию для SD на HAL в среде Keil5(через SPI интерфейс). Отдельно от FATFS инициализация проходит, но как только собираешь проект SPI начинает клинить... не передает данные, возвращает BUSY(мол, отвали занятая я...).
Может у кого есть проект для Keil5 c инициализаций SD по интерфейсу SPI написанный на HAL, в качестве примера?

Виктор
Виктор
7 лет назад

Интересная особенность, в Кубе указал SDIO 4 бит, а в сгенерированном проекте
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
Все при этом работает
Если меняю на
hsd.Init.BusWide = SDIO_BUS_WIDE_4B;
- не работает...

Kinobi
Kinobi
7 лет назад

Пытаюсь подключить SDHC карточку по SDIO интерфейсу. Контроллер STM32F401VE. Пробовал по описанию в Вашей статье, пробовал по документации: http://www.st.com/content/ccc/resource/technical/document/user_manual/10/c5/1a/43/3a/70/43/7d/DM00104712.pdf/files/DM00104712.pdf/jcr:content/translations/en.DM00104712.pdf (всё делал через Cube)
Результат один и тот же. В Вашем примере функция монтирования f_mount(...) выдаёт ошибку FR_NOT_READY. А в примере от ST функция создания файловой системы f_mkfs(...) выдаёт ту же ошибку. SDHC карточка размером 4 Gb class 6 от самсунга. Карточка рабочая, в компе определяется, форматируется. Что ещё очень странно: если карточку достать, то ошибка та же самая. Может быть сталкивались с таким или знаете в чём может быть проблема?

Kinobi
Kinobi
Ответ на комментарий  Aveal
7 лет назад

Спасибо за ответ. Наверное, стоит попробовать с другой картой. Но с этой всё работало в режиме общения по SPI на контроллерах STM32F105 и STM32F407.

Ещё попробовал вот эту библиотеку как с "кубом" так и без него:
https://github.com/yigiter/Sample-STM32F4-codes/tree/master/SDIOLib
Не проходит команда: SD_Command(CMD8, SHRESP, 0x000001AA);
В SDIO интерфейсе выставляется флаг: CTIMEOUT. Не хочет карточка общаться по SDIO или я что-то упускаю из вида.

Kinobi
Kinobi
Ответ на комментарий  Kinobi
7 лет назад

Заработало. Как это часто бывает - дело было в хреновых контактах. В данном случае держатель у microSD подкачал.

Aleksey
Aleksey
7 лет назад

В ходе работы с FatFS столкнулся с следующим нюансом. Проект, описанные в данной статье, работает только со внешним источником тактирования, со внутреннем - нет. Почему- не знаю, но главное, что работает.
Думаю, озвученное будет полезно)

dim
dim
7 лет назад

Здравствуйте, так а пример для fatfs по spi будет?

Дмитрий
Дмитрий
7 лет назад

День добрый, уважаемые знатоки. Задача в том, чтобы на компе отобразилась флешка. В качестве проца stm32f103. Выбрал в CubeMX режим Mass Storage Class. Разрешил FATFS. Просто собрал, зашил и на ПК определился носитель. Но какая файловая система у него ПК не понимает и зайти на носитель не дает. Где и как в проекте объяснить, что я хочу FATFS применить именно для USB. Файлов чертова прорва, куда чего прописывать? Заранее спасибо!

Aleksey
Aleksey
7 лет назад

В чем разница между 0:/1.txt и 0://1.txt ?
Так и так работает. Но как правильнее?

Dimaster
7 лет назад

Это снова я. Может ли память, которую необходимо отформатировать, быть меньше, чем размер кластера? Скажите, люди добрые

Дмитрий
Дмитрий
7 лет назад

Снова здравствуйте. Хочу выяснить такой момент. С компа форматирование STMки получается в режиме Очистка оглавления. Просто форматирование не прокатывает. Каждый раз при подключении устройства форматировать не удобно, так что попытался это сделать средствами STMки, функцией f_mkfs. Не работает. Подскажите, почему не работает. Заранее спасибо!

Артём
Артём
7 лет назад

Добрый день. Вопрос по использованию ф-ции f_mkfs.
Если форматировать под windows, запись и чтение проходит успешно. Если запускать в своей программе f_mkfs ( f_mkfs((TCHAR const*)SDPath, 0, 0) ), программа проходит без ошибок, но карта после подключения к компьютеру требует форматирования. В чем может быть дело? Понижение частоты тактирования ничего не изменило

Юрий
Юрий
6 лет назад

А как добавить свою дату-время к созданному файлу?

Николай
Николай
6 лет назад

Вопрос: как дозаписать уже существующий файл?
Есть в библиотеке FATFS какой - либо указатель как на "высоком" уровне?

Спасибо.

Алексей
Алексей
6 лет назад

Доброго времени суток. Вырисовалась такая проблема есть два исходника одной программы, разных дат создания и различающихся по общему функционалу. В более ранней версии FatFs работает как часы, а в последней версии ПО при попытке запустить функцию f_open ПО уходит в HardFault_Handler. По отладке это происходит сразу после строки в f_open:
if (!fp) return FR_INVALID_OBJECT;
Файлы библиотек идентичные, настройки одинаковые, Stack и Heap увеличивал. Помогите разобраться что за кутерьма?

Александр
Александр
Ответ на комментарий  Алексей
6 лет назад

Добрый день!
Имею похожие проблемы. Подскажите что не так. Все делал по Вашему примеру и все в принципе заработало. Но вот как только я в проект добавил обработку внешнего АЦП + запустил динамическую LED индикацию + клавиатура ... . начались сбой. Притом сбои крайне не регулярные. Последовательность примерно такая: монтируем диск, открываем файл для чтения, читаем, закрываем, открываем для записи, пишем, закрываем. Отчет о результате каждого действия вывожу на индикатор. Каждый раз ошибка в новом месте, то не монтируется то не закрывается, то не пишется .... . Но бывает что все проходит как нужно. Думал аппаратная проблема, но фиг. на этом же устройстве, со всей требухой (внешний ацп, индикатор ..) запустил USB MSD + SDIO, опять же по примеру автора статей. Все работает четко как часы. Подскажите пожалуйста куда копать?
Процессор STM32F103RCT6, использую Cube в паре с Keil uVision 5.

Александр
Александр
Ответ на комментарий  Aveal
6 лет назад

Добрый день! Спасибо что ответили. Проигрался я вчера еще полдня с проектом и в принципе практически все заработало. За исключением того что функция f_mkdir() не хочет создавать папку на диске. Основная проблема оказалась в слишком высокой скорости тактирования. После установки делителя = 40 в принципе все начало работать. Хотя и не так хорошо ка хотелось бы. А с функцией f_mkdir() вообще ничего не понятно. Я ведь не создаю проект с нуля, а фактически перебрасываю часть из готового под AVR. Там я использовал ту же самую FatFs. Все работало отлично. Данные регистрируются четко без потерь, просто надо было добавить возможность считывания результатов регистрации через USB, вот и решил сделать на STM а тут такие непонятки. Пока что для STM я делаю всего второй проект и у меня как и у некоторых других складывается впечатление что Keil на совсем правильно работает с памятью МК. Как Вы думаете имеет ли смысл перебросить проект из Keil в IAR? Может ли это реально помочь?

Александр
Александр
Ответ на комментарий  Александр
6 лет назад

Явных ошибок не выдает, но складывается впечатление что если в нескольких программных модулях резервируются массивы памяти то они могут частично накладываться. Т.е. возникают ошибки при сборке проекта. Ф-ия f_mkdir() выдает ошибку FR_DISK_ERR, Но если на флешке предварительно создать (на ПК) нужные папки то в них вполне успешно создаются, пишутся и читаются файлы без ошибок. Heap и Stack увеличил, поставил аж по 0x800.

Александр
Александр
Ответ на комментарий  Александр
6 лет назад

Продолжил я играться со значением "SDIOCLK clock divide factor" и вот до чего доигрался:
1. Если поставить менее 40 то не работает вообще.
2. Если выставить 40 - 45 начинает более менее работать но периодически глючит в частности f_mkdir() не работает.
3. Если выставить в >= 100 работает четко и стабильно НО USB MSD работать отказывается - долго определяет карту и пишет что диск не форматирован.
4. И наконец если выставить 50 - 60 работает нормально и FatFs и USB MSD. Только приходиться ждать лишних 10 с при подключении устройства к ПК.
В варианте 4 то понятно почему дольше, но вот почему в 3. вообще не работает не понятно?
Уж и не знаю почему так, то ли все потому что у меня карта памяти "тормознутая" или же проблема с моим макетом на котором я работаю - плохая разводка. Но вот такой результат. А Keil все равно глючноватый как мне кажется.

Дмитрий
Дмитрий
6 лет назад

Огромное спасибо за хороший материал! Очень помогло!

Салават
Салават
6 лет назад

Добрый день! Собрал проект в кубе на камне stml476vg, но программа зависает в HAL_Init(), попадаю в void HardFault_Handler(void){ }. Но если закомментировать кусок кода:
if(f_mount(&fileSystem, SDPath, 1) == FR_OK)
{
uint8_t path[13] = "testfile.txt";
path[12] = '\0';
res = f_open(&testFile, (char*)path, FA_WRITE |
FA_CREATE_ALWAYS);
res = f_write(&testFile, testBuffer, 16, &testBytes);
res = f_close(&testFile);
}
программа работает нормально.
В чём может быть проблема?

Алексей
Алексей
5 лет назад

Добрый день! Все как всегда у вас по делу и кратко, но от изменений стандартов cube никто не застрахован(
Отсюда и вопрос: У вас есть нека переменная SD_Path в функции f_mount, которая была раньше, видимо, задефайнена или определена в библиотеках куба.
Но в работе с STM32L496 и кубом версии 4.26.1 rкейл её не нашел. Я поставил туда '0', но это не помогло.
Можете, пожалуйста, подсказать, что нужно сделать?

Алексей
Алексей
Ответ на комментарий  Алексей
5 лет назад

Нашел ответ: эту переменную переименовали в SDPath.
Но проблема перешла на другой уровень:
res = f_mount(&SDFatFS, SDPath, 1);
memcpy((uint8_t*)&res_uint32, &res, 4);
if(res == FR_OK)
{
sprintf(path, "testfile.txt");
res = f_open(&testFile, path, FA_WRITE | FA_CREATE_ALWAYS);
memcpy((uint8_t*)&res_uint32, &res, 4);
if (res == FR_OK) {
HAL_Delay(1000);
res = f_write(&testFile, testBuffer, 16, &testBytes);
memcpy((uint8_t*)&res_uint32, &res, 4);
}
res = f_close(&testFile);
res = f_mount(0, "", 0);
}
Все до f_write отрабатывает без ошибок, а в этой функции на строчке res = validate(&fp->obj, &fs); (а в этой функции на первом if) программа падает в void HardFault_Handler(void) (который в stm32l4xx_it.c).
Почему такое происходит - непонятно(

Алексей
Алексей
Ответ на комментарий  Aveal
5 лет назад

Пробовал и так и сяк - получилось только при выставлении дополнительных строчек на открытие и сразу закрытие файла:
if(res == FR_OK)
{
sprintf(path, "1234.txt");
res = f_open(&SDFile, path, FA_WRITE | FA_CREATE_ALWAYS);
HAL_Delay(500);
res = f_close(&SDFile);
res = f_open(&SDFile, path, FA_WRITE | FA_CREATE_ALWAYS);
memcpy((uint8_t*)&res_uint32, &res, 4);
if (res == FR_OK) {
HAL_Delay(1000);
res = f_write(&SDFile, testBuffer, 16, &testBytes);
memcpy((uint8_t*)&res_uint32, &res, 4);
}
else {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET);
}
res = f_close(&SDFile);
res = f_mount(0, "", 0);
}

Вот ссылка на полный проект:
https://yadi.sk/d/6qOM_Q8WC9nqnw

Алексей
Алексей
Ответ на комментарий  Aveal
5 лет назад

В итоге я так и подумал. Заменил частоту на рабочую - выбрал 4 МГц.
Большое спасибо!

108
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x