I am using TI's dm368 Development Board. The kernel is 2.6.32.17, and the default FLASH file system is jffs2. However, jffs2 is in a large partition, and the Mount speed is very slow and occupies a large amount of Ram. Therefore, I want to use ubifs to see if the performance is better.
The principles and configuration process of ubifs are introduced on many web pages. I will provide a link for you to see. I will not repost it, I will focus on the problems I encountered and solved during the transplantation process.
Http://bbs.chinaunix.net/thread-1954881-1-1.html
The configuration of kerne is very simple. It is available in 2.6.32 and can be selected and re-compiled.
Ubiattach, ubimkvol, and other tools are provided by TI's dvsdk. If they can be used, I am a lazy user and have not re-compiled.
It's easy to follow the instructions on the webpage. The Mount partition is successful, and the file is copied. I'm glad to know that :)
Ubiattach/dev/ubi_ctrl-M 3
Ubimkvol/dev/ubi0-N rootfs-s 480mib
Mount-T ubifs ubi0_0/mnt/NAND/-O sync
But soon I got into trouble. After the Development Board was shut down and restarted, I encountered an error in the mout ubi file system, prompting a bunch of errors and the partition was empty, the copied file is missing.
The problem is as follows:
Ubiattach/dev/ubi_ctrl-M 3
UBI error: ubi_io_read: Error-74 while reading 64 bytes from peb 1662: 0, read 64 bytes
UBI error: ubi_io_read: Error-74 while reading 64 bytes from peb 1663: 0, read 64 bytes
To analyze the problem, I opened both MTD and ubifs's debug log and saw some information;
# Define ebadmsg 74/* not a data message */
/* NAND returns-ebadmsg on ECC errors, but it returns
* The data. For our userspace tools it isimportant
* To dump areas with ECC errors!
* For kernel internal usage it also mightreturn-euclean
* To signal the caller that a bitflip hasoccured and has
* Been corrected by the ECC algorithm.
* Userspace software which accesses NAND thisway
* Must be aware of the fact that it deals withnand
*/
Nand_do_read_ops
Stats = MTD-> ecc_stats;
If (MTD-> ecc_stats.failed-stats. Failed)
Return-ebadmsg;
Nand_read_page_hwecc
Stat = chip-> ECC. Correct (MTD, P, & ecc_code [I], & ecc_calc [I]);
If (STAT <0)
MTD-> ecc_stats.failed ++;
Else
MTD-> ecc_stats.corrected + = Stat;
It seems that an ECC error has occurred, but I use hardware ECC verification. How can I see an ECC verification error in almost all pages?
Root @ dm368-evm :~ # Flash_eraseall/dev/mtd3
Root @ dm368-evm :~ # Ubiattach/dev/ubi_ctrl-M 3
UBI: attaching mtd3 to ubi0
UBI: Physical eraseblock size: 131072 bytes (128 kib)
UBI: Logical eraseblock size: 129024 bytes
UBI: smallest flash I/O unit: 2048
UBI: Sub-page size: 512
UBI: vid header offset: 512 (aligned 512)
UBI: Data offset: 2048
Analyze the ubi Data Writing Process,
UBI dbg (PID 1484): ubi_io_write: Write 512 bytes to peb 57: 0
Int ubi_io_write (struct ubi_device * ubi, const void * Buf, int pnum, int offset,
Int Len)
ADDR = (loff_t) pnum * ubi-> peb_size + offset;
Err = ubi-> MTD-> write (UBI-> MTD, ADDR, Len, & written, Buf );
In the io_init function, you can see the values of several variables;
UBI-> peb_size = ubi-> MTD-> erasesize;
UBI-> peb_count = mtd_div_by_eb (UBI-> MTD-> size, ubi-> MTD );
UBI-> flash_size = ubi-> MTD-> size;
From the debug log, 512 bytes are written here, starting from the starting page of a block, and the offset is 0;
Then the underlying driver of the nand mtd performs the following actions;
Nand_write-> nand_do_write_ops:
Subpage = column | (writelen & (MTD-> writesize-1 ));
Here, the subpage is writelen, 512;
We can also know that ubifs does not use OOB, which is different from jffs2 and yaffs2;
/* Partial page write? */
If (unlikely (column | writelen <(MTD-> writesize-1 ))){
Cached = 0;
Bytes = min_t (INT, bytes-column, (INT) writelen );
Chip-> pagebuf =-1;
Memset (chip-> buffers-> databuf, 0xff, MTD-> writesize );
Memcpy (& Chip-> buffers-> databuf [column], Buf, bytes );
Wbuf = chip-> buffers-> databuf;
}
Ret = chip-> write_page (MTD, Chip, wbuf, page, cached,
(OPS-> mode = mtd_oob_raw ));
The code for the write_page function is as follows;
Static int nand_write_page (structmtd_info * MTD, struct nand_chip * chip,
Const uint8_t * Buf, int page, int cached, int raw)
{
Intstatus;
Chip-> sort func (MTD, nand_sort _seqin, 0x00, page );
If (unlikely (raw ))
Chip-> ECC. write_page_raw (MTD, Chip, Buf );
Else
Chip-> ECC. write_page (MTD, Chip, Buf );
/*
* Cached progamming disabled for now, not sureif its worth
* Trouble. The speed gain is not veryimpressive. (2.3-> 2.6mib/s)
*/
Cached = 0;
Note that raw is used. If mtd_oob_raw is used, ECC verification is not performed and the ECC code is not written to OOB;
In this case, you must specify mtd_oob_raw during read without ECC verification. Otherwise, the error we first saw will appear;
If (MTD-> ecc_stats.failed-stats. Failed)
Return-ebadmsg;
In this case, we may have found the cause of the Error. ubi uses subpage write, while the underlying NAND Flash driver does not actually support subpage write, although ubi only writes 512 bytes at a time, other parts of the page cannot write new data again.
From the perspective of nand_base.c (Drivers \ MTD \ NAND), large page's NAND Flash does not fully support subpage write and has many restrictions. For example, it cannot be the NAND flash of MLC or the hardware ECC;
The more serious problem is that the Code has a defect. When writing some data, fill the data in other parts with 0xff, write the entire page, and write all the ECC codes to OOB, maybe this is the cause of an error in the ECC verification.
Nand_do_write_ops ()
/* Partial page write? */
Memset (chip-> buffers-> databuf, 0xff, MTD-> writesize );
Memcpy (& Chip-> buffers-> databuf [column], Buf, bytes );
Therefore, the solution I came up with is to disable subpage write in the NAND driver.
Step 1: Add nand_no_subpage_write in chip options;
Static struct davinci_nand_pdatadavinci_nand_data = {
. Options = nand_use_flash_bbt | nand_no_subpage_write,
Then re-compile and download the kernel, but the problem persists;
Root @ dm368-evm :~ # Ubiattach/dev/ubi_ctrl-M 3
UBI: attaching mtd3 to ubi0
UBI: Physical eraseblock size: 131072 bytes (128 kib)
UBI: Logical eraseblock size: 129024 bytes
UBI: smallest flash I/O unit: 2048
UBI: Sub-page size: 512
UBI: vid header offset: 512 (aligned 512)
I wonder why the Sub-page size is still 512?
Check the code to see how the sub page size is calculated,
If (! (Chip-> options & nand_no_subpage_write )&&
! (Chip-> cellinfo & nand_ci_celltype_msk )){
Switch (chip-> ECC. Steps ){
Case 2:
MTD-> subpage_sft = 1;
Break;
Case 4:
Case 8:
Case 16:
MTD-> subpage_sft = 2;
Break;
}
}
Chip-> subpagesize = MTD-> writesize> MTD-> subpage_sft;
But I have added nand_no_subpage_write to options? I have some doubts. I have added a print log here. It is indeed a problem here,
Chip-> Options = 0x10101.
MTD-> subpage_sft = 0.
Chip-> subpagesize = 512.
# Define nand_no_subpage_write 0x00000200
However, the options here is obviously incorrect! So where is the nand_no_subpage_write I set lost?
The following function changes the value of chip-> options;
Nand_get_flash_type ()
Printk (kern_info "nand_get_flash_type 1, chip-> Options = 0x % x. \ n", chip-> options );
/* Get chip options, preserve non-Chip Based Options */
Chip-> options & = ~ Nand_chipoptions_msk;
Printk (kern_info "nand_get_flash_type 2, chip-> Options = 0x % x. \ n", chip-> options );
Chip-> options | = type-> options & nand_chipoptions_msk;
Printk (kern_info "nand_get_flash_type 3, chip-> Options = 0x % x. \ n", chip-> options );
/*
* Set chip as a default. Board drivers canoverride it, if necessary
*/
Chip-> options | = nand_no_autoincr;
/* Check if chip is a not a Samsung device. Do not clear
* Options for chips which are not having anextended ID.
*/
If (* maf_id! = Nand_mfr_samsung &&! Type-> pagesize)
Chip-> options & = ~ Nand_samsung_lp_options;
Printk (kern_info "nand_get_flash_type 4, chip-> Options = 0x % x. \ n", chip-> options );
Nand_get_flash_type 1, chip-> Options = 0x10200.
Nand_get_flash_type 2, chip-> Options = 0x10000.
Nand_get_flash_type 3, chip-> Options = 0x1011c.
Nand_get_flash_type 4, chip-> Options = 0x10101.
The problem is here, the red code!
/* Mask to zero out thechip options, which come from the ID table */
# Definenand_chipoptions_msk (0x0000ffff &~ Nand_no_autoincr)
/* Chip can not autoincrement pages */
# Define nand_no_autoincr 0x00000001
After finding the problem, the solution will be available. comment out the red line of code, that is, it will discard nand_no_subpage_write.
// Chip-> options & = ~ Nand_chipoptions_msk;
Re-compile and download the kernel. The problem is fixed!
Start the Development Board again and load ubi. Everything is normal.
Root @ dm368-evm:/# ubiattach/dev/ubi_ctrl-M 3
UBI: attaching mtd3 to ubi0
UBI: Physical eraseblock size: 131072 bytes (128 kib)
UBI: Logical eraseblock size: 126976 bytes
UBI: smallest flash I/O unit: 2048
UBI: vid header offset: 2048 (aligned 2048)
UBI: Data offset: 4096
UBI: attached mtd3 to ubi0
UBI: MTD device name: "filesystem1"
UBI: MTD device size: 512 MIB
UBI: Number of good pebs: 4096
UBI: Number of bad pebs: 0
UBI: Max. allowed volume: 128
UBI: Wear-leveling threshold: 4096
UBI: number of internal volumes: 1
UBI: number of user volumes: 1
UBI: available pebs: 3639
UBI: Total number of FIG: 457
UBI: Number of pebs reserved for badpeb handling: 40
UBI: Max/mean erase counter: 2/1
UBI: Image Sequence Number: 0
UBI: Background thread "ubi_bgt0d" started, PID 1483
UBI device number 0, total 4096 lebs (520093696 bytes, 496.0 MIB), available 3639 lebs (462065664 bytes, 440.7 MIB), Leb size 126976 bytes (124.0 kib)
Root @ dm368-evm:/# Mount-tubifs Ubian 0_0/mnt/NAND/-O sync
Ubifs: mounted ubi device 0, volume0, name "rootfs"
Ubifs: file system size: 51171328 bytes (49972 kib, 48 MiB, 403 lebs)
Ubifs: Journal size: 2539520 bytes (2480 kib, 2 MiB, 20 lebs)
Ubifs: Media Format: W4/R0 (latest is W4/R0)
Ubifs: Default Compressor: lzo
Ubifs: reserved for root: 2416947 bytes (2360 kib)
Root @ dm368-evm:/# DF
Filesystem 1k-blocks used available use % mounted on
/Dev/root 39544232 16239820 21295632 43%/
None 1024 24 1000 2%/dev
Tmpfs 16384 20 16364 0%/var/volatile
Tmpfs 21760 0 21760 0%/dev/SHM
Tmpfs 16384 0 16384 0%/Media/Ram
Ubi0_0 45528 1528 41640 4%/mnt/Nand
Finally, we need to disable the subpage write in the NAND Flash Driver so that chip-> subpagesize = MTD-> writesize can be used.
This is my solution. If you want to use subpage write, make sure that your read/write logic is correct. Either you do not need ECC or the ECC of each subpage should be correct.