今天做升級方案用到了mtd-utils中的flash_eraseall和flash_cp兩個工具,在進行方案驗證的時候,遭遇到各種不解和疑惑,因對MTD的原理不熟悉,所以只能多次嘗試,雖然最后把方案搞定了,不過覺得MTD中的mtd和mtdblock區別這塊還是值得總結學習一下。這里先說明一下問題現象,然后在進行具體的區別原理解釋。?
MTD設備(Nor Flash)使用中的問題現象表現?
- mtd-utils工具對mtd和mtdblock分區設備的區別處理?
- / $ flash_eraseall /dev/mtdblock/2
flash_eraseall: /dev/mtdblock/2: unable to get MTD device info
/ $ flash_eraseall /dev/mtdblock/2
flash_eraseall: /dev/mtdblock/2: unable to get MTD device info
/ $ flash_eraseall /dev/mtd/2
Erasing 128 Kibyte @ 8e0000 -- 98 % complete.
/ $ ls
- / $ flashcp rootfs_version /dev/mtdblock2
This doesn't seem to be a valid MTD flash device!
/ $ flashcp rootfs_version /dev/mtdblock/2
This doesn't seem to be a valid MTD flash device!
/ $ flashcp rootfs_version /dev/mtd2
/ $ ls
-
- mtd和mtdblock分區設備mount時的區別?
- / $ mount -t jffs2 /dev/mtd/2 qqzm/
mount: Mounting /dev/mtd/2 on qqzm/ failed: Invalid argument
/ $ mount -t jffs2 /dev/mtd2 qqzm/
mount: Mounting /dev/mtd2 on qqzm/ failed: Invalid argument
/ $ mount -t jffs2 /dev/mtdblock/2 qqzm/
/ $ ls
- mtdblock掛載成功,單擦除后卸載失敗?
- / $ flash_eraseall /dev/mtd/2 <span></span> Erasing 128 Kibyte @ 8e0000 -- 98 % complete.
/qqzm $ mount
/dev/root on / type jffs2 (rw,noatime)
proc on /proc type proc (rw,nodiratime)
sysfs on /sys type sysfs (rw)
devfs on /dev type devfs (rw)
devpts on /dev/pts type devpts (rw)
/dev/mmcblk0p1 on /mnt/sd type vfat (rw,nodiratime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1)
/dev/mtdblock/2 on /qqzm type jffs2 (rw,noatime)
none on /qqzm/www/cgi-bin/tmp type ramfs (rw)
/qqzm $ cd ..
/ $ umount /qqzm
umount: Couldn't umount /qqzm: Inappropriate ioctl for device
/ $ umount /dev/mtdblock/2
umount: Couldn't umount /dev/mtdblock/2: Inappropriate ioctl for device
/ $
-
通過上面的不斷嘗試和錯誤反饋,我把方案基本驗證通過了,只是對其中的原理不清楚:?
- 為什么mtd和mtdblock明明是同一個設備分區卻有不同的操作??
- mount命令只能掛載塊設備嗎??
- 卸載mtdblock設備時,Inappropriate ioctl for device是什么意思??
- unable to get MTD device info,又是什么意思??
MTD技術的基本原理?
MTD(memory technology device內存技術設備)是用于訪問memory設備(ROM、flash)的Linux的子系統。MTD的主要目的是為了使新的memory設備的驅動更加簡單,為此它在硬件和上層之間提供了一個抽象的接口,并進行了一個層次劃分,層次從上到下大致為:設備文件、MTD設備層、MTD原始設備層、硬件驅動層。MTD的所有源代碼在/drivers/mtd子目錄下。?
系統中的MTD設備文件?
~ $ ls /dev/mtd* -l
crw-rw----? ? 1 root ? ? root? ? ? 90, ? 0 Jan? 1 00:00 /dev/mtd0
crw-rw----? ? 1 root ? ? root? ? ? 90, ? 1 Jan? 1 00:00 /dev/mtd0ro
crw-rw----? ? 1 root ? ? root? ? ? 90, ? 2 Jan? 1 00:00 /dev/mtd1
crw-rw----? ? 1 root ? ? root? ? ? 90, ? 3 Jan? 1 00:00 /dev/mtd1ro
crw-rw----? ? 1 root ? ? root? ? ? 90, ? 4 Jan? 1 00:00 /dev/mtd2
crw-rw----? ? 1 root ? ? root? ? ? 90, ? 5 Jan? 1 00:00 /dev/mtd2ro
crw-rw----? ? 1 root ? ? root? ? ? 90, ? 6 Jan? 1 00:00 /dev/mtd3
crw-rw----? ? 1 root ? ? root? ? ? 90, ? 7 Jan? 1 00:00 /dev/mtd3ro
brw-rw----? ? 1 root ? ? root? ? ? 31, ? 0 Jan? 1 00:00 /dev/mtdblock0
brw-rw----? ? 1 root ? ? root? ? ? 31, ? 1 Jan? 1 00:00 /dev/mtdblock1
brw-rw----? ? 1 root ? ? root? ? ? 31, ? 2 Jan? 1 00:00 /dev/mtdblock2
brw-rw----? ? 1 root ? ? root? ? ? 31, ? 3 Jan? 1 00:00 /dev/mtdblock3
?
/dev/mtd:
crw-rw-rw-? ? 1 root ? ? root? ? ? 90, ? 0 Jan? 1 00:00 0
cr--r--r--? ? 1 root ? ? root? ? ? 90, ? 1 Jan? 1 00:00 0ro
crw-rw-rw-? ? 1 root ? ? root? ? ? 90, ? 2 Jan? 1 00:00 1
cr--r--r--? ? 1 root ? ? root? ? ? 90, ? 3 Jan? 1 00:00 1ro
crw-rw-rw-? ? 1 root ? ? root? ? ? 90, ? 4 Jan? 1 00:00 2
cr--r--r--? ? 1 root ? ? root? ? ? 90, ? 5 Jan? 1 00:00 2ro
crw-rw-rw-? ? 1 root ? ? root? ? ? 90, ? 6 Jan? 1 00:00 3
cr--r--r--? ? 1 root ? ? root? ? ? 90, ? 7 Jan? 1 00:00 3ro
?
/dev/mtdblock:
brw-------? ? 1 root ? ? root? ? ? 31, ? 0 Jan? 1 00:00 0
brw-------? ? 1 root ? ? root? ? ? 31, ? 1 Jan? 1 00:00 1
brw-------? ? 1 root ? ? root? ? ? 31, ? 2 Jan? 1 00:00 2
brw-------? ? 1 root ? ? root? ? ? 31, ? 3 Jan? 1 00:00 3
~ $
可以看到有mtdN和對應的/dev/mtd/N、mtdblockN和對應的/dev/mtdblock/N兩類MTD設備,分別是字符設備,主設備號90和塊設備,主設備號31。其中/dev/mtd0和/dev/mtd/0是完全等價的,/dev/mtdblock0和/dev/mtdblock/0是完全等價的,而/dev/mtd0和/dev/mtdblock0則是同一個MTD分區的兩種不同應用描述,操作上是有區別的。?
/dev/mtdN設備?
/dev/mtdN 是MTD架構中實現的mtd分區所對應的字符設備(將mtd設備分成多個區,每個區就為一個字符設備),其里面添加了一些ioctl,支持很多命令,如MEMGETINFO,MEMERASE等。?
mtd-utils中的flash_eraseall等工具,就是以這些ioctl為基礎而實現的工具,實現一些關于Flash的操作。比如,mtd 工具中 flash_eraseall中:?
if (ioctl(fd, MEMGETINFO, &meminfo) != 0)?
{
?? fprintf(stderr, "%s: %s: unable to get MTD device info\n",exe_name, mtd_device);
?? return 1;
}
MEMGETINFO是Linux MTD中的drivers/mtd/mtdchar.c中的ioctl命令,使用mtd字符設備需要加載mtdchar內核模塊。該代碼解釋了上面的第一個現象。?
/dev/mtdblockN設備?
/dev/mtdblockN,是Flash驅動中用add_mtd_partitions()添加MTD設備分區,而生成的對應的塊設備。MTD塊設備驅動程序可以讓flash器件偽裝成塊設備,實際上它通過把整塊的erase block放到ram里面進行訪問,然后再更新到flash,用戶可以在這個塊設備上創建通常的文件系統。?
而對于MTD塊設備,MTD設備層是不提供ioctl的實現方法的,也就不會有對應的MEMGETINFO命令之類,因此不能使用nandwrite,flash_eraseall,flash_erase等工具去對/dev/mtdblockN去進行操作,否則就會出現上面的現象一,同時也解釋了現象3——用mtd2擦除分區后,在用mtdblock2進行umount就會造成混亂。?
mtd塊設備的大小可以通過proc文件系統進行查看:?
~ $ cat /proc/partitions
major minor? #blocks? name
?
? 31 ? ? 0? ? ? ? 512 mtdblock0
? 31 ? ? 1 ? ? ? 1024 mtdblock1
? 31 ? ? 2 ? ? ? 5632 mtdblock2
? 31 ? ? 3 ? ? ? 9216 mtdblock3
?254 ? ? 0 ? 30760960 mmcblk0 ? ?
?254 ? ? 1 ? 30756864 mmcblk0p1
~ $
后面的兩個是SD塊設備的分區大小。每個block的大小是1KB。?
MTD設備分區和總結
通過proc文件系統查看mtd設備的分區情況:?
~ $ cat /proc/mtd
dev:? ? size ? erasesize? name
mtd0: 00080000 00020000 "boot"
mtd1: 00100000 00020000 "kernel"
mtd2: 00580000 00020000 "roofs70"
mtd3: 00900000 00020000 "app"
~ $
可以發現,實際上mtdN和mtdblockN描述的是同一個MTD分區,對應同一個硬件分區,兩者的大小是一樣的,只不過是MTD設備層提供給上層的視圖不一樣,給上層提供了字符和塊設備兩種操作視圖——為了上層使用的便利和需要,比如mount命令的需求,你只能掛載塊設備(有文件系統),而不能對字符設備進行掛載,否則會出現上面的現象2:無效參數。?
這里對于mtd和mtdblock設備的使用場景進行簡單總結:?
- mtd-utils工具只能應用與/dev/mtdN的MTD字符設備?
- mount、umount命令只對/dev/mtdblockN的MTD塊設備有效?
- /dev/mtdN和/dev/mtdblockN是同一個MTD設備的同一個分區(N一樣)
Linux系統中/dev/mtd與/dev/mtdblock的區別
MTD(memory technology device內存技術設備)是用于訪問memory設備(ROM、flash)的Linux的子系統。MTD的主要目的是為了使新的memory設備的驅 動更加簡單,為此它在硬件和上層之間提供了一個抽象的接口。MTD的所有源代碼在/drivers/mtd子目錄下。我將CFI接口的MTD設備分為四層 (從設備節點直到底層硬件驅動),這四層從上到下依次是:設備節點、MTD設備層、MTD原始設備層和硬件驅動層。
MTD字符驅動程序允許直接訪問flash器件,通常用來在flash上創建文件系統,也可以用來直接訪問不頻繁修改的數據。
MTD塊設備驅動程序可以讓flash器件偽裝成塊設備,實際上它通過把整塊的erase block放到ram里面進行訪問,然后再更新到flash,用戶可以在這個塊設備上創建通常的文件系統。
?
1. /dev/mtdN 是Linux 中的MTD架構中,系統自己實現的mtd分區所對應的字符設備(將mtd設備分成多個區,每個區就為一個字符設備),其里面添加了一些ioctl,支持很多命令,如MEMGETINFO,MEMERASE等。
而mtd-util中的flash_eraseall等工具,就是以這些ioctl為基礎而實現的工具,實現一些關于Flash的操作。比如,mtd 工具中的 flash_eraseall中的:
if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
?? fprintf(stderr, "%s: %s: unable to get MTD device info\n", exe_name, mtd_device);
?? return 1;
}
其中,MEMGETINFO,就是Linux MTD中的drivers/mtd/mtdchar.c中的:
static int mtd_ioctl(struct inode *inode, struct file *file,
?? ? ? u_int cmd, u_long arg)
{
。。。。。
case MEMGETINFO:
?? info.type = mtd->type;
?? info.flags = mtd->flags;
?? info.size = mtd->size;
?? info.erasesize = mtd->erasesize;
?? info.writesize = mtd->writesize;
?? info.oobsize = mtd->oobsize;
?? /* The below fields are obsolete */
?? info.ecctype = -1;
?? info.eccsize = 0;
?? if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
? ? return -EFAULT;
?? break;
。。。
}
而/dev/mtdblockN,是Nand Flash驅動中,驅動用add_mtd_partitions()添加MTD設備分區(其實就是將mtd設備進行不同的分區,當mtd設備還是一樣的,所以mtdblock分區與mtd分區肯定是對應的),而生成的對應的塊設備。
根據以上內容,也就更加明白,為什么不能用nandwrite,flash_eraseall,flash_erase等工具去對/dev/mtdblockN去操作了。因為/dev/mtdblock中不包含對應的ioctl,也就沒有定義對應的命令,不支持你這么操作。
2. mtd char 設備的主設備號是90,而mtd block設備的主設備號是31:
# ls /dev/mtd* -l
crw-r-----? ? 1 root ? ? root? ? ? 90, ? 0 May 30 2007 /dev/mtd0
crw-r-----? ? 1 root ? ? root? ? ? 90, ? 2 May 30 2007 /dev/mtd1
crw-r-----? ? 1 root ? ? root? ? ? 90, ? 4 Jul 17 2009 /dev/mtd2
crw-r-----? ? 1 root ? ? root? ? ? 90, ? 6 May 30 2007 /dev/mtd3
crwxrwxrwx? ? 1 root ? ? root? ? ? 90, ? 8 May 30 2007 /dev/mtd4
crwxrwxrwx? ? 1 root ? ? root? ? ? 90, 10 May 30 2007 /dev/mtd5
crwxrwxrwx? ? 1 root ? ? root? ? ? 90, 12 May 30 2007 /dev/mtd6
crwxrwxrwx? ? 1 root ? ? root? ? ? 90, 14 May 30 2007 /dev/mtd7
crwxrwxrwx? ? 1 root ? ? root? ? ? 90, 16 May 30 2007 /dev/mtd8
crwxrwxrwx? ? 1 root ? ? root? ? ? 90, 18 May 30 2007 /dev/mtd9
# ls /dev/mtdblock* -l
brw-r-----? ? 1 root ? ? root? ? ? 31, ? 0 May 30 2007 /dev/mtdblock0
brw-r-----? ? 1 root ? ? root? ? ? 31, ? 1 May 30 2007 /dev/mtdblock1
brw-r-----? ? 1 root ? ? root? ? ? 31, ? 2 May 30 2007 /dev/mtdblock2
brw-r-----? ? 1 root ? ? root? ? ? 31, ? 3 May 30 2007 /dev/mtdblock3
brwxrwxrwx? ? 1 root ? ? root? ? ? 31, ? 4 May 30 2007 /dev/mtdblock4
brwxrwxrwx? ? 1 root ? ? root? ? ? 31, ? 5 May 30 2007 /dev/mtdblock5
brwxrwxrwx? ? 1 root ? ? root? ? ? 31, ? 6 May 30 2007 /dev/mtdblock6
brwxrwxrwx? ? 1 root ? ? root? ? ? 31, ? 7 May 30 2007 /dev/mtdblock7
brwxrwxrwx? ? 1 root ? ? root? ? ? 31, ? 8 May 30 2007 /dev/mtdblock8
brwxrwxrwx? ? 1 root ? ? root? ? ? 31, ? 9 May 30 2007 /dev/mtdblock9
此設備號,定義在/include/linux/mtd/mtd.h中 :
#define MTD_CHAR_MAJOR ? 90
#define MTD_BLOCK_MAJOR 31
3. 其中,mtd的塊設備的大小,可以通過查看分區信息獲得:
# cat /proc/partitions
major minor #blocks name
31 ? ? 0 ? ? ? 1024 mtdblock0
31 ? ? 1 ? ? ? 8192 mtdblock1
31 ? ? 2 ? ? 204800 mtdblock2
31 ? ? 3? ? ? 65536 mtdblock3
31 ? ? 4 ? ? 225280 mtdblock4
上面中顯示的塊設備大小,是block的數目,每個block是1KB。
而每個字符設備,其實就是對應著上面的每個塊設備。即/dev/mtd0對應/dev/mtdblock0,其他以此類推。換句話說,mtdblockN的一些屬性,也就是mtdN的屬性,比如大小。
4。對每個mtd字符設備的操作,比如利用nandwrite去對/dev/mtd0寫數據,實際就是操作/dev/mtdblock0。
而這些操作里面涉及到的偏移量offset,都指的是此mtd 分區內的偏移。比如向/dev/mtd1的offset為0的位置寫入數據,實際操作的是物理偏移offset=/dev/mtd0的大小=1MB=0x100000。
5.mtd的字符設備和塊設備的命名規則,可以參考下表:
Table 7-1. MTD /dev entries, corresponding MTD user modules, and relevant device major numbers
/dev entry Accessible MTD user module Device type Major number
mtdN char device char 90
mtdrN char device char 90
mtdblockN block device, read-only block device, JFFS, and JFFS2 block 31
nftlLN NFTL block 93
ftlLN FTL block 44
Table 7-2. MTD /dev entries, minor numbers, and naming schemes
/dev entry Minor number range Naming scheme
mtdN 0 to 32 per increments of 2 N = minor / 2
mtdrN 1 to 33 per increments of 2 N = (minor - 1) / 2
mtdblockN 0 to 16 per increments of 1 N = minor
nftlLN 0 to 255 per sets of 16 L = set;[2] N = minor - (set - 1) x 16; N is not appended to entry name if its value is zero.
ftlLN 0 to 255 per sets of 16 Same as NFTL.
The Linux MTD,YAFFS Howto上面這樣寫道:
Erase the mtdblock0
/>eraseall /dev/mtd0
Create the mount directory and mount
/>mkdir -p /mnt/flash0
/>mount -t yaffs /dev/mtdblock0 /mnt/flash0
為什么eraseall對mtd0操作?而不對mtdblock0操作?nand不是塊設備嘛,mtdblock就是塊設備呀。mtd0,mtd1與mtdblock0,mtdblock1是不是一一對應的?
mtd-utils 工具的使用?
一.下載源碼包。
二.編譯
1.修改Makefile ?
CROSS=mipsel-linux-
2.make
3.將編譯生成的可執行文件COPY到開發板上
三.命令的使用
使用命令前用cat /proc/mtd 查看一下mtdchar字符設備;或者用ls -l /dev/mtd*
#cat /proc/mtd
dev:? ? size ? erasesize? name
mtd0: 00c00000 00020000 "ROOTFS"
mtd1: 00200000 00020000 "BOOTLOADER"
mtd2: 00200000 00020000 "KERNEL"
mtd3: 03200000 00020000 "NAND ROOTFS partition"
mtd4: 04b00000 00020000 "NAND DATAFS partition"
為了更詳細了解分區信息用mtd_debug命令
#mtd_debug info /dev/mtdX (不能使用mtdblockX, mtdblockX 只是提供用來 mount 而已)
mtd.type = MTD_NORFLASH
mtd.flags =?
mtd.size = 12582912 (12M)
mtd.erasesize = 131072 (128K)
mtd.oobblock = 1?
mtd.oobsize = 0?
mtd.ecctype = (unknown ECC type - new MTD API maybe?)
regions = 0
命令:flash_erase
作用:擦出指定范圍內flash的內容,如果不指定,默認擦出起始位置的第一塊,使相應flash變為全1
用法:
flash_erase MTD-device [start] [cnt (# erase blocks)] [lock]
MTD-device:待擦出的分區,如/dev/mtd0
start:起始位置設置,這里必須設置為0x20000(128K)的整數倍
cnt: 從start開始計算,要擦出的塊數
lock: 寫保護? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
eg:? ./flash_erase /dev/mtd0 0x40000 5 ? //擦出mtd0分區上從0x40000開始的5塊數據 ,128K/塊
命令:flash_eraseall
作用:擦出整個分區的數據,同時也會作壞塊檢測
用法:
flash_eraseall [OPTION] MTD_DEVICE
-q, --quiet? ? 不顯示打印信息
-j, --jffs2? ? 一jffs2 格式化分區
eg: ./flash_eraseall -j /dev/mtd0?
命令:flashcp
作用:copy 數據到 flash 中
用法:
usage: flashcp [ -v | --verbose ] <filename> <device>
?? ? ? flashcp -h | --help
filename:待寫入的數據
device: 寫入的分區,如/dev/mtd0
eg: ?
filename制作:mkfs.jffs2 -e 0x20000 -d cq8401 -o cq8401.img? -n? //這里的-e 0x20000 必須更你芯片的erasesize 相等
./flashcp cq8401.img /dev/mtd0? // copy cq8401.img文件系統到? /dev/mtd0分區中
當然這個命令的功能跟 dd if=/tmp/fs.img of=/dev/mtd0差不多
命令:nandwrite
作用:向nand flash中寫數據
用法:
nandwrite [OPTION] MTD_DEVICE INPUTFILE
? -a, --autoplace ? ? ? Use auto oob layout
? -j, --jffs2 ? ? ? ? ? force jffs2 oob layout (legacy support)
? -y, --yaffs ? ? ? ? ? force yaffs oob layout (legacy support)
? -f, --forcelegacy ? ? force legacy support on autoplacement enabled mtd device
? -n, --noecc ? ? ? ? ? write without ecc
? -o, --oob ? ? ? ? ? ? image contains oob data
? -s addr, --start=addr set start address (default is 0)
? -p, --pad ? ? ? ? ? ? pad to page size
? -b, --blockalign=1|2|4 set multiple of eraseblocks to align to
? -q, --quiet ? ? ? ? ? don't display progress messages
? ? ? --help? ? ? ? ? ? display this help and exit
? ? ? --version ? ? ? ? output version information and exit
?? ?
eg: ./nandwrite -p /dev/mtd0? /tmp/rootfs.jffs2
命令:nanddump
作用:dump出nand flash一些信息,如:block size,erasesize,oobblock 大小,oob data ,page data等;同時也會作壞塊檢測
用法:
nanddump [OPTIONS] MTD-device
?? ? ? ? ? --help ? ? ? ? ? ? ? display this help and exit
?? ? ? ? ? --version? ? ? ? ? ? output version information and exit
-f file? ? --file=file? ? ? ? ? dump to file
-i ? ? ? ? --ignoreerrors ? ? ? ignore errors
-l length? --length=length? ? ? length
-o ? ? ? ? --omitoob? ? ? ? ? ? omit oob data
-b ? ? ? ? --omitbad? ? ? ? ? ? omit bad blocks from the dump
-p ? ? ? ? --prettyprint? ? ? ? print nice (hexdump)
-s addr? ? --startaddress=addr? start address
eg:./nanddump -p -f nandinfo.txt /dev/mtd0? //dump出nand flash /dev/mtd0數據并保存到 nandinfo.txt?
命令:mtd_debug
作用: 對mtd 調試作用
用法:
usage: mtd_debug info <device>
?? ? ? mtd_debug read <device> <offset> <len> <dest-filename>
?? ? ? mtd_debug write <device> <offset> <len> <source-filename>
?? ? ? mtd_debug erase <device> <offset> <len>
eg:
#./mtd_debug info /dev/mtd0? // 輸出/dev/mtd0上的一些信息,這里必須用mtdx
#./mtd_debug erase /dev/mtd0 0x0 0x40000? // 擦出/dev/mtd0 分區上 從0x0開始的? , 128K*2 大小的數據
#./mtd_debug write /dev/mtdblock0 ox0 0x360810 cq8401.img //向mtdblock0分區,寫入 3.6M 大小的文件系統cq8401.img,這里最好用mtdblockx
#./mtd_debug read? /dev/mtdblock0 ox0 0x360810 read.img? //從mtdblock0中讀出 3.6M 數據保存到read.img
# cmp -l cq8401.img read.img? // 驗證write to flash 和 read from flash 中的數據是否一致;也可以使用diff命令來比較
另外針對nand flash,mtd_debug這個工具來測試mtd驅動也不是很好,用nandwrite和nanddump這兩個工具或許更好點。然后可以用cmp這個命令來比較一下nanddump出來的數據和nandwrite寫入的數據是否一致。
命令:ftl_format
解釋:In order to use one of conventional file systems (Ext2, ext3, XFS, JFS, FAT) over an MTD device, you need a software layer which emulates a block device over the MTD device. These layers are often called Flash Translation Layers (FTLs).
例一:如何測試nor flash 驅動
step1:
#./mtd_debug info /dev/mtd0? // 輸出/dev/mtd0上的一些信息,這里必須用mtdx
step2:
#./mtd_debug erase /dev/mtd0 0x0 0x40000? // 擦出/dev/mtd0 分區上 從0x0開始的? , 128K*2 大小的數據
step3:
#./mtd_debug write /dev/mtdblock0 ox0 0x360810 cq8401.img //向mtdblock0分區,寫入 3.6M 大小的文件系統cq8401.img,這里最好用mtdblockx
step4:
#./mtd_debug read? /dev/mtdblock0 ox0 0x360810 read.img? //從mtdblock0中讀出 3.6M 數據保存到read.img,當然這里的長度應該相等
step5:
# cmp -l cq8401.img read.img? // 驗證write to flash 和 read from flash 中的數據是否一致;也可以使用diff命令來比較
例二:如何測試nand flash 驅動
其實nand flash 驅動同樣可以用例一的方法測試,但既然有nandwrite,nanddump命令,為何不用呢!
step1:
#./flash_eraseall -j /dev/mtd1? ? ? ? //用jffs2格式化該分區
step2:
#./nanddump -p? /dev/mtd1? //dump出nand flash /dev/mtd1數據,可以看到現在的數據全是ff
step3:
#./nandwrite -p ? /dev/mtd1 cq8401.img? // 將cq8401.img文件系統寫入mtd0分區
step4:
#./nanddump -p? /dev/mtd1? //dump出nand flash /dev/mtd1數據,可以看到現在的數據不再是全ff
例三:如何用mtd-util 工具向nand flash寫入文件系統jffs2.img,并修改啟動參數,使文件系統從nand flash 啟動;假設已分好區,mtd0為文件系統分區
方式一:
step1:
NFS起文件系統
#./flash_eraseall -j /dev/mtd0? ? ? ? //用jffs2格式化該分區
#./nandwrite -j -f -p -q /dev/mtd0 jffs2.img? // 將jffs2.img文件系統寫入mtd0分區
step2:
然后再看看我們新寫入的JFFS2文件系統能不能mount上.
#mount -t jffs2 /dev/mtdblock0 /mnt
#ls /mnt
setp3:
重啟開發板,在U-BOOT里 設置啟動參數
#setenv bootargs 'mem=64M console=ttyS0,115200n8 ip=192.168.4.201:::::eth0:off? root=/dev/mtdblock0 rootfstype=jffs2 rw'
#reset
方式二:
NAND 起內核,NAND起文件系統
1. 網起文件系統
nerase 0 55 && nprog 0 192.168.4.200 n-boot.bin.hg && nprog 128 192.168.4.200 zImage-6pci && reset
2.進入網起的文件系統
cat /proc/mtd
3. 制作JIFFS的文件系統
mkfs.jffs2 -e 0x20000 -d root-vw -o dvr20000.img? -n
4.
cp dvr20000.img /dev/mtdblock1
5.修改NAND BOOT啟動參數 include/cq8401_board.h
修改NAND BOOT
setenv bootargs 'mem=64M console=ttyS0,115200n8 ip=192.168.4.201:::::eth0:off? root=/dev/mtdblock1 rootfstype=jffs2 rw'
6.? 從新燒寫
nerase 0 55 && nprog 0 192.168.4.200 n-boot.bin.local && nprog 128 192.168.4.200 zImage-6pci && reset
例四:
如何將一個 .tar.gz文件系統? 寫到 nor 或者 nand flash中
?? target$ mkdir /mnt/flash? ? ?
?? target$ mount -t jffs2 /dev/mtdblock0 /mnt/flash? (mtdblockx只是用來掛載的)
?? target$ cd /mnt/flash
?? target$ tar zxvf rootfs.tar.gz
mtd命令及制作ubi鏡像做根文件系統?
2013-09-25 17:22 2315人閱讀 評論(0) 收藏 舉報
在linux2.6.28后才加入對ubifs的支持
1 查看nand分區
root@ubuntu:~# cat /proc/mtd
dev:? ? size ? erasesize? name
mtd0: 00020000 00020000 "U-Boot-min"
mtd1: 00240000 00020000 "U-Boot"
mtd2: 00020000 00020000 "U-Boot Env"
mtd3: 00440000 00020000 "Kernel"
mtd4: 1f400000 00020000 "File System"
mtd5: 00540000 00020000 "Reserved"
root@ubuntu:~# cat /proc/partitions?
major minor? #blocks? name
? 31? ? ? ? 0? ? ? ? 128 mtdblock0
? 31? ? ? ? 1 ? ? ? 2304 mtdblock1
? 31? ? ? ? 2? ? ? ? 128 mtdblock2
? 31? ? ? ? 3 ? ? ? 4352 mtdblock3
? 31? ? ? ? 4 ? ? 512000 mtdblock4
? 31? ? ? ? 5 ? ? ? 5376 mtdblock5
root@ubuntu:~#?
2、查看mtd4的信息?
root@ubuntu:~# mtdinfo -m 4 -u
mtd4
Name: ? ? ? ? ? ? ? ? ? ? ? ? ? File System
Type: ? ? ? ? ? ? ? ? ? ? ? ? ? nand
Eraseblock size:? ? ? ? ? ? ? ? 131072 bytes, 128.0 KiB
Amount of eraseblocks:? ? ? ? ? 4000 (524288000 bytes, 500.0 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size:? ? ? ? ? ? ? ? ? 512 bytes
OOB size: ? ? ? ? ? ? ? ? ? ? ? 64 bytes
Character device major/minor: ? 90:8
Bad blocks are allowed: ? ? ? ? true
Device is writable: ? ? ? ? ? ? true
Default UBI VID header offset:? 512
Default UBI data offset:? ? ? ? 2048
Default UBI LEB size: ? ? ? ? ? 129024 bytes, 126.0 KiB
Maximum UBI volumes count:? ? ? 128
root@ubuntu:~# mtdinfo -m 2 -u?
或
root@ubuntu:~# mtdinfo /dev/mtd4
mtd2
Name: ? ? ? ? ? ? ? ? ? ? ? ? ? U-Boot Env
Type: ? ? ? ? ? ? ? ? ? ? ? ? ? nand
Eraseblock size:? ? ? ? ? ? ? ? 131072 bytes, 128.0 KiB? ? // FLASH物理擦除塊大小
Amount of eraseblocks:? ? ? ? ? 1 (131072 bytes, 128.0 KiB)
Minimum input/output unit size: 2048 bytes? ? 1)nor flash:通常是1個字節? 2)nand falsh:一個頁面?
Sub-page size:? ? ? ? ? ? ? ? ? 512 bytes? //對于nand flash來說,子頁大小?
OOB size: ? ? ? ? ? ? ? ? ? ? ? 64 bytes
Character device major/minor: ? 90:4
Bad blocks are allowed: ? ? ? ? true
Device is writable: ? ? ? ? ? ? true
Default UBI VID header offset:? 512
Default UBI data offset:? ? ? ? 2048
Default UBI LEB size: ? ? ? ? ? 129024 bytes, 126.0 KiB? //邏輯擦除塊大小
Maximum UBI volumes count:? ? ? 128
mtd4大小為500MiB,擦除單元大小(一般即為塊大小)為128KiB,名字是"NAND simulator partition 0"。 NandFlash
擦除是以塊(block)為單位,讀寫是以頁(page)為單位。
3 root@ubuntu:~# ls -lah /dev/mtd*
crw------- 1 root root 90,? 0 Jan? 1 00:00 /dev/mtd0 //字符設備
crw------- 1 root root 90,? 1 Jan? 1 00:00 /dev/mtd0ro
crw------- 1 root root 90,? 2 Jan? 1 00:00 /dev/mtd1
crw------- 1 root root 90,? 3 Jan? 1 00:00 /dev/mtd1ro
crw------- 1 root root 90,? 4 Jan? 1 00:00 /dev/mtd2
crw------- 1 root root 90,? 5 Jan? 1 00:00 /dev/mtd2ro
crw------- 1 root root 90,? 6 Jan? 1 00:00 /dev/mtd3
crw------- 1 root root 90,? 7 Jan? 1 00:00 /dev/mtd3ro
crw------- 1 root root 90,? 8 Jan? 1 00:00 /dev/mtd4
crw------- 1 root root 90,? 9 Jan? 1 00:00 /dev/mtd4ro
crw------- 1 root root 90, 10 Jan? 1 00:00 /dev/mtd5
crw------- 1 root root 90, 11 Jan? 1 00:00 /dev/mtd5ro
brw-rw---- 1 root disk 31,? 0 Jan? 1 00:00 /dev/mtdblock0? //塊設備,與mtd0對應
brw-rw---- 1 root disk 31,? 1 Jan? 1 00:00 /dev/mtdblock1
brw-rw---- 1 root disk 31,? 2 Jan? 1 00:00 /dev/mtdblock2
brw-rw---- 1 root disk 31,? 3 Jan? 1 00:00 /dev/mtdblock3
brw-rw---- 1 root disk 31,? 4 Jan? 1 00:00 /dev/mtdblock4
brw-rw---- 1 root disk 31,? 5 Jan? 1 00:00 /dev/mtdblock5
root@ubuntu:~#?
4.?
關于mtd工具集的安裝
? ? sudo apt-get install mtd-utils
UBI文件系統鏡像文件的制作
@ubuntu:~$ sudo mkfs.ubifs -r targetfs -m 2048 -e 129024 -c 3900 -o ubifs.img
@ubuntu:~$ sudo ubinize -o ubi.img -m 2048 -p 128KiB -s 512 ubinize.cfg
關于mkfs.ubifs參數的算法
? -m minimum I/O unit size
? -e, --leb-size=SIZE? ? ? logical erase block size
? -c maximum logical erase block count
? -x compression type - "lzo", "favor_lzo", "zlib" or "none" (default: "lzo")
? -p size of the physical eraseblock of the flash this UBI image is created for in bytes
wear_level_reserved_blocks is 1% of total blcoks per device
*logical_erase_block_size* is physical erase block size minus 2 pages for UBI
Block size = page_size * pages_per_block
physical blocks on a partition = partition size / block size
Logical blocks on a partition = physical blocks on a partitiion - reserved for wear level
File-system volume = Logical blocks in a partition * Logical erase block size
關于參數可以參考attach的命令輸出:
root@ubuntu:~# ubiattach? /dev/ubi_ctrl -m 4 -d 0
UBI device number 0, total 4000 LEBs (516096000 bytes, 492.2 MiB), available 0 LEBs (0 bytes), LEB
size 129024 bytes (126.0 KiB)
root@ubuntu:~#?
ubinize.cfg文件
[ubifs]
mode=ubi
image=ubifs.img
vol_id=0
vol_size=450MiB
vol_type=dynamic
vol_alignment=1
vol_name=rootfs
vol_flags=autoresize
5. UBI文件系統鏡像在Linux下的燒寫
flash_eraseall /dev/mtd4
ubiformat /dev/mtd4 -s 512 -f /xxx/ubi.img
6、 UBI文件系統鏡像在U-BOOT下的燒寫
//load ubi image to RAM
tftp ubi.img
//erase MTD4 nand space
nand erase 0x6c0000 0xc820000
//write image to nand
nand write.i 0x81000000 0x6c0000 0xxxxx(image size)
7. UBI文件系統鏡像在Linux下的掛載和卸載
掛載
ubiattach /dev/ubi_ctrl -m 4 -d 0
mount -t ubifs ubi0_0 /mnt/ubi
卸載
umount /mnt/ubi
ubidetach -d 0
8、使用ubi做根文件系統
需要在bootargs中設置如下信息:
? root=ubi0:rootfs ubi.mtd=4 rootfstype=ubifs
?配置linux內核
?? ? ? ? ? 配置的時候選上
? ? ? ? ? 1)Device Drivers? --->Memory Technology Device (MTD) support? --->UBI - Unsorted block images? --->Enable UBI
? ? ? ? ? 2)File systems? --->Miscellaneous filesystems? --->UBIFS file system support
? ? ? ? ? 這樣我們的內核就支持UBIFS文件系統了