Перейти к содержанию
    

stm32f373 + flash(at25df081) + fatFs

Добрый день, прошу помочь всех знатоков.

Хочу смонтировать раздел с помощью fatfs, возвращает FR_NO_FILESYSTEM, получается флеш не отформатирована под Fat.

Расскажите, каким образом её отформатировать или как добиться успешного выполнения f_mount()?

Вот здесь fResult получает это значение.

FATFS fatFs;
FRESULT fResult;
      
fResult = f_mount(&fatFs, "0", 1);

Изменено пользователем vasilijvs

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

получается флеш не отформатирована под Fat.

Расскажите, каким образом её отформатировать или как добиться успешного выполнения f_mount()?

А документацию на сайте разработчика глянуть не судьба?

...там элементарно ведь все.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А документацию на сайте разработчика глянуть не судьба?

...там элементарно ведь все.

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

Я отчаялся уже

 

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

Я отчаялся уже

Разобрался f_mkfs()

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Появился следующий вопрос.

У меня флешка на 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.

Как быть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как быть?
Использовать разбиение вашей флешки на блоки размером 4 К. Получится 256 блоков. Разбиение на сектора в вашей флешке используется только для защиты от записи, а для файловой системы сектор - это единица одновременно стираемой памяти. Ваша память позволяет стирать блок размером 4 К. Этот блок и надо делать сектором файловой системы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использовать разбиение вашей флешки на блоки размером 4 К. Получится 256 блоков. Разбиение на сектора в вашей флешке используется только для защиты от записи, а для файловой системы сектор - это единица одновременно стираемой памяти. Ваша память позволяет стирать блок размером 4 К. Этот блок и надо делать сектором файловой системы.

Да,спасибо,сейчас проходит этот момент,но на функции f_open в HardFault падает(

 

Да,спасибо,сейчас проходит этот момент,но на функции f_open в HardFault падает(

Вот в этом куске кода падает, условие не проходит, хотя внутри disk_read всё выполняется и возвращается RES_OK, а обратно управление не возвращается

if (disk_read(fs->drv, fs->win.d8, sector, 1))
    return FR_DISK_ERR;

Что это может быть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Я так думаю :) .

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ЕМНИП в fatfs размер сектора может быть только 512 байт

 

для файловой системы FTA на stm32 с этой флешкой много возни будет.

надо учитывать что стирается она по 4к, но писать можно по 256 байт...

плюс еще надо бы wear leveling организовать...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ЕМНИП в 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.)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо,за мнения.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 проще ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всем спасибо за советы, сделал по 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отложите fatfs, напишите простенький тест для нижнего уровня (чтение\запись по 512) и найдите там все косяки, их там есть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отложите fatfs, напишите простенький тест для нижнего уровня (чтение\запись по 512) и найдите там все косяки, их там есть.

Написал, попробывал, читаю/пишу, всё корректно, но та же проблема.

 

Привожу полный код diskio.cpp

#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
[codebox] для длинного кода, [code] - для короткого!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...