首页 > 技术文章 > 给OPi Zero Plus添加USB启动功能

wh201906 2019-07-13 00:50 原文

为使OPi Zero Plus支持U盘启动,需要在板载的SPI Flash当中刷入uboot。在这个过程当中绕了很多弯路,特此记录

最终操作步骤见文末

网上的教程仅使用sudo modprobe spi-sunxi、sudo modprobe spi-dev就使得/dev/下出现了SPI设备,而在Armbian系统当中却无效,遂怀疑需要使用官方系统


思路 :配置官方系统→打开SPI功能→写入uboot→测试U盘启动


选用的镜像是ubuntu_desktop_xenial_zeroplus_H5_V0_1.img,更新于2017-08-14

一、刷入系统

推荐使用Etcher写入镜像,因为官方有免安装版本的Etcher可以直接打开使用
下载下来的压缩包需解压两次才可得到最终的img文件(.rar→.xz→.img)

二、使用parted命令扩展分区

官方系统不会自动将分区扩展至整个内存卡,需手动使用parted命令调整
输入sudo parted -l查看当前磁盘信息,记录内存卡对应的设备名(/dev/mmcblk?)以及ext4分区对应的编号(一般是2)
然后输入sudo parted +设备名,例如sudo parted /dev/mmcblk0,进入parted
再输入resizepart并回车,在询问Partition number?时输入对应分区编号并回车,询问End?时输入100%并回车,最后重启,即可将分区扩展至整个内存卡

三、更新软件包

用系统自带的nano或者vim文本编辑器修改/etc/apt/sources.list文件,将原始数据全部用#注释掉后替换为国内软件源,最后执行sudo apt update和sudo apt upgrade更新软件包即可

四、解决开机等待时间过长问题

更新软件包后开机可能会卡在以下步骤,需等待5分钟之后才能继续启动

[*** ] A start job is running for Raise network interfaces

(该启动信息仅在通过串口连接香橙派时可见,若使用ssh连接,则体现为开机后需等待5分钟才可使用ssh)
解决方法:在更新软件包后或之后成功登录进入系统后用文本编辑器打开/lib/systemd/system/networking.service
通常情况下能看到文件开头如下:

[Unit]
Description=Raise network interfaces
Documentation=man:interfaces(5)
DefaultDependencies=no
Wants=network.target
……

此时跳转至文件尾部,将TimeoutStartSec=5min更改为TimeoutStartSec=10,保存并退出即可

五、打开SPI功能(失败)

根据网上的资料,成功执行sudo modprobe spi-sunxi,但仍然无法看到spi设备

查错:

通过其他资料得知SPI功能需要通过sunxi-tools编辑系统文件才能打开
同时在官方系统当中未找到/usr/lib下的uboot镜像,遂放弃,决定在Armbian中进行后续操作


思路 :编译安装zlib→安装其它组件→编译安装sunxi-tools→编辑系统文件→打开SPI功能→写入uboot→测试U盘启动


一、安装zlib

sudo wget http://www.zlib.net/zlib-1.2.11.tar.gz
sudo tar -zxvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
sudo ./configure
sudo make
sudo make install

二、安装其它组件

sudo apt install pkg-config libusb build-essential

三、下载并编译sunxi-tools

git clone https://github.com/linux-sunxi/sunxi-tools
cd sunxi-tools
sudo make
sudo make install

改进:

后来发现有现成sunxi-tools可供安装


思路 :安装sunxi-tools→复制script.bin→用sunxi-tools中的bin2fex进行转换并编辑→覆盖原script.bin,启动SPI功能→写入uboot→测试U盘启动


一、直接安装sunxi-tools

sudo apt install sunxi-tools

二、修改/media/boot/script.bin以启动SPI功能(失败)

boot分区挂载于根目录中而不是/media/中,且boot分区内无任何类似script.bin的文件

查错:

经搜索得知,使用Legacy kernel时才会使用FEX/script.bin来控制硬件功能,而当前Armbian使用的mainline Linux kernel则使用设备树(.dtb文件)来控制硬件功能。遂查询在当前内核当中打开SPI的方法


思路 :修改armbianEnv.txt→启动SPI模块→写入uboot→测试U盘启动


一、查询所支持的硬件功能并启用

参考资料

先使用sudo find /boot/dtb/ -name "*overlay*"命令查找说明文件(以README开头),根据硬件型号选择README.sun50i-h5-overlays并查看,发现如下内容

……
### spi-spidev

