Nandflash关于文件丢失导致启动卡死的解决方案
335x 系列使用 nandflash 作为存储芯片,启动的镜像和数据都保存在 nandflash 上。
nandflash相对于 emmc 来说,成本较低,但是 nandflash 本身也存在丢失数据的概率,这是由于 nandflash 本身的特性导致的。
一般来说,无法启动的原因:频繁的存储数据(log 日志),如果在存储过程突然断电,数据会有概率丢失,一旦文件系统丢失了关键文件,就会影响系统的启动。
解决方法有如下三种:
- 硬件上添加断电保护电路
- 新建分区,软件上实现系统分区和数据分区的分离
- 分区域保护
本篇文章主要从软件层面讲解第二、三种方法:
软件上实现系统分区和数据分区的分离
- 新建一个分区(以 335xd-1G 为例):
内核代码修改:arch/arm/mach-omap2/board-am335xevm-xd.c(或 xs.c 或 xs2.c)
涉及函数:am335x_nand_partitions[]
红框为添加修改代码,给文件系统分配 210MiB 的空间,剩下的为用户分区
重新编译内核,替换原来的 uImaga。
- 重新生成 200MiB 大小的文件系统
我们默认有八个分区,将文件系统放入最后一个分区,文件系统分区大小为 900 多兆
因此,文件系统制作也制作成 900M,如果这时修改分区或者新添分区,就会导致文件系统的分区变小,文件系统就挂载不上,导致无法正常启动。
制作文件系统用到的文件:Linux\ 源码 \ 系统源码 \rootfs\prebuilt 目录下的
所以需要重新打包文件系统镜像,解决方法如下:
原 ubinize-1G.cfg
修改成
(注意:vol_size 不能大于内核设置的 210MiB)
然后按照 335x 软件手册 4.3.1 节 UBI 文件系统的制作,重新生成文件系统镜像,替换原来的 ubi.img
- 挂载分区,按照如下步骤挂载分区:
先查看刚刚新建的 Userfile 分区是否成功
擦除:flash_eraseall /dev/mtd8
添加分区:
ubiattach /dev/ubi_ctrl -m 8 -O 4096 -d 1(注意:256Mnand 为 2048)
ubimkvol /dev/ubi1 -N ubifs -s 200MiB
创建挂载分区并挂载:
mkdir /rootfs
mount -t ubifs ubi1_0 /rootfs/
Sync
再次启动系统时。重新挂载分区
可以将这两条命令加载到 qt.sh 脚本执行
ubiattach /dev/ubi_ctrl -m 8 -O 4096
root@ok335x:~# mount -t ubifs ubi1_0 /rootfs/
分区域保护
对 NAND 进行合理规划,如 Bootloader、内核、文件系统等不同分区,并对各不同分区设置不同的 mask_flags。对于 Bootloader、内核分区,可以设置 mask_flags 为 MTD_WRITEABLE,禁止该 MTD 分区的可写属性,实现这些分区只读, 防止在系统中意外误操作这些分区。
方法如下:arch/arm/mach-omap2/board-am335xevm-xd.c(xs.c 或者 xs2.c 对应板子)
nand 分区配置如下
设置了 mask_flags 的分区,在进入系统后,将无法用 flash_erase 命令擦除该分区, 也无法改写该分区的数据, 从而保护该分区的数据。例如:
对于文件系统分区,则不能通过 mask_flags 来设置只读实现分区保护。不过可以通过修改 /etc/fatab 文件来挂载只读的文件系统:
将 defaults 默认修改成 ro只读:
加了 ro 启动的系统都是只读的,对文件系统进行任何改写都会提示 “Read-only filesystem”,例如:
对这样的只读系统,如果要进行系统修改,可用 mount 命令经系统重新以可写方式挂载:
如果一个系统全部都是只读属性,在实际应用中会很不友好,如果用户需要存储数据,建议单独分出一个 MTD 分区为好,并将这个 MTD 分区单独挂载到文件系统的某个目录。