Open hchaudhary1 opened 6 years ago
I do not think the look ahead buffer needs to be that large. You can probably reduce that considerably. The Kioxia flash devices support partial page writes so you can use a smaller page size (1024 instead of 4096) and reduce your buffer sizes as well. I have noticed a peculiar thing about the Kioxia nand. When reading a page from nand, the OIP time will occasionally exceed the max page read time specification in the data sheet. I am wondering if this is common for other nand devices?
Yes, it supports the page partial program, but I've tested to write byte-by-byte and it also works. So maybe doing as discussed at #277 can achieve a best performance right?
I think you might be confusing the write to the on-chip cache with the page write. There is a limit to the number of writes you can do to the cell array. This is specified in the datasheet as " Number of programs per page" which for the Kioxia chip is 4 (other vendors may only allow 1. For instance, the Alliance chips). You can certainly write byte-by-byte to the cache. But when it comes time to write the cache to the nand cell array, you are limited to 4 times. There are some other limitations related to how the ECC is calculated that impact this as well. The simple solution is to use 1K blocks.
Here's what I'm struggling now because I agree with what you say about what the datasheet says. However, my tests tell me that I can really write byte-by-byte to the cell array. My prog function looks like:
BOOL Flash_LFS_Prog( ... )
{
if (Flash_EnableWrite() == FALSE)
return FALSE;
if (Flash_ProgramLoad(src, colAddr, size) == FALSE)
return FALSE;
if (Flash_ProgramExecute(rowAddr) == FALSE)
return FALSE;
Flash_DisableWrite();
return TRUE;
}
By performing the Program execute, I think I'm writing it to the cell array. What am I missing? Thanks again for your support!
Yes, that is correct. Each time you execute "Program Execute", you write the on chip cache to the NAND cell array. My understanding of what the datasheet says is you can only do this 4 times before you have to erase the block. I haven't actually tried to see if I could write the page more than 4 times. If you go down this path I would be interested to learn how reliable it is.
There are some implications for the spare area as well. ECC is calculated on 512 byte sub blocks of the page. So, when you program the page, ECC is calculated for each 512 chunk.
Yes, that is correct. Each time you execute "Program Execute", you write the on chip cache to the NAND cell array. My understanding of what the datasheet says is you can only do this 4 times before you have to erase the block. I haven't actually tried to see if I could write the page more than 4 times. If you go down this path I would be interested to learn how reliable it is.
There are some implications for the spare area as well. ECC is calculated on 512 byte sub blocks of the page. So, when you program the page, ECC is calculated for each 512 chunk.
Yes, with ECC enabled it's like that, but for now I'm disabling it to keep it simple. I'm not using the spare area also because I can detect if the block is bad or not while doing a block erase or a page program. Besides that, my Flash_LFS_Sync function is returning always 0 because I'm doing the program execute always on the Flash_LFS_Prog. Maybe it's better to switch the program execute to the Flash_LFS_Sync function right?
About the reliability you say, I suspect it's not the best approach (byte-by-byte) to achieve a good one.
@geky @joicetm . I have solved the issue with the help of another person who has faced same issue with QSPI NAND. Please note that this will never come in the case of SPI, as this is a problem bw STM32 QSPI and the W25N01GV NAND.
The microcontroller sends the QSPI command(HAL_QSPI_Command) fields in the order:
- Instruction
- Address
- Alternate bytes
- Dummy Clocks
- Data
But, according to the Winbond data sheet, some commands (those in which the page address is used) need the address after the dummy clock. So this cannot be achieved with sending a QSPI command. So, for these commands now I am sending HAL_QSPI_Command with no address and then sending the address as if it were the data, with "HAL_QSPI_Transmit" function.
FYI. I am not using littlefs now, Instead managing a static queue that holds address and size of data in NAND. Once I get some time I will check with LittleFS. I hope performance will be better as compared to SPI since Quad SPI is much faster.
Regards, Visakh
@geky @joicetm . I have solved the issue with the help of another person who has faced same issue with QSPI NAND. Please note that this will never come in the case of SPI, as this is a problem bw STM32 QSPI and the W25N01GV NAND.
The microcontroller sends the QSPI command(HAL_QSPI_Command) fields in the order:
- Instruction
- Address
- Alternate bytes
- Dummy Clocks
- Data
But, according to the Winbond data sheet, some commands (those in which the page address is used) need the address after the dummy clock. So this cannot be achieved with sending a QSPI command. So, for these commands now I am sending HAL_QSPI_Command with no address and then sending the address as if it were the data, with "HAL_QSPI_Transmit" function.
FYI. I am not using littlefs now, Instead managing a static queue that holds address and size of data in NAND. Once I get some time I will check with LittleFS. I hope performance will be better as compared to SPI since Quad SPI is much faster.
Regards, Visakh
Hi, I am currently experiencing the problem you describe. When You say you are sending it back to back, Firstly, HAL_StatusTypeDef status; QSPI_CommandTypeDef cmd; cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; cmd.AddressMode = QSPI_ADDRESS_NONE; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; cmd.DataMode = QSPI_DATA_NONE; cmd.DummyCycles = dummyCycles; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
cmd.Instruction = 0xD8; // erase
cmd.Address = 0x00;
cmd.AddressSize =0x00;
cmd.NbData = 0;
Are you sending the address like this?
QSPI_CommandTypeDef cmd;
cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
cmd.AddressMode = QSPI_ADDRESS_1_LINE;
cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
cmd.DataMode = QSPI_DATA_NONE;
cmd.DummyCycles = 0;
cmd.DdrMode = QSPI_DDR_MODE_DISABLE;
cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
cmd.Instruction = 0xD8; // erase
cmd.Address = page_address;
cmd.AddressSize = QSPI_ADDRESS_16_BITS;
cmd.NbData = 0;
Did you try to do this? I understood that from what you said.
@hchaudhary1 @geky How to deal with bad blocks ?Factory-generated bad blocks or erase/write? I have this nand flash: Page Size 2048 block_Count 1024
Use below config is OK?
.read_size = 2048, .prog_size = 2048, .block_size = 2048 * 64, .block_count = 1024, .cache_size = 2048, .lookahead_size = 2048, .block_cycles = 500,
I believe LittleFS already has bad block management
yes, the idea is that failing writes will be reallocated to a different block
@hchaudhary1 @rojer when failing writes return LFS_ERR_CORRUPT?but i test ,mark block 0 bad ,Error when open then read file,test code below, Step1: erase all block Step2: mark block0 bad Step3: in nand drv port : _block_read ,_block_erase _block_prog if block bad return LFS_ERR_CORRUPT
Run code : int err = lfs_mount(&cfg_NandFlash, &cfg_NandFlash); if (err) { LFS_LOG_WARN("first fs mount failed\n"); lfs_format(&cfg_NandFlash, &cfg_NandFlash); lfs_mount(&cfg_NandFlash, &cfg_NandFlash); }
uint32_t boot_count = 0;
FS_FILE *fp = fs_open("boot_count", LFS_O_RDWR | LFS_O_CREAT);
fs_read(&boot_count, sizeof(boot_count), fp);
LFS_LOG_ERROR("boot_count is %d\n", boot_count);
boot_count += 1;
fs_seek(fp, 0, LFS_SEEK_SET);
fs_write(&boot_count, sizeof(boot_count), fp);
fs_seek(fp, 0, LFS_SEEK_SET);
boot_count = 0;
fs_read(&boot_count, sizeof(boot_count), fp);
LFS_LOG_ERROR("boot_count is %d\n", boot_count);
fs_close(fp);
Err info: lfs.c line:5161 Expression Faild : lfs_mlist_open
I tested without bad blocks and it works fine
i debug in lfs_format ,when call lfs_dir_compact, lfs_bd_erase(block 0) return LFS_ERR_CORRUPT,goto relocate
run here return LFS_ERR_NOSPC; // can't relocate superblock, filesystem is now frozen if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) { LFS_WARN("Superblock 0x%"PRIx32" has become unwritable", dir->pair[1]); return LFS_ERR_NOSPC; }
@geky @hchaudhary1 @rojer so when bad block at 0 or 1 littlefs cannot handle this situation?
yeah, i guess when block 0 or 1, the superblocks, go bad, it's game over. fortunately, they don't get changed much, normally.
Yes, it supports NAND without modifications. You have to write your own read, write, erase functions ofcoarse
EDIT: Tested with Micron MT29F 1GiB model, that has hardware ECC.
Can you share the MT29F wrapper ?
@zbqxyz and @hchaudhary1
Which nand (mt29f2g01abagdwb), it has 128 bytes per page. So I don't see and understand why you didn't include it in littlefs configuration. Without that it will calculate wrong physical block ?
Hello,
I am using LittleFs on a spi nand flash Micron, MT29F and it works very well.
But now, I would like to improve write speed, if possible.
I understand (tell me if I am wrong), that after every write, there is a read spi transfert, and a compare to check.
Pleased find enclosed a timing:
But MT29F nand flash provide an 'uncorrected ECC error code' when it cannot correct read page.
So I think that we just have to test the flag, no need to do a spi read transfert to check write. So we could avoid many read spi transferts.
What do you think about this ?
Thank you, best regards
Hello,
Here was my config:
// minimum read and prog size operation // if use ecc, only 4 'partial page programming' are allowed // so size must be > PAGE_DATA_SIZE/4 // if not, ecc error bit remains high ...
erase_littlefs_wrapper, .sync = sync_littlefs_wrapper,
// block device configuration
.read_size = LFS_SIZE_READ_PROG,
.prog_size = LFS_SIZE_READ_PROG,
.block_size = PAGE_DATA_SIZE * NUM_PAGE_BLOCK,
.block_count = NUM_BLOCKS,
.lookahead_size = LFS_SIZE_READ_PROG,
// cache_size must be multiple of read_size
.cache_size = LFS_SIZE_READ_PROG,
// Set to -1 to disable block-level wear-leveling.
.block_cycles = -1
};
Is that what you expected ?
Le sam. 15 oct. 2022 à 05:28, Matt Mercaldo @.***> a écrit :
Hello Jac666, What was your config for the MT29F NAND chip? Thanks!
— Reply to this email directly, view it on GitHub https://github.com/littlefs-project/littlefs/issues/11#issuecomment-1279646322, or unsubscribe https://github.com/notifications/unsubscribe-auth/AI6ZODFOFCQUXCIGL5TYC5LWDIQHBANCNFSM4EMT3LFQ . You are receiving this because you commented.Message ID: @.***>
Perfect! Thanks so much!
@joicetm I am wondering what SPI driver you are using? I am using the same Winbond NAND memory and can't find the driver that provides the functions your wrapper uses. flash_w25n01gv_read_lfs or similar functions
Any help would be appreciated. Or if there are other drivers that would do the job that would be much appreciated.
Update, if you contact Winbond they can provide you with an example driver that works on STM32 MCUs. I used this as the basis of my own driver.
Hello .I am using LittleFs on a spi nand flash in esp32s3. What suggestions do you have to increase the speed of reading and writing? In a situation where the number of files is small, I can read 3 files with size 100 byte in a second. By increasing the number of files to 3000, the speed decreases a lot and it takes 40 seconds to read 3 files .
Hi, Does your user application directly access the NAND flash through Zephyr's FS subsystem (fs_xxx) or LittleFS interfaces (lfs_xxx)? I ask because I encountered a linking issue when attempting to use Zephyr's FS subsystem by adding partition configuration in the device tree.
However, everything works perfectly when I utilize the LittleFS interfaces to access the NAND flash.
[Partition configuration] &MT29FXXX { partitions { compatible = "fixed-partitions";
#size-cells = <1>;
littlefs_partition: partition@0 {
label = "littlefs_storage";
reg = <0x00000000 0x001000000>;
};
}; };
[Application]
static struct fs_mount_t lfs_mnt = { .type = FS_LITTLEFS, .fs_data = &cfg, .storage_dev = (void*)STORAGE_PARTITION_ID, .mnt_point = "/littlefs", }; ... fs_mount(&lfs_mnt);
[Error messages]
[4/12] Linking C executable zephyr/zephyr_pre0.elf FAILED: bin/ld.bfd: zephyr/libzephyr.a(flash_map_default.c.obj):(.rodata.default_flash_map+0x4c): undefined reference to __device_dts_ord_98
__device_dts_ord_98 corresponds to my spi flash driver
I constructed my SPI NAND flash driver as an out-of-tree driver, considering that it might be the cause of the problem. I'm curious to know if you encountered a similar issue when building your SPI NAND driver outside of the Zephyr codebase and adding partition configurations.
wonderful discussion...
Hi,
I am also working on porting littlefs driver, on top of MT29. I am able to port the fs.
Although while life testing, I am getting -84 error (i.e. LFS_ERR_CORRUPT) after I write around 210 files of 3K, and after that complete file system gets corrupted.
So can anyone help me to understand the cause of error.
My config struct is as follows:
const struct lfs_config cfg = {
.context = NULL,
.read = lfsread,
.prog = lfsprog,
.erase = lfserase,
.sync = lfssync,
.lock = sh_lfslock,
.unlock = sh_lfsunlock,
.read_size = 4096,
.prog_size = 4096,
.block_size = 4096,
.block_count = 262144,
.block_cycles = 512,
.cache_size = 4096,
.lookahead_size = 4096,
};
I'll let the others speak up to correct me if i am wrong..
It looks like your configuration is not correct. Read size is pretty high - you may want to think about tuning it to something smaller.
My running config is read size - 16 prog size - 1024 cache size - 1024 lookahead - 16 block count - 2048
you have to be careful because the sizes are not bytes all the time. Remember, the chip can only do 4 write operations before it needs to get refreshed to all FF as per the documentation on the chip.
There are some good notes in this blog overall about these value and what they should be.
You will also want to deep dive the amazing documentation created for littlefs.
On 07/13/2023 7:18 AM EDT ParthJaiswal17 @.***> wrote:
Hi,
I am also working on porting littlefs driver, on top of MT29. I am able to port the fs.
Although while life testing, I am getting -84 error (i.e. LFS_ERR_CORRUPT) after I write around 210 files of 3K, and after that complete file system gets corrupted.
So can anyone help me to understand the cause of error.
My config struct is as follows:
const struct lfs_config cfg = {
.context = NULL, .read = lfsread, .prog = lfsprog, .erase = lfserase, .sync = lfssync,
ifdef LFS_THREADSAFE
.lock = sh_lfslock, .unlock = sh_lfsunlock,
endif
.read_size = 4096, .prog_size = 4096, .block_size = 4096, .block_count = 262144, .block_cycles = 512, .cache_size = 4096, .lookahead_size = 4096,
};
— Reply to this email directly, view it on GitHub https://github.com/littlefs-project/littlefs/issues/11#issuecomment-1634065169, or unsubscribe https://github.com/notifications/unsubscribe-auth/AQAXUR2QSIS3HN6Q5TRYFA3XP7KQTANCNFSM4EMT3LFQ. You are receiving this because you commented.Message ID: @.***>
Hi mattmercaldo,
Thank you for the advice, although if decrease the prog size to 1024, I get ecc error during read, also if reduce read size I am getting error while reading file number 32, must be metadeta issue.
Although the update is I have resolved the Issue by Increasing the block size to actual block size of MT29 flash which is 256KB and now it is working well, but with the cost of low speed.
Thank you.
NAND working well
Hello @hchaudhary1 Can you give me the config for littleFS, in my case, I'vs already completed the driver for MT29F2G01 flash (read/prog/erase working ok) but I'm stucking at some points. Anyway, if you do not mind, can you give me your contact, I wanna ask you some questions about your config for littlefs on that nand flash. Thank you
Trying to get littleFS running on w25m02gw SPI NAND, So far it seem to be working okay, with ability to write multiple file, read back and confirm data..etc.
.read_size/.prog_size is 2048 bytes(page size), and .erase_size is 64 x page size(128KB)
@hchaudhary1 Any guess Why I am seeing frequent block erases.. on every 4K write? It appears like its starting on a new block on every write.
More details here - https://github.com/littlefs-project/littlefs/issues/905
Hi I would like to use LittleFS directly on a NAND chip, such as Micron MT29F.
The minimum erasable unit on the MT29F is 128KiB The smallest writable unit is 2KiB (random write) The smallest writable unit is 1 byte (sequential write)
Thanks