UFFS v1.3.3 is released.
- Simplify flash interface.
- Improved bad block handling.
- Better support for MLC NAND flash.
- Added hardware ECC and RS-ECC controller emulator.
- Bug fixes.
The biggest change of this release is on the flash interface. We simplify the flash interface, writting a NAND flash driver is much simpler than befor.
The flash-interface-example.c adds the NAND commands demo, it's a good start point to the real NAND flash driver.
The emulator got improved as well, we have hardware ECC and MLC RS-ECC emulated. The emulator also emulates bit-flip errors, block erase errors and manufacture bad blocks.
Source code package can be downloaded from sourceforge.net: uffs-v1.3.3.tar.bz2
Wednesday, November 17, 2010
Monday, April 5, 2010
UFFS v1.3.2 released
UFFS v1.3.2 is released.
Changes from v1.3.1:
* Add POSIX like file system APIs.
* Use new APIs on simulator test commands
* Bug fixes and other improvements:
- fix ticket: 2968955, example code mount table start block bug
- fix ticket: 2963571, ECC bug
- fix ticket: 2974818, add new config option: CONFIG_BAD_BLOCK_POLICY_STRICT
- fix ticket: 2968962, improve uffs_Perror() and friends
Download source package from sf.net: uffs-1.3.2.tar.bz2
Changes from v1.3.1:
* Add POSIX like file system APIs.
* Use new APIs on simulator test commands
* Bug fixes and other improvements:
- fix ticket: 2968955, example code mount table start block bug
- fix ticket: 2963571, ECC bug
- fix ticket: 2974818, add new config option: CONFIG_BAD_BLOCK_POLICY_STRICT
- fix ticket: 2968962, improve uffs_Perror() and friends
Download source package from sf.net: uffs-1.3.2.tar.bz2
Monday, March 1, 2010
UFFS v1.3.1 released
Changes from v1.3.0:
* Tidy up three memory allocators: static, native and system.
* Fix bugs in flash interface example.
* Fix memory allocation bugs when using static memory allocator.
* Add flash driver interface 'WriteFullPage()' for easier implementation of nand driver, or connect to other nand layout (e.g. eCos NAND lib).
* Fix compilation errors for BlackFin DSP compiler.
Tuesday, February 23, 2010
Writing NAND driver for UFFS
Writing a NAND driver for UFFS is pretty straight forward.
The main job to implement NAND driver for UFFS is setup "struct uffs_StorageAttrSt" and provide functions in "struct uffs_FlashOpsSt" .
Setup "struct StorageAttrSt":
This is the data structure to describe the basic attributes of you NAND flash, tell UFFS which ECC option your driver will use and how the tag and ECC will be layout to page spare area.
uffs_StorageAttrSt::total_blocks
Total blocks of your NAND flash chip. (Note: not the block numbers of your certain UFFS partition)
uffs_StorageAttrSt::page_data_size
The size of NAND flash page data area, in bytes. For example, 512, 1024, 2048 ... etc.
uffs_StorageAttrSt::pages_per_block
How many pages in one block
uffs_StorageAttrSt::spare_size
Size of page spare area. For example: 16, 32, 64 ... etc.
uffs_StorageAttrSt::block_status_offs
There is one byte on page spare area used for indicating block status (bad/good block). The position of the status byte is NAND vendor specific. For example, SAMSUNG NAND flash with small page size (512) usually use the 5th bytes of spare as status byte, so you should set ::block_status_offs = 4 (0 based offset).
uffs_StorageAttrSt::ecc_opt
Choose ECC options for your driver:
For most modem MCUs with build-in NAND controller, your should choose UFFS_ECC_HW, otherwise choose UFFS_ECC_SOFT. Some very rare NAND controller will write ECC right after encode, in this case, choose UFFS_ECC_HW_AUTO.
uffs_StorageAttrSt::layout_opt
Tell UFFS do the layout for you or you driver will do the layout. In most case, you should choose letting UFFS do the layout (UFFS_LAYOUT_UFFS). In very rare case you might want to do the layout in your driver (UFFS_LAYOUT_FLASH).
If UFFS_LAYOUT_UFFS is chosen, your driver must provide 'ReadPageSpare' and 'WritePageSpare' functions in "struct uffs_FlashOpsSt". (will discuss this later)
if UFFS_LAYOUT_FLASH is chosen, your driver must provide 'ReadPageSpareWithLayout' and 'WritePageSpareWithLayout' functions in "struct uffs_FlashOpsSt".
uffs_StorageAttrSt::ecc_layout, uffs_StorageAttrSt::data_layout
Tell UFFS how to layout the ECC and Tag data on page spare area.
In most case, you should set ecc_layout and data_layout to NULL and UFFS will create the layout array for you.
However, if you have to use UFFS_ECC_HW_AUTO for ecc_opt (because of the rare hardware controller) or you want to create your own spare layout to be compatible with other software, you need to provide the layout array.
The layout array is unsigned char array, start from offset, followed by size, terminated by [0xFF, 0x00].
For example, you have 6 bytes ECC (for page size 512), 8 bytes tag, the status byte is the 5th byte.
To create a spare layout as:
You should provide layout array as:
Layout array for ecc_layout: [0x09, 0x06, 0xFF, 0x00]
Layout array for data_layout: [0x00, 0x04, 0x05, 0x04, 0xFF, 0x00] (Note: the 8 bytes tag data is split by status byte at 5th)
Provide functions for "struct uffs_FlashOpsSt"
int ReadPageData(uffs_Device *dev, u32 block, u32 page, u8 *data, int len, u8 *ecc);
This function read flash page data.
dev: uffs_Device
block, page: block and page number to be read. The page number is relative number (to the block).
data: buffer for the read data
len: the size of data to be read
ecc: if your driver use hardware to calculate ECC (ecc_opt = UFF_ECC_HW), your driver should copy the calcuated ECC to ecc. For other ecc_opt (UFFS_ECC_NONE, UFFS_ECC_SOFT or UFFS_ECC_HW_AUTO), ecc is not used.
int ReadPageSpare(uffs_Device *dev, u32 block, u32 page, u8 *spare, int ofs, int len);
This function implements reading page spare data to spare.
dev: uffs_Device
block, page: block and page number to be read. The page number is relative number (to the block).
spare: buffer for the read data
ofs: reading offset from the start of spare area.
len: the data amount to be read
For example, to read 3 bytes spare data from 518th byte of page: ofs=6, len=3 (page data size 512)
Note: 'ReadPageData' and 'ReadPageSpare' function are single-shot operations, which means you should do the full cycle reading from NAND:
....cs=0...[READ CMD]..[COL]..[ROW]...[Transfer data]...cs=1...
int ReadPageSpareWithLayout(uffs_Device *dev, u32 block, u32 page, u8 *tag, int len, u8 *ecc);
If you do the spare layout in your driver (layout_opt = UFFS_LAYOUT_FLASH), this function should be implemented instead of 'ReadPageSpare' function.
int WritePageData(uffs_Device *dev, u32 block, u32 page, const u8 *data, int len, u8 *ecc);
This function implements programing data to page data area.
dev: uffs_Device
block, page: block and page number to be wrote
data: data buffer
len: size of data
ecc: If you use hardware ECC (ecc_opt = UFFS_ECC_HW), your should copy calculated ECC to ecc.
This function should return UFFS_FLASH_BAD_BLK if a bad block is found.
int WritePageSpare(uffs_Device *dev, u32 block, u32 page, const u8 *spare, int ofs, int len, UBOOL eod);
This function implements programing spare to page spare area.
dev: uffs_Device
block, page: block and page number to be wrote
data: data buffer
ofs: programing offset from the start of spare area
len: size of data
eod: U_FALSE if this function is called after 'WritePageData', otherwise U_TRUE
UFFS_FLASH_BAD_BLK should be returned if a bad block is found.
Note1: When programing a full page (data area + spare area), UFFS call WritePageData() followed by WritePageSpare(eod = U_TRUE). In this case, START command sent in WritePageData() and PROGRAM command sent in WritePageSpare(), this avoid partial program.
Note2: When programming page spare area only, UFFS call WritePageSpare(eod = U_FALSE). In this case, START and PROGRAM command issued within WritePageSpare() function.
int WriteFullPage(uffs_Device *dev, u32 block, u32 page, const u8* data, int len, const u8 *ts, int ts_len, const u8 *ecc);
If you do the spare layout in your driver (layout_opt = UFFS_LAYOUT_FLASH), this function should be implemented instead of
int IsBadBlock(uffs_Device *dev, u32 block);
Implement this function if your NAND driver maintain the bad block table by itself, otherwise leave it NULL.
int MarkBadBlock(uffs_Device *dev, u32 block);
Implement this function if your NAND driver maintain the bad block table by itself, otherwise leave it NULL.
int EraseBlock(uffs_Device *dev, u32 block);
This function implements block erasing.
UFFS_FLASH_BAD_BLK should be returned if a bad block is found.
Example
flash interface example is included in source package: src/example/flash-interface-example.c
The main job to implement NAND driver for UFFS is setup "struct uffs_StorageAttrSt" and provide functions in "struct uffs_FlashOpsSt" .
Setup "struct StorageAttrSt":
This is the data structure to describe the basic attributes of you NAND flash, tell UFFS which ECC option your driver will use and how the tag and ECC will be layout to page spare area.
uffs_StorageAttrSt::total_blocks
Total blocks of your NAND flash chip. (Note: not the block numbers of your certain UFFS partition)
uffs_StorageAttrSt::page_data_size
The size of NAND flash page data area, in bytes. For example, 512, 1024, 2048 ... etc.
uffs_StorageAttrSt::pages_per_block
How many pages in one block
uffs_StorageAttrSt::spare_size
Size of page spare area. For example: 16, 32, 64 ... etc.
uffs_StorageAttrSt::block_status_offs
There is one byte on page spare area used for indicating block status (bad/good block). The position of the status byte is NAND vendor specific. For example, SAMSUNG NAND flash with small page size (512) usually use the 5th bytes of spare as status byte, so you should set ::block_status_offs = 4 (0 based offset).
uffs_StorageAttrSt::ecc_opt
Choose ECC options for your driver:
- UFFS_ECC_NONE - do not use ECC ( not recommended )
- UFFS_ECC_SOFT - UFFS will take care of ECC calculation and correction.
- UFFS_ECC_HW - Your NAND driver will use hardware ECC generator to encode/decode ECC
- UFFS_ECC_HW_AUTO - Your NAND controller will generate ECC code AND write the ECC codes to page spare area (and you can't stop that !) when you write data to page data area. This will cause partial programming on spare area as UFFS need to write tag to spare later.
For most modem MCUs with build-in NAND controller, your should choose UFFS_ECC_HW, otherwise choose UFFS_ECC_SOFT. Some very rare NAND controller will write ECC right after encode, in this case, choose UFFS_ECC_HW_AUTO.
uffs_StorageAttrSt::layout_opt
Tell UFFS do the layout for you or you driver will do the layout. In most case, you should choose letting UFFS do the layout (UFFS_LAYOUT_UFFS). In very rare case you might want to do the layout in your driver (UFFS_LAYOUT_FLASH).
If UFFS_LAYOUT_UFFS is chosen, your driver must provide 'ReadPageSpare' and 'WritePageSpare' functions in "struct uffs_FlashOpsSt". (will discuss this later)
if UFFS_LAYOUT_FLASH is chosen, your driver must provide 'ReadPageSpareWithLayout' and 'WritePageSpareWithLayout' functions in "struct uffs_FlashOpsSt".
uffs_StorageAttrSt::ecc_layout, uffs_StorageAttrSt::data_layout
Tell UFFS how to layout the ECC and Tag data on page spare area.
In most case, you should set ecc_layout and data_layout to NULL and UFFS will create the layout array for you.
However, if you have to use UFFS_ECC_HW_AUTO for ecc_opt (because of the rare hardware controller) or you want to create your own spare layout to be compatible with other software, you need to provide the layout array.
The layout array is unsigned char array, start from offset, followed by size, terminated by [0xFF, 0x00].
For example, you have 6 bytes ECC (for page size 512), 8 bytes tag, the status byte is the 5th byte.
To create a spare layout as:
[ D0, D1, D2, D3, S, D4, D5, D6, D7, ECC1, ECC2, ECC3, ECC4, ECC5, ECC6]
D0-D7: 8 bytes tag. S: the status byte ECC1 - ECC6: 6 bytes ECC.
You should provide layout array as:
Layout array for ecc_layout: [0x09, 0x06, 0xFF, 0x00]
Layout array for data_layout: [0x00, 0x04, 0x05, 0x04, 0xFF, 0x00] (Note: the 8 bytes tag data is split by status byte at 5th)
Provide functions for "struct uffs_FlashOpsSt"
int ReadPageData(uffs_Device *dev, u32 block, u32 page, u8 *data, int len, u8 *ecc);
This function read flash page data.
dev: uffs_Device
block, page: block and page number to be read. The page number is relative number (to the block).
data: buffer for the read data
len: the size of data to be read
ecc: if your driver use hardware to calculate ECC (ecc_opt = UFF_ECC_HW), your driver should copy the calcuated ECC to ecc. For other ecc_opt (UFFS_ECC_NONE, UFFS_ECC_SOFT or UFFS_ECC_HW_AUTO), ecc is not used.
int ReadPageSpare(uffs_Device *dev, u32 block, u32 page, u8 *spare, int ofs, int len);
This function implements reading page spare data to spare.
dev: uffs_Device
block, page: block and page number to be read. The page number is relative number (to the block).
spare: buffer for the read data
ofs: reading offset from the start of spare area.
len: the data amount to be read
For example, to read 3 bytes spare data from 518th byte of page: ofs=6, len=3 (page data size 512)
Note: 'ReadPageData' and 'ReadPageSpare' function are single-shot operations, which means you should do the full cycle reading from NAND:
....cs=0...[READ CMD]..[COL]..[ROW]...[Transfer data]...cs=1...
int ReadPageSpareWithLayout(uffs_Device *dev, u32 block, u32 page, u8 *tag, int len, u8 *ecc);
If you do the spare layout in your driver (layout_opt = UFFS_LAYOUT_FLASH), this function should be implemented instead of 'ReadPageSpare' function.
int WritePageData(uffs_Device *dev, u32 block, u32 page, const u8 *data, int len, u8 *ecc);
This function implements programing data to page data area.
dev: uffs_Device
block, page: block and page number to be wrote
data: data buffer
len: size of data
ecc: If you use hardware ECC (ecc_opt = UFFS_ECC_HW), your should copy calculated ECC to ecc.
This function should return UFFS_FLASH_BAD_BLK if a bad block is found.
int WritePageSpare(uffs_Device *dev, u32 block, u32 page, const u8 *spare, int ofs, int len, UBOOL eod);
This function implements programing spare to page spare area.
dev: uffs_Device
block, page: block and page number to be wrote
data: data buffer
ofs: programing offset from the start of spare area
len: size of data
eod: U_FALSE if this function is called after 'WritePageData', otherwise U_TRUE
UFFS_FLASH_BAD_BLK should be returned if a bad block is found.
Note1: When programing a full page (data area + spare area), UFFS call WritePageData() followed by WritePageSpare(eod = U_TRUE). In this case, START command sent in WritePageData() and PROGRAM command sent in WritePageSpare(), this avoid partial program.
Note2: When programming page spare area only, UFFS call WritePageSpare(eod = U_FALSE). In this case, START and PROGRAM command issued within WritePageSpare() function.
int WriteFullPage(uffs_Device *dev, u32 block, u32 page, const u8* data, int len, const u8 *ts, int ts_len, const u8 *ecc);
If you do the spare layout in your driver (layout_opt = UFFS_LAYOUT_FLASH), this function should be implemented instead of
'WritePageData()' + 'WritePageSpare()' functions.
If you want to use YAFFS NAND interface or eCos NAND lib, you should implement this function.
int IsBadBlock(uffs_Device *dev, u32 block);
Implement this function if your NAND driver maintain the bad block table by itself, otherwise leave it NULL.
int MarkBadBlock(uffs_Device *dev, u32 block);
Implement this function if your NAND driver maintain the bad block table by itself, otherwise leave it NULL.
int EraseBlock(uffs_Device *dev, u32 block);
This function implements block erasing.
UFFS_FLASH_BAD_BLK should be returned if a bad block is found.
Example
flash interface example is included in source package: src/example/flash-interface-example.c
UFFS v1.3.0 released
It's been 9 months since last release, it is a long time !
Thanks to the people who tried/adopted UFFS in their projects, it's YOU made this release :)
Version 1.3 is an important version in the way to UFFS2, the new features and structure changes in v1.3 made a clean and flexible code base. It's recommended for all UFFS users to update to this new release.
New Features in v1.3.0:
* Grouped buffers
* New APIs for file/dir search, mount table operations ... etc.
* New flash interface
- support page size up to 4K bytes
- Support hardware ECC
- Avoid partial page programing
- Allow user defined spare layout for special NAND controller
* Lower memory consumption
Download source package from:
http://sourceforge.net/projects/uffs/files/uffs/uffs-1.3.0/uffs-1.3.0.tar.bz2/download
or get it from GIT repo:
Thanks to the people who tried/adopted UFFS in their projects, it's YOU made this release :)
Version 1.3 is an important version in the way to UFFS2, the new features and structure changes in v1.3 made a clean and flexible code base. It's recommended for all UFFS users to update to this new release.
New Features in v1.3.0:
* Grouped buffers
* New APIs for file/dir search, mount table operations ... etc.
* New flash interface
- support page size up to 4K bytes
- Support hardware ECC
- Avoid partial page programing
- Allow user defined spare layout for special NAND controller
* Lower memory consumption
Download source package from:
http://sourceforge.net/projects/uffs/files/uffs/uffs-1.3.0/uffs-1.3.0.tar.bz2/download
or get it from GIT repo:
git://uffs.git.sourceforge.net/gitroot/uffs/uffs
Saturday, January 2, 2010
UFFS git repo URL on sourceforge has been changed !
sourceforge has changed the UFFS git repo URL, you can clone the new repo:
If you want to try out v1.3, please checkout the b-uffs-1.3 branch:
git checkout --track -b b-uffs-1.3 origin/b-uffs-1.3
git clone git://uffs.git.sourceforge.net/gitroot/uffs/uffs
If you want to try out v1.3, please checkout the b-uffs-1.3 branch:
git checkout --track -b b-uffs-1.3 origin/b-uffs-1.3
Subscribe to:
Posts (Atom)