littlefs-project / littlefs

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

How to port LFS to any flash memory? #448

Open barani143 opened 4 years ago

barani143 commented 4 years ago

Hi all,

I am new to LFS and trying to understand the design. The main question that arises to me is how to port LFS to any flash memory. I couldn't able to find any guidance where we can port the LFS. For porting the LFS what are the dependency required and what are the functions that need to be modified during porting. I having read/write functions that will be used to write and read flash memory and how I will invoke those functions in LFS.

Thanks

barani143 commented 4 years ago

Can anyone point to the right path and how to move forward for porting the littlefs to a flash memory.

geky commented 4 years ago

Hi @barani143, porting documentation is one area that needs work, so the best I can do is point you to code comments.

The entry point to littlefs is lfs_mount and lfs_format which take in a struct lfs_config. This struct contains function pointers that tell littlefs which functions to call for the specific block device operations.

Currently these are more-or-less documented here: https://github.com/ARMmbed/littlefs/blob/master/lfs.h#L150-L243

As for dependencies, littlefs is fairly self contained. At worst you may have to modify lfs_util.h if you have a special compiler/architecture: https://github.com/ARMmbed/littlefs/blob/master/lfs_util.h

barani143 commented 4 years ago

Hi geky, Thanks for the reply. There are couple of queries from the lfs_config structure

  1. Function pointers in the config structure for read, program, erase and sync where I can register my flash read, write, erase and sync function during initialization. Is my understanding is correct?

For example:(Please correct me if I was wrong) // Low-level driver function will be like as below: void FlashRead( uint32_t address, void *buffer, uint32_t length )

// Wrapper for flash read and lfs read function: void LfsFlashBlockRead( const struct lfs_config cfg, lfs_block_t block, lfs_off_t off, void buffer, lfs_size_t size) { // off - whether it can be a base address or not // cfg->block_size - block_size will be configured during lfs_int is correct. eg:- If allocating 4KB of total block then during // intialization time it will block_size = 4096 // Based upon the value of block whether the data will be read from specific address or can guide me what exactly block // parameter does

  FlashRead( (block * cfg->block_size + off), (uint32_t*)buffer, size );

}

// So lfs_init is like below: lfs_config config; void lfs_init( void ) { config.read = LfsFlashBlockRead; config.write = LfsFlashBlockWrite; config.erase = LfsFlashBlockErase; config.sync = LfsFlashBlockSync;

// From comment read_size is minimum size of block read. 
// So if I configure to 32 then it will read 32 byte as a minimum to flash
 config.read_size =  32;     

// From comment prog_size is the minimum size of block read. 
// So if I configure to 32 then it will write 32 bytes as a minimum to flash.
 config.prog_size =  32;   

// How block_size differ from block_count ?

}

  1. For porting only littefs only lfs.c, lfs_util.c, lfs.h and lfs_util.h these files need to be added in my project or any other file I have to add.
  2. If I modify the lfs by the above step 1 whether it work directly or apart from this is there anything required to be modified to work.

Thanks

geky commented 4 years ago

Function pointers in the config structure for read, program, erase and sync where I can register my flash read, write, erase and sync function during initialization. Is my understanding is correct?

Yes, struct lfs_config is required in lfs_mount and lfs_format, which need to be called before any other filesystem operation.

// From comment read_size is minimum size of block read. // So if I configure to 32 then it will read 32 byte as a minimum to flash

Yes. One note is that littlefs may call read with a multiple of the read_size. So it may call with 64 or 96, but the offset will be aligned to 32-bytes and will never be less than 32-bytes.

For porting only littefs only lfs.c, lfs_util.c, lfs.h and lfs_util.h these files need to be added in my project or any other file I have to add.

Just lfs.h, lfs.c, lfs_util.h, and lfs_util.c.

If I modify the lfs by the above step 1 whether it work directly or apart from this is there anything required to be modified to work.

You will also need to set the other members of the config struct. The readme has a minimal configuration:

// configuration of the filesystem is provided by this struct
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 = 16,
    .prog_size = 16,
    .block_size = 4096,
    .block_count = 128,
    .cache_size = 16,
    .lookahead_size = 16,
    .block_cycles = 500,
};
barani143 commented 4 years ago

Hi geky,

Thanks for the support and quick reply. I have a few more queries over the configuration. Below are in details

  1. How the block_size differ from block_count?
  2. I have done the configuration as same as the README.md and testing in the same way but while mounting getting an error and enter to the failure condition with error code -84.

