首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >U引导'nand标记‘没有影响。

U引导'nand标记‘没有影响。
EN

Stack Overflow用户
提问于 2019-09-24 14:56:05
回答 1查看 1.1K关注 0票数 2

情境:董事会有一个手臂CPU,它旁边有Nand闪存。在电源启动时,U引导引导程序启动并将闪存内容复制到RAM中,然后将控制转移到RAM中的代码。一个具有一些应用程序代码的Linux系统,通过Buildroot组成,开始运行。它的整个文件系统作为一个UBIFS文件存储在闪存中,并开始使用该文件。

当设置某个字节时,引导加载程序保持控制,并启动TFTP传输以下载和存储新的闪存映像。

扳机:一块板坏了。Linux内核启动清楚地显示了这个问题:

代码语言:javascript
复制
[    1.931150] Creating 8 MTD partitions on "atmel_nand":
[    1.936285] 0x000000000000-0x000000040000 : "at91bootstrap"
[    1.945280] 0x000000040000-0x0000000c0000 : "bootloader"
[    1.954065] 0x0000000c0000-0x000000100000 : "bootloader env"
[    1.963262] 0x000000100000-0x000000140000 : "bootloader redundant env"
[    1.973221] 0x000000140000-0x000000180000 : "spare"
[    1.981552] 0x000000180000-0x000000200000 : "device tree"
[    1.990466] 0x000000200000-0x000000800000 : "kernel"
[    1.999210] 0x000000800000-0x000010000000 : "rootfs"
...
[    4.016251] ubi0: attached mtd7 (name "rootfs", size 248 MiB)
[    4.022181] ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
[    4.029040] ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
[    4.035941] ubi0: VID header offset: 2048 (aligned 2048), data offset: 4096
[    4.042960] ubi0: good PEBs: 1980, bad PEBs: 4, corrupted PEBs: 0
[    4.049033] ubi0: user volume: 2, internal volumes: 1, max. volumes count: 128
[    4.056359] ubi0: max/mean erase counter: 2/0, WL threshold: 4096, image sequence number: 861993884
[    4.065476] ubi0: available PEBs: 0, total reserved PEBs: 1980, PEBs reserved for bad PEB handling: 36
[    4.074898] ubi0: background thread "ubi_bgt0d" started, PID 77
...
[    4.298009] UBIFS (ubi0:0): UBIFS: mounted UBI device 0, volume 0, name "rootfs", R/O mode
[    4.306415] UBIFS (ubi0:0): LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
[    4.316418] UBIFS (ubi0:0): FS size: 155926528 bytes (148 MiB, 1228 LEBs), journal size 9023488 bytes (8 MiB, 72 LEBs)
[    4.327197] UBIFS (ubi0:0): reserved for root: 0 bytes (0 KiB)
[    4.333095] UBIFS (ubi0:0): media format: w4/r0 (latest is w5/r0), UUID AE9F77DC-04AF-433F-92BC-D3375C83B518, small LPT model
[    4.346924] VFS: Mounted root (ubifs filesystem) readonly on device 0:15.
[    4.356186] devtmpfs: mounted
[    4.367038] Freeing unused kernel memory: 1024K
[    4.371812] Run /sbin/init as init process
[    4.568143] UBIFS (ubi0:1): background thread "ubifs_bgt0_1" started, PID 83
[    4.644809] UBIFS (ubi0:1): recovery needed
[    4.685823] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 235:4096, read only 126976 bytes, retry
[    4.732212] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 235:4096, read only 126976 bytes, retry
[    4.778705] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 235:4096, read only 126976 bytes, retry
[    4.824159] ubi0 error: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 235:4096, read 126976 bytes

..。这会导致异常,但是内核继续运行,然后检测到另一个错误:

代码语言:javascript
复制
[    5.071518] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 709:4096, read only 126976 bytes, retry
[    5.118110] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 709:4096, read only 126976 bytes, retry
[    5.164447] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 709:4096, read only 126976 bytes, retry
[    5.210987] ubi0 error: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 709:4096, read 126976 bytes

..。但令人印象深刻的是,这套系统仍然活跃起来,表现得几乎很好。为什么内核不把这些闪存块标记为坏的呢?这些数据无论如何都无法读取,至少下一个图像闪烁可能会跳过坏块.