Activates SPIdev device node (/dev/spidevX.Y) for userspace SPI access,
where X is the bus number and Y is the CS number

SPI 0 pins (MOSI, MISO, SCK, CS): PC0, PC1, PC2, PC3
SPI 1 pins (MOSI, MISO, SCK, CS): PA15, PA16, PA14, PA13

Parameters:

param_spidev_spi_bus (int)
SPI bus to activate SPIdev support on
Required
Supported values: 0, 1

param_spidev_spi_cs (int)
SPI chip select number
Optional
Default: 0
Supported values: 0, 1
Using chip select 1 requires using "spi-add-cs1" overlay

param_spidev_max_freq (int)
Maximum SPIdev frequency
Optional
Default: 1000000
Range: 3000 - 100000000
……

从中得知配置启动spi-spidev时必须配置参数param_spidev_spi_bus,其余参数为可选项

打开/boot/armbianEnv.txt,在overlays=的后面加上spi-spidev(用空格与前项分隔开),并在文件末尾添上一行
param_spidev_spi_bus=0
保存文件并重启

二、查找内核功能并启用

参照之前资料的内容以及错误提示,输入sudo find /lib/modules/xxx/kernel -name "spi"找到了该文件

/lib/modules/4.19.57-sunxi64/kernel/drivers/spi/spidev.ko

遂输入sudo modprobe spidev启用该功能,后可在/dev/中找到spidev0.0,成功打开SPI功能

改进:

过程中搜索资料发现在Armbian系统中可使用armbian-config直接开启SPI功能


思路 :直接启动SPI功能→写入uboot→测试U盘启动


一、直接使用armbian-config启动SPI

方法如下:
输入sudo armbian-config→选中System并回车→选中Hardware并回车→选中spi-spidev,用空格选中→左右方向键选中Save并回车→左右方向键选中Back并回车→选中Reboot并回车
等待重启完成即可

二、写入uboot

先输入sudo apt install flashrom安装刷写工具

资料得知uboot镜像为/usr/lib/linux-u-boot-orangepizero_5.31_armhf/u-boot-sunxi-with-spl.bin
其中linux-u-boot-orangepizero_5.31_armhf取决于当前系统版本
我找到的镜像文件为/usr/lib/linux-u-boot-next-orangepizeroplus_5.85_arm64/sunxi-spl.bin
通过以下命令刷入

cd
dd if=/dev/zero count=2048 bs=1K | tr '\000' '\377' > spi.img
dd if=/usr/lib/linux-u-boot-next-orangepizeroplus_5.85_arm64/sunxi-spl.bin of=spi.img bs=1k conv=notrunc
sudo flashrom -p linux_spi:dev=/dev/spidev0.0 -c MX25L1605 -w spi.img

(dd命令的文件目录根据bin文件实际位置调整)
最后显示

Erase/write done.
Verifying flash... VERIFIED.

刷写镜像成功

三、测试U盘启动(失败)

关机,拔出SD卡,插上预先写入了系统镜像的U盘,插电启动
串口输出如下:

U-Boot SPL 2019.04-armbian (May 08 2019 - 17:52:07 +0200)
DRAM: 512 MiB
Trying to boot from sunxi SPI

然后就一直卡在这个界面不进入系统

查错:

1.怀疑U盘系统镜像有误

重新刷入最新的Armbian_5.83镜像,重试,仍然无法开机

2.怀疑系统自带的镜像文件错误

进入系统,使用以下命令重装相关包

sudo apt remove linux-u-boot-orangepizeroplus-next
sudo apt install linux-u-boot-orangepizeroplus-next

重装后重复上述二、三步,仍然无法启动

3.怀疑找错了镜像文件

原因:
1.在刷入镜像文件以前,无内存卡插电启动系统时串口无输出,刷入镜像文件以后,无卡插电启动时有上述串口输出,且刷入空镜像文件后,无卡启动时的串口输出又会消失
说明系统是从SPI Flash当中启动的

2.资料当中使用dd命令共向spi.img当中写入了300KB左右的数据,而使用我找的bin文件却只写入了30KB左右的数据

3.我找到的bin文件为sunxi-spl.bin,末尾是spl而不是spi,说明此文件可能不是为了写入SPI Flash而专门设计的,且原教程中的文件名为u-boot-sunxi-with-spl.bin,英文含义不同

综上,推测找错了镜像文件的可能性很大


思路 :直接启动SPI功能→查找/生成uboot镜像文件→写入uboot→测试U盘启动


