|
stm32f373 + flash(at25df081) + fatFs |
|
|
|
Feb 17 2016, 14:15
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Добрый день, прошу помочь всех знатоков. Хочу смонтировать раздел с помощью fatfs, возвращает FR_NO_FILESYSTEM, получается флеш не отформатирована под Fat. Расскажите, каким образом её отформатировать или как добиться успешного выполнения f_mount()? Вот здесь fResult получает это значение. Код FATFS fatFs; FRESULT fResult; fResult = f_mount(&fatFs, "0", 1);
Сообщение отредактировал vasilijvs - Feb 17 2016, 14:15
|
|
|
|
|
Feb 18 2016, 03:56
|
■ ■ ■ ■
    
Группа: Свой
Сообщений: 1 100
Регистрация: 9-08-06
Пользователь №: 19 443

|
Цитата(vasilijvs @ Feb 17 2016, 17:15)  получается флеш не отформатирована под Fat. Расскажите, каким образом её отформатировать или как добиться успешного выполнения f_mount()? А документацию на сайте разработчика глянуть не судьба? ...там элементарно ведь все.
--------------------
Делай что должен и будь что будет.
|
|
|
|
|
Feb 18 2016, 09:45
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(skripach @ Feb 18 2016, 06:56)  А документацию на сайте разработчика глянуть не судьба? ...там элементарно ведь все. А можете ткнуть,куда именно глядеть? Я отчаялся уже Цитата(vasilijvs @ Feb 18 2016, 12:01)  А можете ткнуть,куда именно глядеть? Я отчаялся уже Разобрался f_mkfs()
|
|
|
|
|
Feb 19 2016, 09:52
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Появился следующий вопрос. У меня флешка на 1 Мбайт, имеет 16 секторов по 64 Кбайта. В функции f_mkfs, есть следующий код, который возвращает FR_DISK_ERR и не дает успешно завершить это функцию. Код /* Create a partition in this function */ if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) return FR_DISK_ERR; Как раз не проходит по второму условию, т.к. количество секторов на моей флешке 16. Как быть?
|
|
|
|
|
Feb 19 2016, 10:48
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(Сергей Борщ @ Feb 19 2016, 12:58)  Использовать разбиение вашей флешки на блоки размером 4 К. Получится 256 блоков. Разбиение на сектора в вашей флешке используется только для защиты от записи, а для файловой системы сектор - это единица одновременно стираемой памяти. Ваша память позволяет стирать блок размером 4 К. Этот блок и надо делать сектором файловой системы. Да,спасибо,сейчас проходит этот момент,но на функции f_open в HardFault падает( Цитата(vasilijvs @ Feb 19 2016, 13:25)  Да,спасибо,сейчас проходит этот момент,но на функции f_open в HardFault падает( Вот в этом куске кода падает, условие не проходит, хотя внутри disk_read всё выполняется и возвращается RES_OK, а обратно управление не возвращается Код if (disk_read(fs->drv, fs->win.d8, sector, 1)) return FR_DISK_ERR; Что это может быть?
|
|
|
|
|
Feb 19 2016, 18:05
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Проверьте FаtFs на предмет размера сектора. Может он где-то считает, что у Вас 512 байт по стандарту. по поводу disk_read. disk_read(fs->drv, fs->win.d8, sector, 1)) - что такое fs->win.d8? как я понимаю, это вот это: Код ................ DWORD database; /* Data start sector */ DWORD winsect; /* Current sector appearing in the win[] */ BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ } FATFS; где тут d8? И чему равен _MAX_SS? По дефолту он равен 512. Если Вы сделали сектор в 4К, то и сюда пишите 4096. И если у Вас disk_read даже не возвращается, а улетает в космос под названием HardFault - то cкорее всего Вы где-то внутри этой функции портите память, в частности, стек, где хранися адрес возврата. При возврате проц пытается перейти по адресу из стека, но там явно какая-то чепуха. Оно это дело просекает и уходит в HardFault, дабы уберечь систему от непредсказуемости. Я так думаю  .
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Feb 20 2016, 09:41
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(KRS @ Feb 19 2016, 22:42)  ЕМНИП в fatfs размер сектора может быть только 512 байт http://elm-chan.org/fsw/ff/en/appnote.htmlLimits FAT sub-types: FAT12, FAT16 and FAT32. Number of open files: Unlimited. (depends on available memory) Number of volumes: Upto 10. File size: Upto 4G-1 bytes. (by FAT specs.) Volume size: Upto 2T bytes at 512 bytes/sector. (by FAT specs.) Cluster size: Upto 64K bytes at 512 bytes/sector. (by FAT specs.) Sector size: 512, 1024, 2048 and 4096 bytes. (by FAT specs.)
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Feb 25 2016, 13:50
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Спасибо,за мнения. Увеличил _MAX_SS, в HardFault уже не падает. Следующая функция check_fs() вызывается в find_volume() и возвращает значение 2 из-за которого в функции f_open() возвращается FR_NO_FILESYSTEM. Что ещё можно сделать? Все функции чтения, записи реализованы, что может быть не так? Код static BYTE check_fs ( /* 0:FAT boor sector, 1:Valid boor sector but not FAT, 2:Not a boot sector, 3:Disk error */ FATFS* fs, /* File system object */ DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ ) { fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ if (move_window(fs, sect) != FR_OK) /* Load boot record */ return 3;
if (LD_WORD(&fs->win.d8[BS_55AA]) != 0xAA55) /* Check boot record signature (always placed at offset 510 even if the sector size is >512) */ return 2;
if ((LD_DWORD(&fs->win.d8[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ return 0; if ((LD_DWORD(&fs->win.d8[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ return 0;
return 1; }
Сообщение отредактировал vasilijvs - Feb 25 2016, 13:50
|
|
|
|
|
Mar 1 2016, 12:34
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Всем спасибо за советы, сделал по 512 сектор. И действительно, получилось смонтировать систему и создать файл. Но записывать данные в файл всё равно упорно не хочет Заходя в функцию f_write(), в первой строке пытается выбрать новый кластер, а следом вылетает из функции. Код fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */
if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ Есть идеи как можно полечить? Почему он не может найти свободный кластер?
Сообщение отредактировал vasilijvs - Mar 1 2016, 12:35
|
|
|
|
|
Mar 3 2016, 09:42
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(skripach @ Mar 1 2016, 21:19)  Отложите fatfs, напишите простенький тест для нижнего уровня (чтение\запись по 512) и найдите там все косяки, их там есть. Написал, попробывал, читаю/пишу, всё корректно, но та же проблема. Привожу полный код diskio.cpp CODE #include "diskio.h" #include "ff_gen_drv.h" #include "flash.h" #include "spi.h"
extern Disk_drvTypeDef disk; extern Spi spi(GPIO_PIN_10, GPIO_PIN_11, GPIO_PIN_12, GPIO_PIN_2); extern Flash flash(spi);
/** * @brief Initializes a Drive * @param pdrv: Physical drive number (0..) * @retval DSTATUS: Operation status */ DSTATUS disk_initialize(BYTE pdrv) { DSTATUS stat = RES_OK; if(disk.is_initialized[pdrv] == 0) { disk.is_initialized[pdrv] = 1; stat = disk.drv[pdrv]->disk_initialize(); } return stat; }
/** * @brief Gets Disk Status * @param pdrv: Physical drive number (0..) * @retval DSTATUS: Operation status */ DSTATUS disk_status(BYTE pdrv) { DSTATUS stat; stat = disk.drv[pdrv]->disk_status(); return stat; }
/** * @brief Reads Sector(s) * @param pdrv: Physical drive number (0..) * @param *buff: Data buffer to store read data * @param sector: Sector address (LBA) * @param count: Number of sectors to read (1..128) * @retval DRESULT: Operation result */ DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, BYTE count) { DWORD realSector = sector * 512; flash.readArray(realSector, count * 512, buff); return RES_OK; }
/** * @brief Writes Sector(s) * @param pdrv: Physical drive number (0..) * @param *buff: Data to be written * @param sector: Sector address (LBA) * @param count: Number of sectors to write (1..128) * @retval DRESULT: Operation result */ #if _USE_WRITE == 1 DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, BYTE count) { DWORD realSector = sector * 512;
for (int i = 0; i < count; ++i) { flash.eraseBlock512(realSector + i * 512); } for(int i = 0; i < (count * 2); ++i) { uint8_t temp[256]; for(int j = 0; j < sizeof(temp); ++j) { temp[j] = buff[i * 256 + j]; } flash.writeData(realSector + i * 256, sizeof(temp), temp); } return RES_OK; } #endif /* _USE_WRITE == 1 */
/** * @brief I/O control operation * @param pdrv: Physical drive number (0..) * @param cmd: Control code * @param *buff: Buffer to send/receive control data * @retval DRESULT: Operation result */ #if _USE_IOCTL == 1 DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) { DRESULT res = RES_ERROR; switch (cmd) { case CTRL_SYNC: res = RES_OK; break; case GET_SECTOR_COUNT: *(DWORD*)buff = 2048; res = RES_OK; break; case GET_SECTOR_SIZE: *(DWORD*)buff = 512; res = RES_OK; break; case GET_BLOCK_SIZE: *(DWORD*)buff = 512; res = RES_OK; break; } return res; } #endif /* _USE_IOCTL == 1 */
/** * @brief Gets Time from RTC * @param None * @retval Time in DWORD */ DWORD get_fattime (void) { return 0; }
Сообщение отредактировал IgorKossak - Mar 4 2016, 13:24
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Mar 3 2016, 16:40
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(hd44780 @ Mar 3 2016, 16:39)  Ну надо смотреть, что именно не нравится create_chain .. Хз. На SD-картах и USB флэшках я такого не видел. Вылетает в первом return 0, после того как в цикле побегает. Код ncl = scl; /* Start cluster */ for (;;) { ncl++; /* Next cluster */ if (ncl >= fs->n_fatent) { /* Wrap around */ ncl = 2; if (ncl > scl) return 0; /* No free cluster */ } cs = get_fat(fs, ncl); /* Get the cluster status */ if (cs == 0) break; /* Found a free cluster */ if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ return cs; if (ncl == scl) return 0; /* No free cluster */ }
|
|
|
|
|
Mar 3 2016, 17:24
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Поглядел Ваш код diskio.c (работа отпустила  ) flash.readArray(realSector, count * 512, buff); flash.writeData(realSector + i * 256, sizeof(temp), temp); 1-й аргумент функций - что это? Выше Вы писали, что тестировали прослойку. Вы тестировали функции diskio.c?
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Mar 3 2016, 17:46
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(hd44780 @ Mar 3 2016, 20:24)  Поглядел Ваш код diskio.c (работа отпустила  ) flash.readArray(realSector, count * 512, buff); flash.writeData(realSector + i * 256, sizeof(temp), temp); 1-й аргумент функций - что это? Выше Вы писали, что тестировали прослойку. Вы тестировали функции diskio.c? Да, их тестировал disk_read(),disk_write() Это адрес начальный, откуда читать/писать
|
|
|
|
|
Mar 3 2016, 18:23
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 25-11-11
Пользователь №: 68 515

|
Цитата(vasilijvs @ Feb 17 2016, 17:15)  Добрый день, прошу помочь всех знатоков. ........ fResult = f_mount(&fatFs, "0", 1) ну как я вот подошел к этому 1) в Яндексе набираем "FAT32 MBR" "FAT32 boot record" "FAt32 описание"...изучаем структуры boot record, partition table и собственно самой FAT 2) форматируем в Windows флэшку,скачиваем программу посекторного чтения http://electronix.ru/forum/index.php?act=a...st&id=97074 (пост http://electronix.ru/forum/index.php?showt...1337) копируем на флэшку файлы,смотрим программой что куда записалось,анализируем цепочку FAT,в общем исследуем,что делает Windows с флэшкой 3) Пишем низкоуровневый драйвер,публикующий функции посекторного чтения-записи,читаем даташиты на микросхемы памяти,sd-card и прочее..кстати для эмуляции можно использовать ОЗУ микроконтроллера,сектора там организовать 4) ну и далее пристегиваем товарища Чэна(или Чана) ,если не удалось или лень,пишем свое детище на основе нюансов,изученных в п.2...так же поймете,как форматировать на любой размер Сложного ничего нет,надо просто включить мозг..
Сообщение отредактировал romas2010 - Mar 3 2016, 18:27
|
|
|
|
|
Mar 3 2016, 20:41
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(romas2010 @ Mar 3 2016, 21:23)  ну как я вот подошел к этому 1) в Яндексе набираем "FAT32 MBR" "FAT32 boot record" "FAt32 описание"...изучаем структуры boot record, partition table и собственно самой FAT 2) форматируем в Windows флэшку,скачиваем программу посекторного чтения http://electronix.ru/forum/index.php?act=a...st&id=97074 (пост http://electronix.ru/forum/index.php?showt...1337) копируем на флэшку файлы,смотрим программой что куда записалось,анализируем цепочку FAT,в общем исследуем,что делает Windows с флэшкой 3) Пишем низкоуровневый драйвер,публикующий функции посекторного чтения-записи,читаем даташиты на микросхемы памяти,sd-card и прочее..кстати для эмуляции можно использовать ОЗУ микроконтроллера,сектора там организовать 4) ну и далее пристегиваем товарища Чэна(или Чана) ,если не удалось или лень,пишем свое детище на основе нюансов,изученных в п.2...так же поймете,как форматировать на любой размер Сложного ничего нет,надо просто включить мозг.. Да в том и дело, что всё уже проанализировал. Читается/пишется всё как надо. С f_mount вопрос решился, файл создается,а вот данные туда записать не получается
Сообщение отредактировал vasilijvs - Mar 3 2016, 20:42
|
|
|
|
|
Mar 4 2016, 08:11
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(skripach @ Mar 4 2016, 02:04)  Вангую, запись блока затирает лишнее помимо того что нужно записать. Вот как все происходит. Чтение 3584 байт, которые после нужных нам 512. Стирание 4096. Запись оставшихся 3584 с начального адреса + 512. Код void Flash::eraseBlock512(uint32_t address) { uint8_t source[7 * 512]; readArray(address + 512, sizeof(source), source); eraseBlock(address, Block4k); uint8_t temp[256]; for(int i = 0; i < 14; ++i) { for(int j = 0; j < sizeof(temp); ++j) { temp[j] = source[i * 256 + j]; } writeData(address + 512 + i * 256, sizeof(temp), temp); } }
|
|
|
|
|
Mar 4 2016, 12:32
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(aaarrr @ Mar 4 2016, 15:21)  А почему после, если 512 байт могут быть в середине блока 4k? Потому что указывается адрес стираемого блока, значит они начальные 512. А то что после,перезаписывается.
Сообщение отредактировал vasilijvs - Mar 4 2016, 12:34
|
|
|
|
|
Mar 10 2016, 14:15
|
Группа: Участник
Сообщений: 13
Регистрация: 17-02-16
Пользователь №: 90 493

|
Цитата(aaarrr @ Mar 4 2016, 15:44)  Нельзя просто взять и назначить начало блока 4k с какого попало адреса. Он должен быть выравнен по границе 4k. Спасибо большое! Всё заработало. Действительно проблема была в выравнивании границ стирания.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|