littlefs-project / littlefs

A little fail-safe filesystem designed for microcontrollers
BSD 3-Clause "New" or "Revised" License
5.12k stars 790 forks source link

STM32F103 corrupted dir pair #847

Open dryet opened 1 year ago

dryet commented 1 year ago

Hello,

I am using W25Qxx library with littlefs. My specific chip is Winbond W25Q80DVNIG and STM32F103C8T6

My config is: `const struct lfs_config cfg = { // block device operations .read = user_provided_block_device_read, .prog = user_provided_block_device_prog, .erase = user_provided_block_device_erase, .sync = user_provided_block_device_sync,

    // block device configuration
    .read_size = 256,
    .prog_size = 256,
    .block_size = 4096,
    .block_count = 256,
    .cache_size = 256,
    .lookahead_size = 128,
    .block_cycles = 500, };`

My fuction to write and read are: `int user_provided_block_device_read(const struct lfs_config c, lfs_block_t block, lfs_off_t off, void buffer, lfs_size_t size) {

W25qxx_ReadPage((uint8_t*) buffer, block * c->block_size, off, size);
return 0;

}

int user_provided_block_device_prog(const struct lfs_config c, lfs_block_t block, lfs_off_t off, const void buffer, lfs_size_t size) {

W25qxx_WritePage((uint8_t*) buffer, block * c->block_size, off, size);
return 0;

}

int user_provided_block_device_erase(const struct lfs_config *c, lfs_block_t block) {

W25qxx_EraseSector(block * c->block_size);
return 0;

}

int user_provided_block_device_sync(const struct lfs_config *c) { return 0; }`

I am using the littlefs demo as a program. But when running i get only this error in console and STM32 triggers a HardFault: ../Core/Src/lfs.c:1299:error: Corrupted dir pair at {0x0, 0x1}<\n>

When looking for a fix I couldn't find a real answer. Has anyone fixed this issue or do you know where could be my problem? Thank you so much.

mipinko commented 1 year ago

I think I've had a similar problem. You might want to change your read_size and prog_size to be the same size as the buffer/register in memory you are interfacing with. Looking at your parameters I think you have the wrong values for the block size and count, as in the datasheet it states that one block is 64KB divided into 16 sectors 4KB each, hence I would try to increase read_size and prog_size to 4KB and block_size to 64KB (you can erase only the whole 64KB block).

For example, I was interfacing a 125Mbyte W25N01 memory. Here's my lfs config:

const struct lfs_config cfg = {
    // block device operations
    .read  = block_device_read,
    .prog  = block_device_prog,
    .erase = block_device_erase,
    .sync  = block_device_sync,

    // block device configuration
    .read_size = 2048,
    .prog_size = 2048,
    .block_size = 131072,
    .block_count = 1024,
    .cache_size = 2048,
    .lookahead_size = 16,
    .block_cycles = 500,
};

And block device functions:

/*   LittleFS <---> STM32 HAL glue functions    */
int block_device_read(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size)
{

    if(!W25N01_PageDataRead(block*64 + off))return LFS_ERR_IO;
    if(!W25N01_ReadData(0, buffer, size))return LFS_ERR_IO;
    return 0;
}

int block_device_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
{
    if(!W25N01_RandomLoadProgramData(0, (uint8_t*)buffer, size))return LFS_ERR_IO;
    if(!W25N01_ProgramExecute(block*64 + off))return LFS_ERR_IO;
    return LFS_ERR_OK;
}

int block_device_erase(const struct lfs_config *c, lfs_block_t block)
{
    if(!W25N01_BlockErase(block*64))return LFS_ERR_IO;
    return LFS_ERR_OK;
}

int block_device_sync(const struct lfs_config *c)
{
    return 0;
}

Please note that I am not using c->block_size as a scale factor for the block index because it would not be correct. Instead, I refer to the size of the block in pages(sectors in your case). One read/write is the size of a page (2KB) and there are 64 pages in one block.

dryet commented 1 year ago

@mipinko Thank you so much for your answer. You are right about the block and sector size. So i changed them to this: `const struct lfs_config cfg = { // block device operations .read = user_provided_block_device_read, .prog = user_provided_block_device_prog, .erase = user_provided_block_device_erase, .sync = user_provided_block_device_sync,

    // block device configuration
    .read_size = 4096,
    .prog_size = 4096,
    .block_size = 65536,
    .block_count = 16,
    .cache_size = 4096,
    .lookahead_size = 128,
    .block_cycles = 500, };`

But the error stays the same. I know the driver is working because I have seen other people use it without issues. Could there be a problem somewhere else?

BilibiliW commented 1 year ago

Hi, The same thing happened to me recently. The error occurred when I mount the w25q64, I got err info like this: lfs.c:1070:error: Corrupted dir pair at {0x0, 0x1} I've try many ways, but it did't work. Just now, I see the official routine comment said "reformat if we can't mount the filesystem, this should only happen on the first boot", then I ues lfs_format interface after mount faild, and remount it, finally it works. this littleFS version is 2.4.1, memory chip is W25Q64,config like this:

        cfg_w25q.read_size      = 16;
    cfg_w25q.prog_size      = 16;
    cfg_w25q.block_count    = 128;
    cfg_w25q.block_size     = 4096;
    cfg_w25q.cache_size     = 16;
    cfg_w25q.lookahead_size = 16;       //bitmap
    cfg_w25q.block_cycles   = 500;              //wear leveling
    cfg_w25q.read           = w25qxxRead;
    cfg_w25q.erase          = w25qxxErase;
    cfg_w25q.prog           = w25qxxWrite;
    cfg_w25q.sync           = w25qxxSync;

if your error is occurs in first mount, you can try my method. stm32 triggers a HardFault maybe other issue like memory leak or addr error, please check you driver and parameter.

The undefined printf function will also cause some abnormal problems:

#ifndef LFS_ERROR
#ifndef LFS_NO_ERROR
#define LFS_ERROR_(fmt, ...) \
    printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
#else
#define LFS_ERROR(...)
#endif
#endif
dryet commented 1 year ago

@BilibiliW Thank you for your answer. I have added the reformating and you were right. It is now throwing a HardFault when I debug. My STM32F103C8 seems to end on the address 0x20005000. I will investigate this issue later. This was all done on my custom STM32 board. I will test little fs on an official STM32 board in 2 weeks and I will try to fix this issue by eliminating my potetial errors in design or it also might be a fake STM32F103C8.

BrianPugh commented 12 months ago

This may or may not be relevant, but in my stm32h7b0 project, I had to be careful around the dcache.