Below are my configuration:

lfs_t lfs; lfs_file_t file; lfs_config config;

// For read int block_read( const struct lfs_config c, lfs_block_t block, lfs_off_t off, void buffer, lfs_size_t size ) { int read_err; read_err = FlashRead( blockc->block_size + off + BASE_ADDRESS, (uint32_t)buffer, size ); // BASE_ADDRESS = File system starting address in flash memory return read_err; }

// For Write int block_prog( const struct lfs_config c, lfs_block_t block, lfs_off_t off, void buffer, lfs_size_t size ) { int write_err; write_err = FlashWrite( blockc->block_size + off + BASE_ADDRESS, (uint32_t)buffer, size ); // BASE_ADDRESS = File system starting address in flash memory return write_err; }

// For erase int block_erase( const struct lfs_config c, lfs_block_t block ) { int erase_err; erase_err = FlashErase( blockc->block_size + off + BASE_ADDRESS, (uint32_t*)(0xFFFFFFFF), BLOCK_SIZE ); // BASE_ADDRESS = File system starting address in flash memory return erase_err; }

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

void test_lfs_init() { config.read = block_read; config.prog = block_prog; config.erase = block_erase; config.sync = block_sync;

config.read_size = 16,
config.prog_size = 16,
config.block_size = 4096,
// How value 128 came?
config.block_count = 128,       
config.cache_size = 16,
config.lookahead_size = 16,
config.block_cycles = 500,

lfs_mount( &lfs, &config );     // Getting error here itself
lfs_format( &lfs, &config );

}

int main( void ) { test_lfs_init();

// read current count
uint32_t boot_count = 0;
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));

// update boot count
boot_count += 1;
lfs_file_rewind(&lfs, &file);
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));

// remember the storage is not updated until the file is closed successfully
lfs_file_close(&lfs, &file);

// release any resources we were using
lfs_unmount(&lfs);

// print the boot count
printf("boot_count: %d\n", boot_count);

}

I have also tried by changing the configuration by getting an error while mounting.

Thanks

barani143 commented 4 years ago

Can anyone point to the right path and what is happing in my configuration?. Always getting -84 error and also tried to re-mount after the failure but error.

geky commented 4 years ago

block_count = size of disk / block_size

So if the size of your flash is 4MiB and your block_size = 4096, block_count = 4*1024*1024 / 4096, or block_count = 1024.

I have done the configuration as same as the README.md and testing in the same way but while mounting getting an error and enter to the failure condition with error code -84.

I'm not sure why. Your code looks correct (block * c->block_size + off + BASE_ADDRESS is correct).

-84 (LFS_ERR_CORRUPT) most likely means that a write did not work.

Have you tried writing and reading some raw data to the flash to see if the functions work?

(uint32_t*)(0xFFFFFFFF)

This part also looks suspicious but I don't know the FlashErase API. Should it be &(uint32_t)(0xFFFFFFFF)?

barani143 commented 4 years ago

Hi geky,

Still, I am facing the same problem and it returning -84 while doing lfs_mount and -28 while doing lfs_format. I have checked the raw read/write functions and works fine. Is littlefs has any flash size dependency whether it work with minimum flash ( less than 100KB i.e 32KB). To debug the problem I have built the lfs in the GCC by creating a virtual flash memory as shown below:

include

include "lfs/lfs.h"

include "lfs/lfs_util.h"

define ONE_KB ( 1024 )

define PAGE_NUM ( 32 )

define FLASH_SIZE ( PAGE_NUM * ONE_KB )

unsigned char VirutalFlash[FLASH_SIZE];

int FlashWrite( unsigned int address, unsigned char *data, unsigned int length ) { //unsigned int count = length >>2; unsigned int count = length;

/** check the length initialize or not */
if(length == 0)
{
    printf("LENGTH_FAIL\n");
    return -1;
}

printf("Write Count: %d\n", count);

 while(count)  
 {
    VirutalFlash[address] = *data;
    printf("W_ADD: 0x%X W_Data: 0x%X VirutalFlash: 0x%X\n", address, *data, VirutalFlash[address]);
    //address += 4;
    address += 1;
    count--;
 }

return 0;

}

int FlashRead( unsigned int address, unsigned char *data, unsigned int length ) { //unsigned int count = length >> 2; unsigned int count = length;

if((length == 0) || (data == NULL))
{
    return -1;
}

printf("Read Count: %d\n", count);

while (count) {

    printf("R_ADD: 0x%X R_Data: 0x%X VirutalFlash: 0x%X\n", address, *data, VirutalFlash[address]);
    *data = VirutalFlash[address];
     data++;
     //address += 4;
     address += 1;
     count--;
}

return 0;

}

