恩山无线论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1975|回复: 40
打印 上一主题 下一主题

让 MT7621 等不支持 SPI-NAND 的路由器直接从 SPI-NAND 上启动

  [复制链接]
跳转到指定楼层
1#
发表于 2020-10-9 23:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
原帖地址:https://blog.hackpascal.net/2020 ... -spi-nand-directly/
转载请注明原帖链接和作者!



在现在看来,现今比较老的一批路由器芯片,以 Atheros/QCA/MediaTek 等的 MIPS 平台的芯片为代表,基本都只支持从 SPI-NOR 启动。
如果要使用 SPI-NAND,就必须使用双 Flash 方案,即从 SPI-NOR 上启动,再从 SPI-NAND 上加载固件。
对于现有的方法,从单 Flash 改为双 Flash 就很不容易。如果是新设计的方案,双 Flash 会增加额外的物料成本和开发成本,不划算。

说到底,这还是因为 SPI-NOR 跟 SPI-NAND 使用的读指令的时序不同:

SPI-NOR 的 Read data (03h) 指令时序:

总结为 1个字节的 Opcode + 3字节的地址 + 输出数据

SPI-NAND 的 Read from cache x1 (03h) 指令时序:

总结为 1个字节的 Opcode + 2字节的地址 + 1字节的无用时钟 + 输出数据

可以看到这两者差异还是很明显的。而 CPU 读取数据的时序是固定不变的,即 SPI-NOR 的时序。因此这类 CPU 是不能从 SPI-NAND 上启动的。



但是,Micron 在他们的 SPI-NAND 中,提供了一个功能,可以将自身的 Read from cache x1 (03h) 和 Fast read from cache x1 (0Bh) 的时序转换为 SPI-NOR 的时序。
并且绝大部分 SPI-NAND 在上电之后都会将其第一个 page 的数据加载至 cache 里面,Micron 的当然也不例外。
这样,CPU 就能够直接访问到 SPI-NAND 第一个 page 的数据了。虽然一个 page 普遍都是 2KB 大小,少部分是 4KB。


根据描述,这个功能需要一系列复杂的操作才能开启,而且这个功能是不会因为断电就失效的。
但是,Micron 只提到了怎么开启这个功能,而没有提到怎么关闭这个功能。事实上我测试和发现,这个功能一旦开启就不能关闭了。



那么,能否在有限的 2KB 大小内,写一份代码让 MT7621 直接从 SPI-NAND 上启动呢?
显然我做到了。我的设计如下:

整个 Bootloader 分为3个部分:
  • 第一阶段,此时没有内存可用。需要将第二阶段的代码从 SPI-NAND 读取出来并执行。
  • 第二阶段,初始化 CPU 内存等,并加载第三阶段
  • 第三阶段,即常规的 Bootlaoder,例如 Breed 或者 U-Boot

虽然 MT7621 有 24KB 的 SRAM 可用,但是考虑到第二阶段大小必定大于 24KB,因此第二阶段只能放在 cache 上执行。
MT7621 有 256KB 的 L2 cache,4-way。MIPS 规定最多 3 way 可以被锁定,也就是最多 192KB 的 L2 cache 可以被用于加载第二阶段,完全足够了。

因此,第一阶段需要完成如下操作:
  • 初始化 MIPS CPS,以便于能够进行 cache 初始化操作
  • 初始化 cache,并锁定一部分用于加载第二阶段
  • 初始化 spi-nand 驱动,并加载第二阶段到 cache
  • 执行第二阶段

第二阶段主要就是加载并执行 MTK SDK U-Boot 中提供的初始化内存的 mt7621_stage_sram.bin,然后完成其余必要的初始化操作。
最后执行 spi-nand 驱动,加载第三阶段到内存,并执行

所以开发难点在于第一阶段,如何将这么多功能塞进 2KB 以内。
首先当然是精简代码,只保留必要的部分。
然后就是利用 CPU 和编译器的特性:
MIPS CPU 支持 mips16 压缩指令,因此这个选项必须要开启
再一个是 gcc 编译器的链接时优化 (Link-time optimization, LTO) 功能。通常的优化都只能在一个源代码中进行优化。
这个 LTO 功能可以跨越源代码文件边界,将全部源代码看成一个整体进行进一步优化,减小体积。
只不过要注意的是 LTO 一直存在 BUG,因此只给第一阶段使用,不能给后续阶段使用。

最终我成功将第一阶段的大小控制在了 1.88KB 左右。这里面还有一个本可以去掉的串口输出功能。



然后就是 Bootloader / Kernel 适配了。

要能支持 SPI-NAND,U-Boot 最好选用 Upstream的,因为它已经支持 spi-nand framework 了。
但是 Upstream U-Boot 并不支持 MT7621 因此作罢。
而给 MTK SDK U-Boot 增加 SPI-NAND 支持工程量更大,因此不考虑。
最后就只有 Breed 可以胜任了。

而 Kernel 正式支持 SPI-NAND 需要版本 4.18 及之后了,当然 4.14 版本也可也轻松 backport。
Kernel 的 spi-nand 驱动需要进行修改,识别 SPI-NAND 是否开启了 NOR Read 功能,如果开启了,就要修改 spi-mem op template,调整其 read_cache 的时序。
另一点是,开启 NOR Read 之后, 03h 和 0Bh 这两个指令的时钟频率不能高于 20MHz,否则会得到错误的数据。因此 dts 里面要限制其 spi master的速率。

