Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: stm32f373 + flash(at25df081) + fatFs
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
vasilijvs
Добрый день, прошу помочь всех знатоков.
Хочу смонтировать раздел с помощью fatfs, возвращает FR_NO_FILESYSTEM, получается флеш не отформатирована под Fat.
Расскажите, каким образом её отформатировать или как добиться успешного выполнения f_mount()?
Вот здесь fResult получает это значение.
Код
FATFS fatFs;
FRESULT fResult;
      
fResult = f_mount(&fatFs, "0", 1);
skripach
Цитата(vasilijvs @ Feb 17 2016, 17:15) *
получается флеш не отформатирована под Fat.
Расскажите, каким образом её отформатировать или как добиться успешного выполнения f_mount()?

А документацию на сайте разработчика глянуть не судьба?
...там элементарно ведь все.
vasilijvs
Цитата(skripach @ Feb 18 2016, 06:56) *
А документацию на сайте разработчика глянуть не судьба?
...там элементарно ведь все.

А можете ткнуть,куда именно глядеть?
Я отчаялся уже

Цитата(vasilijvs @ Feb 18 2016, 12:01) *
А можете ткнуть,куда именно глядеть?
Я отчаялся уже

Разобрался f_mkfs()
vasilijvs
Появился следующий вопрос.
У меня флешка на 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.
Как быть?
Сергей Борщ
Цитата(vasilijvs @ Feb 19 2016, 11:52) *
Как быть?
Использовать разбиение вашей флешки на блоки размером 4 К. Получится 256 блоков. Разбиение на сектора в вашей флешке используется только для защиты от записи, а для файловой системы сектор - это единица одновременно стираемой памяти. Ваша память позволяет стирать блок размером 4 К. Этот блок и надо делать сектором файловой системы.
vasilijvs
Цитата(Сергей Борщ @ 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;

Что это может быть?
hd44780
Проверьте 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, дабы уберечь систему от непредсказуемости.

Я так думаю sm.gif .
KRS
ЕМНИП в fatfs размер сектора может быть только 512 байт

для файловой системы FTA на stm32 с этой флешкой много возни будет.
надо учитывать что стирается она по 4к, но писать можно по 256 байт...
плюс еще надо бы wear leveling организовать...
skripach
Я бы прослоечку сделал для записи/чтения по 512 байт.
esaulenka
Цитата(KRS @ Feb 19 2016, 22:42) *
ЕМНИП в fatfs размер сектора может быть только 512 байт


http://elm-chan.org/fsw/ff/en/appnote.html
Limits
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.)
vasilijvs
Спасибо,за мнения.

Увеличил _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;
}
hd44780
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;

Т.е. оно не может найти сигнатуру MBR/бут сектора (тот самый 0xAA55). Убедитесь в её наличии.
При необходимости отформатируйте её функцией mkfs (если правильно название вспомнил).

Если честно, я бы пошёл по пути, предложенному skripach - напишите прослойку для эмуляции 512 байтовых секторов.
Может и сложновато будет, зато не придётся перепахивать весь FatFs в поисках очередного капкана.
Да и потом обновлять версии FatFs проще ...
vasilijvs
Всем спасибо за советы, сделал по 512 сектор.
И действительно, получилось смонтировать систему и создать файл.
Но записывать данные в файл всё равно упорно не хочет sad.gif
Заходя в функцию 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) */

Есть идеи как можно полечить?
Почему он не может найти свободный кластер?
skripach
Отложите fatfs, напишите простенький тест для нижнего уровня (чтение\запись по 512) и найдите там все косяки, их там есть.
vasilijvs
Цитата(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;
}
hd44780
Ну надо смотреть, что именно не нравится create_chain ..
Хз. На SD-картах и USB флэшках я такого не видел.
vasilijvs
Цитата(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 */
    }
hd44780
Поглядел Ваш код diskio.c (работа отпустила rolleyes.gif )

flash.readArray(realSector, count * 512, buff);
flash.writeData(realSector + i * 256, sizeof(temp), temp);

1-й аргумент функций - что это?
Выше Вы писали, что тестировали прослойку. Вы тестировали функции diskio.c?
vasilijvs
Цитата(hd44780 @ Mar 3 2016, 20:24) *
Поглядел Ваш код diskio.c (работа отпустила rolleyes.gif )

flash.readArray(realSector, count * 512, buff);
flash.writeData(realSector + i * 256, sizeof(temp), temp);

1-й аргумент функций - что это?
Выше Вы писали, что тестировали прослойку. Вы тестировали функции diskio.c?

Да, их тестировал disk_read(),disk_write()
Это адрес начальный, откуда читать/писать
romas2010
Цитата(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...так же поймете,как форматировать на любой размер

Сложного ничего нет,надо просто включить мозг..
vasilijvs
Цитата(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 вопрос решился, файл создается,а вот данные туда записать не получается
skripach
Цитата(vasilijvs @ Mar 3 2016, 23:41) *
,а вот данные туда записать не получается

Вангую, запись блока затирает лишнее помимо того что нужно записать.
vasilijvs
Цитата(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);
    }
}
aaarrr
Цитата(vasilijvs @ Mar 4 2016, 11:11) *
Чтение 3584 байт, которые после нужных нам 512.

А почему после, если 512 байт могут быть в середине блока 4k?
vasilijvs
Цитата(aaarrr @ Mar 4 2016, 15:21) *
А почему после, если 512 байт могут быть в середине блока 4k?

Потому что указывается адрес стираемого блока, значит они начальные 512.
А то что после,перезаписывается.
aaarrr
Нельзя просто взять и назначить начало блока 4k с какого попало адреса. Он должен быть выравнен по границе 4k.
esaulenka
Влезу с рекламой-не-в-тему.
Есть такая замечательная штука, как 010 editor. Позволяет быстро накидать шаблоны структур, а потом разобрать большой бинарный файл в соответствии с этими структурами.
Как использовать в данном случае:
- читаем спецификацию на FAT
- читаем хелп от этого редактора, пишем соответствующие шаблоны (впрочем, для FAT16 уже есть в комплекте)
- пишем для контроллера функцию, которая позволит сохранить дамп памяти этой датафлеш.
- сидим и смотрим структуру дампа, получается очень наглядно.
vasilijvs
Цитата(aaarrr @ Mar 4 2016, 15:44) *
Нельзя просто взять и назначить начало блока 4k с какого попало адреса. Он должен быть выравнен по границе 4k.

Спасибо большое!
Всё заработало.
Действительно проблема была в выравнивании границ стирания.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.