调查:所以内核在闪存的"rootfs“分区中发现了一个缺陷的PEB #235 (十进制)。每个PEB为128 is,因此错误位于字节30,801,920 (十进制)以外的某个位置。由于"rootfs“分区仅从闪存的字节0x800000开始,实际损坏的页面必须超出字节39,190,528 (十进制)或0x2560000。当然,在U中使用nand读取实用程序时:

代码语言:javascript
复制
U-Boot> nand read 0x20000000 0x2560000 0x1000
NAND read: device 0 offset 0x2560000, size 0x1000
 4096 bytes read: OK
U-Boot> nand read 0x20000000 0x2561000 0x1000
NAND read: device 0 offset 0x2561000, size 0x1000
 4096 bytes read: OK
U-Boot> nand read 0x20000000 0x2562000 0x1000
NAND read: device 0 offset 0x2562000, size 0x1000
PMECC: Too many errors
NAND read from offset 2562000 failed -5
 0 bytes read: ERROR

所以损坏的页面位于闪存块内的偏移量8K处。从其他各种帖子中,我了解到nand闪存具有128K块的2K页面,在每2048个有效负载字节上有64个额外的“带外”字节,使每个页面的总大小达到2112字节。无论如何,128 K的整个块将不得不停止使用,因为这是擦除大小。没问题,有多余的存储空间,我只是想确保下一个闪存会跳过这个坏块。由于Linux内核和引导加载程序都不费事地标记坏块,所以我将在U-boot中手工完成:

代码语言:javascript
复制
U-Boot> nand markbad 2562000
block 0x02562000 successfully marked as bad

对第二个坏闪存页的类似调查显示,另一个错误位于闪存地址0x60a1000处:

代码语言:javascript
复制
U-Boot> nand read 0 60A1000 800
NAND read: device 0 offset 0x60a1000, size 0x800
PMECC: Too many errors
NAND read from offset 60a1000 failed -5
 0 bytes read: ERROR

因此,在这里,nand 实用工具也用于手动在这个块上放置一个永久标记:

代码语言:javascript
复制
U-Boot> nand markbad 60a1000
block 0x060a1000 successfully marked as bad

并核实是否考虑到所有因素:

代码语言:javascript
复制
U-Boot> nand bad
Device 0 bad blocks:
  02560000
  060a0000

就像应该的一样--从每个128 K块开始,两个块都被标记了。

问题:所以我了解到,64个OOB字节被分成2个字节标记,38个字节纠错代码,24个字节日志记录。在伴随着每2048个有效负载字节的所有OOB字节中,只有第一段64个字节与2KB的第一页一起使用它的2字节标记代码来指示整个128 2KB块的状态。这两个字节应该在闪存设备本身中被修改,这样这种状态才是持久的。因此,在我的U引导会话中,我没有启动Linux系统,而是重新启动CPU并保持U引导:

代码语言:javascript
复制
U-Boot> reset
resetting ...
RomBOOT
 ba_offset = 0xc ...
AT91Bootstrap 3.6.0-00029-g0cd4e6a (Wed Nov 12 12:14:04 CET 2014)
NAND: ONFI flash detected
NAND: Manufacturer ID: 0x2c Chip ID: 0x32
NAND: Disable On-Die ECC
PMECC: page_size: 0x800, oob_size: 0x40, pmecc_cap: 0x4, sector_size: 0x200
NAND: Initialize PMECC params, cap: 0x4, sector: 0x200
NAND: Image: Copy 0x80000 bytes from 0x40000 to 0x26f00000
NAND: Done to load image
U-Boot 2013.10-00403-g1f9a20a (Nov 12 2014 - 12:14:27)
CPU: SAMA5D31
Crystal frequency:       12 MHz
CPU clock        :      528 MHz
Master clock     :      132 MHz
DRAM:  128 MiB
NAND:  256 MiB
MMC:   mci: 0
In:    serial
Out:   serial
Err:   serial
Net:   macb0
Hit any key to stop autoboot:  0
U-Boot> nand info
Device 0: nand0, sector size 128 KiB
  Page size      2048 b
  OOB size         64 b
  Erase size   131072 b
U-Boot> nand bad
Device 0 bad blocks:
U-Boot> 