int block_read( const struct lfs_config c, lfs_block_t block, lfs_off_t off, void buffer, lfs_size_t size ) { int r_status; r_status = FlashRead( (block c->block_size + off), (unsigned char)(buffer), size); return r_status; }

int block_prog( const struct lfs_config c, lfs_block_t block, lfs_off_t off, const void buffer, lfs_size_t size ) { int w_status; w_status = FlashWrite( (block c->block_size + off), (unsigned char)(buffer), size); return w_status;
}

int block_erase( const struct lfs_config c, lfs_block_t block ) { int e_status; unsigned char data_buf[1024]; memset( &data_buf[0], 0x00, 1024 ); e_status = FlashWrite( (block c->block_size), &data_buf[0], 1024); return e_status;
}

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

// variables used by the filesystem lfs_t lfs; lfs_file_t file;

// configuration of the filesystem is provided by this struct const struct lfs_config cfg = { // block device operations .read = block_read, .prog = block_prog, .erase = block_erase, .sync = block_sync,

// block device configuration
.read_size = 16,
.prog_size = 16,
.block_size = 1024,
.block_count = 32,
.cache_size = 16,
.lookahead_size = 16,
.block_cycles = 500,

};

int main(int argc, char **argv) { memset( &VirutalFlash[0], 0xFFFFFFFF, FLASH_SIZE );

int err1 = lfs_format(&lfs, &cfg);

// mount the filesystem
int err = lfs_mount(&lfs, &cfg);

// reformat if we can't mount the filesystem
// this should only happen on the first boot
if (err) {
    lfs_format(&lfs, &cfg);
    lfs_mount(&lfs, &cfg);
}

// read current count
uint32_t boot_count = 0;
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));

// update boot count
boot_count += 1;
lfs_file_rewind(&lfs, &file);
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));

// remember the storage is not updated until the file is closed successfully
lfs_file_close(&lfs, &file);

// release any resources we were using
lfs_unmount(&lfs);

// print the boot count
printf("boot_count: %d\n", boot_count);

return 0;

} But this also not working. Is my configuration is correct? Can you guide me what can be the problem to receive -84, 28 error code .

Change in lfs_util.h file:

define LFS_NO_ASSERT

define LFS_YES_TRACE

Thanks

barani143 commented 4 years ago

Can anyone help me out what mistake I am doing in code and I don't know why I am always getting -28 on lfs_format and -84 on lfs_mount functions.

e107steved commented 4 years ago

You have some "void buffer" references which should probably be "void buffer", and then typecast to (unsigned char ) before you use them.

barani143 commented 4 years ago

Hi e107steved, I have done some typing error. Thanks for that note. Actually I am using int block_read( const struct lfs_config c, lfs_block_t block, lfs_off_t off, void buffer, lfs_size_t size ) { int r_status; r_status = FlashRead( (block c->block_size + off), (unsigned char )(buffer), size); return r_status; }

int block_prog( const struct lfs_config c, lfs_block_t block, lfs_off_t off, const void buffer, lfs_size_t size ) { int w_status; w_status = FlashWrite( (block c->block_size + off), (unsigned char )(buffer), size); return w_status; }

int block_erase( const struct lfs_config c, lfs_block_t block ) { int e_status; unsigned char data_buf[1024]; memset( &data_buf[0], 0x00, 1024 ); e_status = FlashWrite( (block c->block_size), &data_buf[0], 1024); return e_status; }

But I am getting the same problem. Can anyone help me out to overcome this issue. In the simualtion itself it is not working and getting the error -28 and -84. I don't know what is going wrong.

Thanks

barani143 commented 4 years ago

Can anyone help me out to overcome this issue.

barani143 commented 4 years ago

I found an issue #306 reported already for the simulation test suite. I have tried that also and getting an error -84. I don't what is happing and can anyone help me to overcome this issue.

barani143 commented 4 years ago

Is there anything I am doing wrong while porting lfs. Can anyone help me out and point the right path what going wrong?

eddyv19 commented 3 years ago

HI Barani143,

Did you find a solution to this problem. I am getting the exact same result as you. Error -84 when mounting and error -28 when formating.

Thanks, Eddy

nikosgri commented 4 months ago

Hello, I have the same problem as well. Do you managed to make it work?