SPI NAND 启动
在常见的方案中,通常划出前面 4 个 Block 作为保存第一级引导程序的保存分区,并且在每个 Block 中保存一份启动镜像。 本芯片的实现方案有一些不同。
候选启动块
本方案中同样划出前面 4 个 Block 作为第一级引导程序的保存区域, 这个区域称为显式的第一级引导程序保存区域,进行 MTD 分区时,应该将其预留为启动分区。
除此之外,本方案还另外定义了 14 个索引号为偶数的 Block 作为保存第一级引导程序的候选块, 这 14 个块从 NAND 的前 1024 个块中随机选取。对于块大小为 128 K 的 NAND,候选块分布在前 128 MB, 对于块大小为 256 KB 的 NAND,候选块分布在前 256 MB。
如下表,总共有 18 个 Block 作为候选启动块。这些启动块的使用规则是:
-
按照优先顺序,逐个检查是否为好块
-
按顺序选出 4 个好块作为启动块,分别写入启动镜像
-
对于后 14 个候选块,如果被选中作为启动块,则在烧录启动镜像时将其标记为坏块,以及启动块的特殊标记。标记为坏块的目的是防止其它应用再次使用该块而导致启动镜像被破坏
-
如果表中所列候选块都是坏块,该 SPI NAND 无法作为启动器件使用
|
优先顺序 |
Block ID |
说明 |
|---|---|---|
|
1 |
0 |
启动分区内,优先使用,保存启动镜像备份 1 |
|
2 |
1 |
启动分区内,优先使用,保存启动镜像备份 1 |
|
3 |
2 |
启动分区内,优先使用,保存启动镜像备份 1 |
|
4 |
3 |
启动分区内,优先使用,保存启动镜像备份 1 |
|
5 |
202 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
6 |
32 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
7 |
312 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
8 |
296 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
9 |
142 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
10 |
136 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
11 |
392 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
12 |
526 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
13 |
452 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
14 |
708 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
15 |
810 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
16 |
552 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
17 |
906 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
|
18 |
674 |
如果是好块,则作为启动块。写入启动镜像后标记为坏块 |
在正常情况下,烧录的 SPI NAND 前面四个块为好块,则仅有前面四个块被用作启动块, 后面的 14 个候选块不需要保留,可以作为其它用途。
Page table
烧录在启动块上的数据并不仅仅是启动镜像,还包括一个页索引表 (Page Table)。Page Table 的目的是构建一个全局的索引表,通过该索引表,可以找到所有保存备份镜像的 Page 的地址 (PA)。 这样 BROM 一旦读取到正确的 Page Table,就可以直接读取到所有备份镜像,减少尝试的时间。
Page Table 总是保存在启动块的 Page0 中。启动块中数据的分布如下。
|
页号 |
内容 |
|---|---|
|
Page 0 |
保存 Page Table (2 KB) 的数据,仅使用前 2 KB |
|
Page 1 |
启动镜像的第 1 个 2 KB/ 4 KB 数据 |
|
Page 2 |
启动镜像的第 2 个 2 KB/ 4 KB 数据 |
|
Page 3 |
启动镜像的第 3 个 2 KB/ 4 KB 数据 |
|
Page 4 |
启动镜像的第 4 个 2 KB/ 4 KB 数据 |
|
…… |
…… |
| 警告 | |
|---|---|
Page Table 中包括一个头信息,以及所有备份镜像所在的页地址。其格式如下表所示。
| 区域 | 名字 | 类型 | 字节 | 备注 |
|---|---|---|---|---|
| Head | Magic | CHAR | 4 | “AICP” 标记 |
| Entry Count | U16 | 2 | 启动镜像占用的 Page 数量 | |
| Page Size | U16 | 2 | 当前 SPI NAND 的 Page Size | |
| Page per block | U8 | 1 | 当前 SPI NAND 中,一个块的页数量 | |
| Blocks | U8 | 1 | 当前 SPI NAND 的块数量 = Blocks * 512 | |
| Planes | U8 | 1 | 当前 SPI NAND 的 Plane 数量 | |
| Padding | U8 | 1 | ||
| Data 0 | Image0 Data 0 Address | U32 | 4 | 启动镜像第 0 个 Page 数据保存在 Block0/Block1 中的 Page 地址 |
| Image1 Data 0 Address | U32 | 4 | 启动镜像第 0 个 Page 数据保存在 Block2/Block3 中的 Page 地址 | |
| Data 0 Checksum | U32 | 4 | 启动镜像第 0 个 Page 数据的 32 位校验和 | |
| Data 1 | Image0 Data 1 Address | U32 | 4 | 启动镜像第 1 个 Page 数据保存在 Block0/Block1 中的 Page 地址 |
| Image1 Data 1 Address | U32 | 4 | 启动镜像第 1 个 Page 数据保存在 Block2/Block3 中的 Page 地址 | |
| Data 1 Checksum | U32 | 4 | 启动镜像第 1 个 Page 数据的 32 位校验和 | |
| … | … | … | … | … |
此处中的 Block0、Block1、Block2、Block3 是指选定的四个候选块。
使用 Page Table,除了可以快速定位启动备份镜像在 SPI NAND 中的位置,还可以提高启动成功的概率。 在极端情况下,可能出现四个启动块都在使用过程中变成坏块的情况,BROM 无法从单个块中读取完整启动镜像。 借助 Page Table 的信息,只要不出现同一块镜像数据在 4 个启动块中都出现损坏的情况, 此时 BROM 还可以通过组织分布在不同启动块中没有损坏的 Page 数据,重建出一个完整的启动镜像。
SPI NAND 的启动流程
SPI NAND 启动时,首先按照上述的候选块顺序,逐个尝试从候选启动块读取 Page Table。一旦找到可以用的 Page Table,就可以找到备份镜像保存的页地址 (PA)。 接下来尝试从单个启动块中读取完整的备份镜像。所有备份镜像,逐个尝试。 如果 4 个启动块中的备份镜像都出现读取错误,这时可以尝试将 4 个启动块中没有出错的 Page 数据进行组合的方式,重建完整的启动镜像。 如果都失败,则从 SPI NAND 启动失败。

兼容性处理
BROM 阶段,从 SPI NAND 启动时,使用下列参数:
| 线宽 | 1 线 | QUAD SPI 的读命令,各家要求不尽相同 |
| Page Read 命令 | 13h | 所有厂家都支持的命令 |
| Read Cache 命令 | 03h | 所有厂家都支持的命令 |
| Plane | 1 | 总是假设为 1,由于 Page Table 总是保存在 Block ID 为偶数的块上,因此总是可以访问 |
| 频率 | 24 MHz | 为了稳定可靠 |
