【文件系统异常】升级导致文件系统异常总结

文件系统异常原因:设备存在坏块,导致写入内容错位,设备存在坏块,坏块的位置无法正常写入

目前我们路由器设备使用Nandflash内存的型号有 UR3X、UR5X

一、坏块的原因

NAND Flash产生坏块原因
由于NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生产中及使用过程中会产生坏块。坏块的特性是:当编程/擦除这个块时,不能将某些位拉高,这会造成Page Program和Block Erase操作时的错误,相应地反映到Status Register的相应位。

二、坏块的种类
1.固有坏块
这是生产过程中产生的坏块,一般芯片原厂都会在出厂时都会将坏块第一个page的spare area的第1个或者6个byte标记为不等于0xff的值,标记在哪一位是根据page的大小决定的。
2.使用中产生的坏块
这是在NAND Flash使用过程中,如果Block Erase或者Page Program错误,就可以简单地将这个块作为坏块来处理,这个时候需要把坏块标记起来。为了和固有坏块信息保持一致,将新发现的坏块的第一个page的spare area的第1个或者6个Byte标记为非0xff的值。

 

我们了解了NAND Flash出厂时在spare area中已经反映出了坏块信息,因此,如果在擦除一个块之前,

① 一定要先check一下spare area的第1或者第6个byte是否是0xff,如果是就证明这是一个好块,可以擦除;

② 如果是非0xff,那么就不能擦除。当然,这样处理可能会犯一个错误―――“错杀伪坏块”,因为在芯片操作过程中可能由于电压不稳定等偶然因素会造成NAND操作的错误。但是,为了数据的可靠性及软件设计的简单化,我们就要奉行“蒋委员长”的“宁可错杀一千,也决不放过一个”的宗旨。
补充说明:
  1.需要对前面由于Page Program错误发现的坏块进行一下特别说明。如果在对一个块的某个page进行编程的时候发生了错误就要把这个块标记为坏块,首先就要把其他好的page里面的内容备份到另外一个空的好块里面,然后,把这个块标记为坏块。当然,这可能会犯“错杀”之误,一个补救的办法,就是在进行完页备份之后,再将这个块擦除一遍,如果Block Erase发生错误,那就证明这个块是个真正的坏块,那就毫不犹豫地将它打个“戳”吧! (也就是双重验证证明当前的块是坏块)
  2.可能有人会问,为什么要使用spare area的第一个或者第六个byte作为坏块标记。这是NAND Flash生产商的默认约定的,但是也不一定必须得是第一或者第六个byte,只是这两者情况用的比较多而已。

三、路由器文件系统异常根本原因

eg.

当前我们的路由器设备,先有uboot系统后才往内烧录ext2文件,最后才能进行升级bin文件

烧录ext2文件时候 烧录的过程是一整片一整片的烧录到固定的位置,ext2的烧录内容=(bin的内容+填充内容)

填充的部分是预留的为了以后有新功能扩展的时候能够使用是固定的大小接在位置镜像内容的后面,如果说当前有坏块,则写内容会往后移动,那对应的填充内容部分也会往后移动,比如假设我们的kernel大小是7M,此时如果一个坏块是128k,则最后的位置是7M+128k

但是我们升级的时候 使用的是bin文件

(烧录是一块一块的升级先升级完dtb、再升级kernel、接着升级rootfs,然后解压升级工具压缩包)

这时候的烧录根据镜像真实的大小写到哪里就到哪里,但是原先的ext2的填充还是存在,

但是我们读取文件的位置是固定的 如上图划分的那样,倘若当前的划分区域存在坏块,则会出现以下的情况出现

因此,我们可以知道 引起文件系统异常的根本原因:系统读取数据和写入数据的位置不一致导致文件系统读取异常

修改内容:

原先我们写reserved区域的时候使用的命令是dd,dd只能 if 接指定文件,of 接硬盘符,遇到坏块直接无法正常写入,现在使用dd命令改为mtd命令处理,则当前可以跳过坏块进行读写,除非遇到当前坏块大小超过整个存储空间大小的情况,才会无法正常写入

 

四、如何标记正常的块为坏块模拟坏块问题的产生

使用dmesg命令我们可以从中发现当前的分区情况如下

 
[    1.175148] 0x00000 0000000-0x0000 00040000 : "dtb"  
[    1.183245] 0x00000 0040000-0x0000 00700000 : "kernel"
[    1.192491] 0x00000 0700000-0x0000 07a00000 : "rootfs"
[    1.204027] mtd: device 2 (rootfs) set to be root filesystem
[    1.214492] 1 squashfs-split partitions found on MTD device rootfs
[    1.220817] 0x0000 01be0000-0x0000 07a00000 : "rootfs_data"
[    1.232020] 0x0000 07a00000-0x0000 07f00000 : "backup"
[    1.241297] 0x0000 07f00000-0x0000 08000000 : "reserved"
[    1.250258] gpmi-nand 1806000.gpmi-nand: driver registered.

  

已知当前的分区地址,一块地址是128 k,那么怎么知道下一个地址是什么?

如标记坏块在第一个dtb块

如果要计算当前的区域大小可以这样计算

16进制转换成10进制,计算一下大小可以这样计算单位是B,再除以1024把单位变成k 大小一共是 256k 一块固定是128k,可以算出是多少块 根据dtb

可以计算出当前有2块

 

dtb的地址是0000000 - 00040000  因为当前是2块 所以可以知道中间有一块地址是00020000

进入uboot模式 

1、标记坏块

=> nand markbad off 00020000

block 0x00000000 successfully marked as bad

block 0x00020000 successfully marked as bad

2、查询当前的坏块

=> nand bad    

3、擦除坏块标记

=> nand scrub -y 0xa0000 0x20000

NAND scrub: device 0 offset 0xa0000, size 0x20000

 

please enter erase passwd:ursalink521125

Erasing at 0xa0000 -- 100% complete.

OK

 擦除坏块第一个是要擦除的起始地址 后面是要擦除的位置大小                

 

在uboot下 nand 可以直接看到当前nand的用法

 

 

经过实验,如果坏块区域在dtb 则系统直接异常

因为当前uboot的写是会跳过坏块去写,但是读是按照固定位置去读的,因为坏块所以dtb写到了kernel的占位,当前的kernel读到的内容是dtb的内容导致当前系统异常 无法正常启动

posted @ 2020-01-02 15:55  陈晓猛  阅读(957)  评论(0编辑  收藏  举报