一、直接使用armbian-config启动SPI

方法见上

二、查找/生成uboot镜像文件

在目录/usr/lib/linux-u-boot-next-orangepizeroplus_5.85_arm64/当中找到了u-boot.itb,猜测该文件可用于生成uboot镜像
查阅资料1以及资料2得知sunxi-spl.bin和u-boot.itb共同直接构成启动所需的uboot镜像
结合之前单独刷写sunxi-spl.bin时串口输出有部分启动内容的情况,猜测需将u-boot.itb直接刷写至sunxi-spl.bin后

输入ls -l /usr/lib/linux-u-boot-next-orangepizeroplus_5.85_arm64/得知sunxi-spl.bin占用32768个字节
查阅资料1
以及资料2,得知dd命令中用bs指定读写块的大小(单位为字节),用seek指定跳过多少块进行写入(单位为块)

输入命令如下:

cd
dd if=/dev/zero count=2048 bs=1K | tr '\000' '\377' > spi.img
dd if=/usr/lib/linux-u-boot-next-orangepizeroplus_5.85_arm64/sunxi-spl.bin of=spi.img bs=1k conv=notrunc
dd if=/usr/lib/linux-u-boot-next-orangepizeroplus_5.85_arm64/u-boot.itb of=spi.img bs=1 seek=32768 conv=notrunc

三、写入uboot

输入以下命令

sudo flashrom -p linux_spi:dev=/dev/spidev0.0 -c MX25L1605 -w spi.img

四、测试U盘启动(部分失败)

按照先前步骤,在一个金士顿U盘上启动失败,在一个闪迪U盘上启动成功
前者的串口输出中有如下内容

EHCI timed out on TD
……
Verifying Checksum ... Bad Data CRC
Ramdisk image is corrupt or invalid
SCRIPT FAILED: continuing...

后者的串口输出中对应内容如下

Verifying Checksum ... OK
## Flattened Device Tree blob at 4fa00000
Booting using the fdt blob at 0x4fa00000

经查询,U盘有坏道可能导致无法成功启动



最终方案:

直接启动SPI功能→生成uboot镜像文件→安装flashrom→写入uboot→测试U盘启动


1.直接使用armbian-config启动SPI

输入sudo armbian-config→选中System并回车→选中Hardware并回车→选中spi-spidev,用空格激活→左右方向键选中Save并回车→左右方向键选中Back并回车→选中Reboot并回车
等待重启完成即可

重启后输入ls /dev,可在设备列表当中看到一个名为spidev0.0的设备

2.生成uboot镜像文件

输入apt search linux-u-boot-orangepizeroplus,查看以下两个包是否有[installed]字样

linux-u-boot-orangepizeroplus-dev
linux-u-boot-orangepizeroplus-next

若两者没有出现[installed](情况少见),则输入sudo apt install linux-u-boot-orangepizeroplus-next,等待安装完成后进入下一步
其中任意一个包有[installed],则执行以下命令

cd
dd if=/dev/zero count=2048 bs=1K | tr '\000' '\377' > spi.img
dd if=/usr/lib/linux-u-boot-next-orangepizeroplus_5.85_arm64/sunxi-spl.bin of=spi.img bs=1k conv=notrunc
dd if=/usr/lib/linux-u-boot-next-orangepizeroplus_5.85_arm64/u-boot.itb of=spi.img bs=1 seek=32768 conv=notrunc

其中linux-u-boot-next-orangepizeroplus_5.85_arm64用自己系统中的对应路径去替换,方法是输入ls /usr/lib,查看名字以linux-u-boot开头的文件夹
之后在用户目录下会有一个大小为2097152字节的spi.img文件

3.安装flashrom

输入sudo apt install flashrom

4.写入uboot

输入sudo flashrom -p linux_spi:dev=/dev/spidev0.0 -c MX25L1605 -w spi.img

过程中可能出现Erasing and writing flash chip... FAILED和ERASE FAILED!
但只要最后显示

Erase/write done.
Verifying flash... VERIFIED.

则说明写入成功

5.测试U盘启动

先挑一块质量好的U盘,使用Etcher向U盘写入Armbian的镜像文件
香橙派关机拔电源,取出内存卡,将写好的U盘插入香橙派,插电开机启动即可


后记:

/usr/lib/下有一个u-boot目录,里面的platform_install.sh对于如何生成uboot镜像文件也有参考价值

2019.07.06

推荐阅读