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

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

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

Ars
Ars
10 лет назад

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

MikeNT
MikeNT
10 лет назад

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

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

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

Roman
Roman
10 лет назад

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

Roman
Roman
10 лет назад

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

Roman
Roman
10 лет назад

Монтирует, но не открывает файл и не создает (пробовал с уже созданным). Делитель увеличивал. А какая формула вычисления делителя, что делится на 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
10 лет назад

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

Alexey
Alexey
10 лет назад

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

Sergey
Sergey
10 лет назад

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

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

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

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

Да, у меня все получилось и по 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
9 лет назад

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

Sergey
Sergey
10 лет назад

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

Sergey
Sergey
10 лет назад

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

Sergey
Sergey
10 лет назад

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

Sergey
Sergey
10 лет назад

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

Sergey
Sergey
10 лет назад

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

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

У меня в связке 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.

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

Тоже столкнулся с такой проблемой, а решение оказалось простым. Надо всего лишь перед записью или чтением блока надо узнавать текущее состояние карты:
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); // Выводим в терминал считанный блок (до первого нуля) в виде текста
}

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

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

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

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

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

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

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

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

RiseOfDeath
RiseOfDeath
10 лет назад

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

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

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

RiseOfDeath
RiseOfDeath
10 лет назад

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

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

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

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

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

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

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

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

Я по началу тоже долбался. Но потом увидел, что 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

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

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

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

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

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

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

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

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

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

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

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 всё заработало!

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

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

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

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;
Тут я пробовал прочитать с записью в массив по указателю и без него. все равно ничего на получается.
Красный, зеленый, желтый диоды включаются, когда пошагово отлаживаю, а синий нет.
Подскажите плииииз, в чем дело, почему не читается?
Спасибо заранее всем, кто ответит.

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

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

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

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

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

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

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

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

v1
v1
9 лет назад

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

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

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

Kinobi
Kinobi
9 лет назад

Пытаюсь подключить 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
9 лет назад

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

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

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

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

Aleksey
Aleksey
9 лет назад

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

dim
dim
9 лет назад

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

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

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

Aleksey
Aleksey
9 лет назад

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

Dimaster
9 лет назад

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

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

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

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

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

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

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

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

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

Спасибо.

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

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

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

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

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

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

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

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

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

Продолжил я играться со значением "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 все равно глючноватый как мне кажется.

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

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

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

Добрый день! Собрал проект в кубе на камне 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);
}
программа работает нормально.
В чём может быть проблема?

Никита
Никита
Ответ на комментарий  Aveal
1 год назад

Добрый день, столкнулся с такой же проблемой, хотел узнать есть ли решение?

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

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

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

Нашел ответ: эту переменную переименовали в 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
7 лет назад

Пробовал и так и сяк - получилось только при выставлении дополнительных строчек на открытие и сразу закрытие файла:
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
7 лет назад

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

110
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
Обзор конфиденциальности

На этом сайте используются файлы cookie, что позволяет нам обеспечить наилучшее качество обслуживания пользователей. Информация о файлах cookie хранится в вашем браузере и выполняет такие функции, как распознавание вас при возвращении на наш сайт и помощь нашей команде в понимании того, какие разделы сайта вы считаете наиболее интересными и полезными.