坏的块已经被遗忘了,-标记代码是而不是持久地应用?当然,这个U引导版本似乎很老了。从那以后,nand标记坏实用程序是否得到了改进?

解决办法:我自己在坏块中修改了第一个页面的OOB字节。我将第一个页面的所有2112字节读入RAM,然后修改2字节标记代码,并将2112字节从RAM写回闪存。从技术上讲,我应该删除整个128 K的闪存页,然后写回所有128 K的内容。但我的懒惰今天已经受到了足够的挑战。Nand闪光灯可以从1任意切换到0-这是反向操作是困难的,需要一个擦除恢复整个128 K页回到所有-0xFF。我注意到所有的“块好”标记都编码为0xFFFF,所以我认为写"0x0000“就足够了。

代码语言:javascript
复制
U-Boot> nand read.raw 0x20200000 0x2560000 1
NAND read:  2112 bytes read: OK

nand read.raw的格式有点古怪,与nand.read相反,nand.read希望size作为最后一个参数(以字节为单位),而不是以页数表示的大小。第一页是我们所需要的,所以论点'1‘起作用。这些内容已经转移到内存中,可以使用utility的md实用程序来检查:

代码语言:javascript
复制
U-Boot> md 0x20200000 0x210
20200000: 23494255 00000001 00000000 01000000    UBI#............
20200010: 00080000 00100000 9cfb6033 00000000    ........3`......
...
202007e0: 00000000 00000000 00000000 00000000    ................
202007f0: 00000000 00000000 00000000 00000000    ................
20200800: ffffffff ffffffff ffffffff ffffffff    ................
20200810: ffffffff ffffffff ffffffff ffffffff    ................
20200820: ffffffff b0c9aa24 0008fdb8 00000000    ....$...........
20200830: 00000000 00000000 00000000 00000000    ................

请注意md实用程序是如何以不同的格式期望它的size参数的:这个工具期望它以单词单位表示。只是让我们保持警惕。地址0x20200800的转储清楚地显示了markbad是如何失败的:坏块的2个标记字节仍然在0xFFFF上欢快地运行。

然后,要修改这些字节,另一个U引导实用程序就派上用场了:

代码语言:javascript
复制
U-Boot> mm 0x20200800
20200800: ffffffff ? 00000000
20200804: ffffffff ? q

这有点粗糙,我已经更改了4 first OOB字节,而不是仅仅更改了2第一标记字节。最后,将修改后的内容写回闪存:

代码语言:javascript
复制
U-Boot> nand write.raw 0x20200000 0x2560000 1
NAND write:  2112 bytes written: OK

有趣的是,nand错误的诊断没有注意到刚才标记的块,即使在某些nand读取了确实失败的尝试之后。

代码语言:javascript
复制
U-Boot> nand bad
Device 0 bad blocks:
U-Boot>

但这没什么好担心的。第二个坏块是以类似的方式手动标记的,并且在另一个重置时:

代码语言:javascript
复制
U-Boot> reset
resetting ...
RomBOOT
 ba_offset = 0xc ...
AT91Bootstrap 3.6.0-00029-g0cd4e6a (Wed Nov 12 12:14:04 CET 2014)
...
U-Boot 2013.10-00403-g1f9a20a (Nov 12 2014 - 12:14:27)
...
Hit any key to stop autoboot:  0
U-Boot> nand bad
Device 0 bad blocks:
  02560000
  060a0000
U-Boot>

瞧,“坏块”的标记一直存在!下一个闪存操作巧妙地跳过了坏块,在闪存的各个分区中保存了一致的内核和文件系统。这是一直以来的意图,但似乎需要硬朗的手工工作。没有自动化的方法吗?

EN

回答 1

Stack Overflow用户

发布于 2019-09-26 20:39:25

自2014年以来,U-Boot已经发生了很大的变化。可能与您的问题相关的补丁包括:

support")

  • c4adf9db5d38

  • dc0b69fa9f97 ("mtd: nand: mxs_nand:允许BBT )“(spl: nand: sunxi:删除对所谓的”综合症“mode")

  • 8d1809a96699的支持(spl: nand:简单:用芯片专用的read_buf()替换readb() )

拜托,用U-Boot Git头重测一次。如果仍然有什么遗漏,请向report开发人员列表报告,或者更好地发送您的补丁程序。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58083109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档