另外,开启了 NOR Read 的 SPI-NAND 存在一个跟 SPI-NOR 32MB 类似的软重启问题。
跟 SPI-NOR 直接读取存储的数据不同,SPI-NAND 的 03h/0Bh 指令是读取的内部 cache 的数据,而真实存储的数据需要预先在 SPI-NAND 内部读取到 cache 后,才能通过 03h/0Bh 读出。
而要将数据写入 SPI-NAND,也是先将数据加载到 cache,SPI-NAND 内部才会将数据实际写入。
这样会带来的一个显而易见的问题就是,cache 内的数据会随着对 SPI-NAND 的操作而不断变化,而软重启后,cache 的数据就是未知的了,且99.99%的概率不是第一个 page 的数据。
这会导致软重启无法开机。因此解决办法自然是在每次完整的读写操作之后,都执行一个加载第一个 page 的数据到 cache 的命令,以保证正常操作性,软重启能正常执行。



实际测试结果

第一二阶段 + Breed 输出:


Kernel 内 spi-nand 相关的输出:




我将第一二阶段的源代码放在 github 上:
https://github.com/hackpascal/mt7621-boot-spi-nand

对 kernel 的修改:
https://github.com/hackpascal/openwrt-dev/commits/mt7621-boot-spi-nand

测试用的 bootloader 和固件:
https://pan.baidu.com/s/17aWbKr7QzKWw8zw7fog_nw
提取码:8iqj

loader-no-payload.bin 不含第三阶段,可以自行拼接。
loader-breed.bin 的第三阶段是 Breed。

关于如何开启 SPI-NAND 的 NOR Read 功能,没有统一的方法,使用编程器,或者通过 ft2232 这类支持 SPI 的芯片,下发 Micron 手册上描述的指令,来开启

评分

参与人数 6恩山币 +9 收起 理由
hwvxb + 1 一看就是觉得高端、大气、上档次!
WeDone + 2 一看就是觉得高端、大气、上档次!
ITdesk + 2 支持一波大佬
那个男人 + 1 兄弟,你肥皂又掉了…
我妻亚衣 + 2 强大的恩山!(以下重复1万次)
dlsys + 1 恩山全体路由党向你学习!

查看全部评分

我的恩山、我的无线 The best wifi forum is right here.
2#
发表于 2020-10-9 23:48 | 只看该作者
前排广告位.
我的恩山、我的无线 The best wifi forum is right here.
3#
发表于 2020-10-9 23:54 | 只看该作者
虽然没看懂,感觉很牛逼
来自安卓客户端来自安卓客户端
我的恩山、我的无线 The best wifi forum is right here.
4#
发表于 2020-10-9 23:55 | 只看该作者
受益良多
我的恩山、我的无线 The best wifi forum is right here.
5#
发表于 2020-10-9 23:57 | 只看该作者
膜拜大佬,顶上↑↑↑↑↑
来自安卓客户端来自安卓客户端
我的恩山、我的无线 The best wifi forum is right here.
6#
发表于 2020-10-9 23:59 | 只看该作者
我的恩山、我的无线 The best wifi forum is right here.
7#
发表于 2020-10-10 00:03 | 只看该作者
大佬又出现了!一直用你的Breed,谢过~
我的恩山、我的无线 The best wifi forum is right here.
8#
发表于 2020-10-10 00:11 | 只看该作者
摩拜摩拜
来自安卓客户端来自安卓客户端
我的恩山、我的无线 The best wifi forum is right here.
9#
发表于 2020-10-10 00:14 | 只看该作者
没有沙发了
我的恩山、我的无线 The best wifi forum is right here.
10#
发表于 2020-10-10 00:23 | 只看该作者
Mark!

另:最近遇到一个问题,newifi D1 /D2 SPI-NOR 32MB ,breed+openwrt官方19版

在使用了 AdGuard Home(非luci)官方Github后,软重启就失效了,LED灯也一直慢闪状态。

删掉 AGH 也是恢复不了。还在研究是什么问题造成的。

breed已经修复了SPI-NOR 32MB 软重启问题了。在没有启动AGH的时候也是没有异常,看样子,AGH会改动系统的配置??

我的恩山、我的无线 The best wifi forum is right here.
11#
发表于 2020-10-10 00:58 | 只看该作者
看来,

不久就会让很多双盘位的机型有得玩了..

H大就是...

我的恩山、我的无线 The best wifi forum is right here.
12#
发表于 2020-10-10 01:00 | 只看该作者
神人神操作
来自苹果客户端来自苹果客户端
我的恩山、我的无线 The best wifi forum is right here.
13#
发表于 2020-10-10 01:10 | 只看该作者
膜拜大神,不明觉厉~
我的恩山、我的无线 The best wifi forum is right here.
14#
发表于 2020-10-10 01:52 | 只看该作者
牛A,虽说现在MT7621已经算不上热门,但市场存量实在是庞大,各种机型/配置够多
我的恩山、我的无线 The best wifi forum is right here.
15#
发表于 2020-10-10 04:36 | 只看该作者
虽然没看懂,但感觉很牛逼
我的恩山、我的无线 The best wifi forum is right here.
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|Archiver|恩山无线论坛(常州市恩山计算机开发有限公司版权所有) ( 苏ICP备05084872号 )|网站地图

GMT+8, 2020-12-6 09:26

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表