知方号

知方号

Jffs2文件系统的制作及使用

Jffs2文件系统的制作及使用

为什么使用Jffs2?

在嵌入式系统中,为加速启动,核心的根文件系统会使用RamFs,一般会放到RAM中,但是这种文件系统一般是掉电丢失的,因为存储在Ram中。但实际应用中有一些配置文件是需要非易失特性的,主要用于配置应用程序。因此,一般的嵌入式产品的文件系统是多种格式共存的,核心的Rootfs使用ramfs,可以加速系统运行速度,一些需要非易失性的配置文件一般使用Jffs2(norflash做为存储介质时)或者yffs2(nandflash做为存储介质时)文件系统。 Jffs2(Journalling Flash FileSystem Version2)文件系统专为嵌入式系统设计,存储介质主要是NorFlash或者NandFlash,是一种简单非易失性的文件系统。

分区是啥?

我们习惯将大的复杂的东西划分为小的简单的东西,就像你买个衣橱,会把衣橱按照功能划分成几个区域(有放上衣的、有放裤子的)。利用信息存储空间也一样,当你拿到一个256G硬盘的时候,你很自然地会按照功能分出几个空间来—–分区。一般会有安装OS的盘、软件的盘、资料盘、游戏盘。这样会有几个好处—易查找、故障隔离,好了,通俗地讲:好找资料、一个分区如果出了问题,一般不会影响到别的分区。硬盘的分区信息是被存储到硬盘的0磁道0柱面1扇区的DPT(Disk Partition Table硬盘分区表)。说的直白点就是画出几个范围,大家互相不干扰,这些分区作为OS格式化文件系统的最小单位。 Jffs2文件系统的存储介质一般是norflash,也可以划分分区,但这些分区并不保存到norflash上。只是BootLoader和kernel的之间的一种约定。嵌入式系统中的分区一般分为:u-boot、u-boot环境变量、kernel、dtb、rootfs、其他一些设计需要的分区。 说了这么多,来点实际的: 我的板子上有个128M的norflash,然后分了6个分区。 fe8000000.flash: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000001 Chip ID 0x002801 Amd/Fujitsu Extended Query Table at 0x0040 Amd/Fujitsu Extended Query version 1.5. number of CFI chips: 1 6 cmdlinepart partitions found on MTD device fe8000000.flash Creating 6 MTD partitions on "fe8000000.flash": 0x000000000000-0x000006e00000 : "uboot" 0x000006e00000-0x000006e20000 : "kernel" 0x000006e20000-0x000006e40000 : "dtb" 0x000006e40000-0x000006e60000 : "jffs2" 0x000005000000-0x000005300000 : "test" 0x000005300000-0x000008000000 : "fs"

嵌入式系统下所有的norflash、nandflash等存储设备都被抽象成mtd存储设备。上面分区的u-boot对应系统下的dev/mtdblock0,test分区代表dev/mtdblock4。 fdisk -l |grep mtd

Disk /dev/mtdblock0: 110 MiB, 115343360 bytes, 225280 sectors Disk /dev/mtdblock1: 128 KiB, 131072 bytes, 256 sectors Disk /dev/mtdblock2: 128 KiB, 131072 bytes, 256 sectors Disk /dev/mtdblock3: 128 KiB, 131072 bytes, 256 sectors Disk /dev/mtdblock4: 3 MiB, 3145728 bytes, 6144 sectors Disk /dev/mtdblock5: 45 MiB, 47185920 bytes, 92160 sector

分区有了,我们就可以制作文件系统了。 mkfs.mkfs.jffs2 /dev/mtdblock4 好像很明朗了,分区是制作文件系统的最小单位。就是说你可以把/dev/mtdblock3格式化成ext2格式的文件系统,同时把/dev/mtdblock4格式化成jffs2格式的文件系统。 下面的章节会详细说明制作jffs2文件系统并尽量说明白u-boot、kernel和文件系统的关系以及使用方法。

u-boot下的分区和Linux下的分区的联系和区别

从上面的描述看到,分区就说约定了怎么划分存储空间的一种说法而已。那就顺便带出了几个问题,u-boot下怎么划分分区?需要将分区信息存储吗?kernel怎么分区?u-boot下分区和kernel下分区有什么区别和联系呐? u-boot下有时候也有分区的概念,但u-boot下的分区的概念和linux下不太一样,linux下主要是用于将一个block设备从物理这个层面上划分为几个分区,是系统格式化成不同文件系统的最小单元。 但在u-boot下只是一个地址范围,仅仅表示起始、结束地址而已。其实也差不多了,一样的目的只是表示的方法不一样罢了。

在代码里写死(此方法已经不使用,dts替代)。使用dts文件创建分区。在u-boot下使用cmdline传参(bootargs->mtdparts),且cmdline的优先级较高,即如果dtb设置了mtd 分区,但同时cmdline也设置了分区则,cmdline设置的分区会覆盖掉kernel设置的分区。以mtdparts设置的为最后的设置内容。

我们使用cmdline传参数的方法来做说明。 setenv bootargs "root=/dev/ram rw console=ttyS0,115200 ramdisk_size=70000000 mtdparts=fe8000000.flash:110m(uboot),128k(kernel),128k(dtb),128k(jffs2),3m@0x5000000(test),-(fs)" 使用环境变量mtdparts,具体说明见u-boot官网。 总之,u-boot里划分的存储设备分区和kernel需一致,这样在u-boot里升级固件会方便一些。因为我们在开发阶段,会使用HOST开发主机制作文件系统,然后烧录到指定的分区,kernel启动后可以mount该分区,从而读写文件。

怎么制作Jffs2文件系统?

制作jffs2文件系统很简单。 mkfs.jffs2 -r ./jaffs2_rootfs -o rootfs.jaffs2 -pad 0x300000 -b -n 具体参数 mkfs.jffs2 --help

使用Jffs2

我们得将制作好的jffs2格式的文件系统烧写到norflash上,烧录到那个分区?那个位置?客官别着急,我们看下我们的分区咋划分的,上面的mtdparts=tdparts=fe8000000.flash:110m(uboot),128k(kernel),128k(dtb),128k(jffs2),3m@0x5000000(test),-(fs) 我们计划使用test这个分区来做测试。可以看到test分区大小是3M,且起始地址在norflash的0x5000000的offset处。而且我们的flash存储映射到CPU线性地址0xfe8000000开始的地方,从CPU侧来看的线性地址为:0xfe8000000+0x5000000=0xfed000000。test这个分区的基地址=fe8000000,加上offset=0x5000000 因此地址=0xfed000000,其中在CPU侧来操作nor flash 时,操作的地址为0xed000000,0xfed000000为内部addr bus地址,该CPU是一个32bit指令集,32bit data bus,64bit address bus的IC,在指令集这一层面来看,操作的存储器地址32bit,CPU内部做移位。 启动系统后,可以查看test分区对应的/dev/mtdblock4。 fdisk -l /dev/mtdblock4 Disk /dev/mtdblock4: 3 MiB, 3145728 bytes, 6144 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes

系统启动log里面test分区的range: 0x000005000000-0x000005300000 : "test" 对应到CPU那一侧的操作地址range: 0x0000ed000000-0x0000ed300000

好,烧录到那个位置知道了,下面开始烧录。 usb start;fatload usb 0 1000000 jaffs2_rootfs· protect off 0xed000000 +$filesize;erase 0xed000000 +$filesize;cp.b 1000000 0xed000000 $filesize;protect on 0xed000000 +$filesize 不同开发环境的烧录方法可能不一样,但是大致思路是将生成的jffs2文件系统的image烧录到指定的offset上。 然后启动kernel,启动后: mkdir test mount -t jffs2 /dev/mtdblock4 test/

mount |grep jffs2 /dev/mtdblock4 on /home/root/test type jffs2 (rw,relatime)

df -h Filesystem Size Used Avail Use% Mounted on /dev/root 202M 83M 109M 44% / devtmpfs 2.0G 4.0K 2.0G 1% /dev tmpfs 2.0G 168K 2.0G 1% /run tmpfs 2.0G 156K 2.0G 1% /var/volatile /dev/sda1 3.5G 859M 2.6G 25% /run/media/sda1 /dev/mtdblock4 3.0M 388K 2.7M 13% /home/root/test

附录 dts 中的norflash分区

nor@0,0 { #address-cells = ; #size-cells = ; compatible = "cfi-flash"; reg = ; bank-width = ; device-width = ;

` partition@0 { reg = ; label = "RCW"; read-only; }; partition@20000 { reg = ; label = "kernel"; }; partition@800000 { reg = ; label = "DTB"; }; partition@a00000 { reg = ; label = "File system"; }; };` mtdpart 设置 setenv bootargs "root=/dev/ram rw console=ttyS0,115200 ramdisk_size=70000000 mtdparts=fe8000000.flash:110m(uboot),128k(kernel),128k(dtb),128k(jffs2),3m@0x5000000(test),-(fs)"

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。