荔枝派Nano 全流程指南
u-boot 初体验
安装交叉编译链
首先需要安装交叉编译链:
# 此处为获取7.2.1版本,您可获取其他版本或者通过链接直接下载 wget http://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/arm-linux-gnueabi/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz tar -vxJf gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz sudo cp -r ./gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi /opt/ sudo vim /etc/bash.bashrc # 在文件末尾 添加以下内容 PATH="$PATH:/opt/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi/bin" # 添加完毕 # 使路径生效 source /etc/bash.bashrc 此时可用 arm-linux-gnueabi-gcc -v 进行测试;若普通用户状态下没有成功,通过 sudo su 切换到root用户再尝试;
编译 u-boot
然后从github上拉取对 Nano 进行了适配的 u-boot:
sudo apt-get install git git clone https://github.com/Lichee-Pi/u-boot.git cd u-boot # 查看分支 git branch -a # 切换到 Nano 分支 git checkout nano-v2018.01
u-boot 对于新手来说目录层级稍显复杂,您可参考下表进行快速的熟悉和目标文件定位(搬运并修改自 荔枝派One)
. ├── api //封装一些平台无关的操作,如字符串打印,显示,网络,内存 ├── arch //以平台架构区分 │ ├──arm │ │ └──cpu │ │ │ └──arm926ejs │ │ │ │ └──sunxi //cpu相关的一些操作,如定时器读取 │ │ │ │ │ └──u-boot-spl.lds //spl的放置方法 │ │ └──dts │ │ │ └──suniv-f1c100s-licheepi-nano.dts // f1c100s芯片的一些配置 │ │ │ └──suniv-f1c100s-licheepi-nano.dtb │ │ │ └──suniv-f1c100s.dtsi │ │ │ └──suniv.dtsi │ │ └──lib //一些库文件 │ │ └──mach-sunxi │ │ │ └──board.c //board_init_f │ │ │ └──dram_sun4i.c //ddr的操作,复位,时钟,延时,odt,etc. │ │ │ └──dram_helpers.c //ddr的设置及读写测试 ├── board │ ├──sunxi │ │ └──board.c //sunxi_board_init 入口 │ │ └──dram_suniv.c //DRAM的一些默认参数 ├── cmd //Uboot命令行的一些命令 ├── common //含spl ├── configs //menuconfig里的默认配置,比如各类驱动适配 │ ├── licheepi_nano_defconfig │ ├── licheepi_nano_spiflash_defconfig ├── disk //硬盘分区的驱动 ├── doc ├── drivers //外设驱动 ├── dts ├── examples ├── fs //多种文件系统 ├── include │ ├──configs │ │ └──sunxi_common.h //预配置的参数,如串口号等 │ │ └──suniv.h ├── lib //加密压缩等算法 ├── net //nfs,tftp等网络协议 ├── post ├── scripts
了解u-boot大致结构后,我们就可以开始尝试编译了;
# 此处告知make采用arm-linux-gnueabi下的所有交叉编译工具,目标架构为Arm,设定各项默认配置为 nano 的spiflash支持版 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- licheepi_nano_spiflash_defconfig # 若不带spi-flash的板子,请换成 licheepi_nano_defconfig # 进行可视化配置 make ARCH=arm menuconfig 若要在套餐中附带的LCD上输出显示,请通过配置 ARM architecture ‣ Enable graphical uboot console on HDMI, LCD or VGA 为 Y
接着配置同级的 LCD panel timing details 为:
x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:40,up:31,lo:13,hs:1,vs:1,sync:3,vmode:0
注:此块屏为为 800*480 规格,如为 480*272 请尝试如下配置 x:480,y:272,depth:18,pclk_khz:10000,le:42,ri:8,up:11,lo:4,hs:1,vs:1,sync:3,vmode:0
并将 LCD panel backlight pwm pin 设为:
PE6 (查自 Nano 原理图)
LCD简单配置
# 开始编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8 编译完成后,可一看到目录下多了一堆以u-boot带头的文件,我们只需取 u-boot-sunxi-with-spl.bin 即可;
下载工具 sunxi-tools 安装
在食用前,我们仍需要一个适配 Nano 的下载工具;
git clone -b f1c100s-spiflash https://github.com/Icenowy/sunxi-tools.git cd sunxi-tools make && sudo make install
如果出现:fel_lib.c:26:20: fatal error: libusb.h: No such file or directory,那需要安装libusb:
sudo apt-get install libusb-1.0-0-dev
准备完软件,可以准备一下硬件:) 串口默认为 UART0
不插卡上电~
新到的一片 Nano ,基本上是上电无反应的,LCD亮但无内容,此时 Nano 自动进入fel下载模式,可以通过命令 sudo sunxi-fel ver 来确认有无成功进入fel模式。
此时有两种方式进行程序下载:
# 1.以 uboot file-with-spl形式进行(单次运行,测试时个人推荐) sunxi-fel uboot /your/path/to/u-boot-sunxi-with-spl.bin # 请自行修改到本机地址 # 2.烧进 spi-flash (开机自启) sunxi-fel -p spiflash-write 0 /your/path/to/u-boot-sunxi-with-spl.bin # note: 重新烧录或重进fel模式时,请在上电时拉低SPI flash 的 CS引脚
下载结束后,即可看到串口输出信息,LCD显示图标与简单信息。
此时在串口控制台(minicom、putty或其他)输入 bdinfo
将列出各种板子信息,如:
arch_number = 0x00000000 boot_params = 0x80000100 DRAM bank = 0x00000000 -> start = 0x80000000 -> size = 0x02000000 baudrate = 115200 bps TLB addr = 0x80FF0000 relocaddr = 0x80F72000 reloc off = 0xFF872000 irq_sp = 0x80E67D90 sp start = 0x80E67D80 FB base = 0x81E89000 Early malloc usage: 118 / 400 fdt_blob = 80e67da8
愉快地完成了 u-boot 的初体验~
再探 Uboot
首先进入 uboot,控制台输入 printenv ,可看到控制台输出以下信息:
arch=arm baudrate=115200 board=sunxi board_name=sunxi --- 略去一些信息 --- boot_scripts=boot.scr.uimg boot.scr bootcmd=run distro_bootcmd cpu=arm926ejs
通过此命令我们可以看到 uboot 自动配置了一些启动命令与参数,其中变量 boot_scripts 指定了启动时要加载哪个命令文本文件,依据此处,我们进行 boot.scr 的构建;
建立 boot.cmd 并确认参数
boot.scr 由 boot.cmd 生成,此处新建一个 boot.cmd 文件,并写入以下内容:
setenv bootargs console=tty0 console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 rw load mmc 0:1 0x80C00000 suniv-f1c100s-licheepi-nano.dtb load mmc 0:1 0x80008000 zImage bootz 0x80008000 - 0x80C00000
第一行setenv命令,设定了变量bootargs(启动参数)为:通过tty0和ttyS0串口输出启动信息;启动失败延迟5秒重启,根文件在TF卡的第二分区,可读写;
第二行指定了从TF中将设备树的dtb文件加载到0x80C00000的位置(地址参考自官方SDK)
第三行指定了将压缩后的内核zImage加载到0x80008000的位置
第四行为从加载地址启动内核的命令
生成 boot.scr
uboot ‣ tools ‣mkimage ,通过该程序生成boot.scr
为使用方便,建议将其:
cp ./mkimage /usr/local/bin/mkimage
生成 boot.scr
mkimage -C none -A arm -T script -d boot.cmd boot.scr
最后将其放入第一分区
主线Linux编译
源码下载
完整下载命令为:
git clone https://github.com/Icenowy/linux.git
git拉取有时速度很慢,建议做如下配置:
sudo vim /etc/hosts # 添加下面两行 192.30.253.112 github.com 151.101.73.194 github.global.ssl.fastly.net
# 添加完成
# 可自行通过dns检测网站检测github.global.ssl.fastly.net,更换为更快的ip地址
完整拉取linux极大,建议只拉取单层分支,减少等待时间:
git clone --depth=1 -b f1c100s-480272lcd-test https://github.com/Icenowy/linux.git
配置
下载 .config 文件
,放入源码主目录进行替换 (若下载时文件名有变,请重命名回 .config );
进行编译
编译工具链为 arm-linux-gnueabi,工具链的安装请参考 uboot 编译部分
make ARCH=arm menuconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j4 #请自行修改编译线程数
生成的 zImage 在 arch ‣ arm ‣ boot 目录下;将其放入第一分区。
Nano 设备树简介
Nano的设备树在源码的 linux ‣ arch ‣ arm ‣ boot ‣ dts ‣ suniv-f1c100s-licheepi-nano.dts;
该文件描述了各类外设的定义与配置,以下做简要描述;
其中由 / { … } 包裹的为根节点,定义了各类总线、外设的配置;
&xxx { … } 所包裹的内容为引用,其定义来自于 suniv.dtsi (suniv系列设备通用的定义)
compatible 属性,将与驱动源码中的 compatible 定义对应,进行识别选择;
设备树各部分的编写,可参考 linux ‣ Documentation ‣ devicetree ‣ bindings 下各个模组
设备树整体的详细介绍,请参考 Device_Tree , zero文档 中也有较为详细的描述;
修改设备树中 LCD 配置
当前默认的 LCD配置 为480X272大小的屏幕,
“qiaodian,qd43003c0-40”, “simple-panel”
若要修改为适配800X480的屏,此处应当:
/ { } 所包裹的根节点目录下,panel属性下的compatible,应修改为:
“lg,lb070wv8”, “simple-panel”
linux ‣ drivers ‣ gpu ‣ drm ‣ panel 下有许多屏幕的配置,可挑选合适的进行配置;
添加底板上的 RGB LED 节点配置
/ { } 所包裹的根节点目录下进行添加
leds { compatible = "gpio-leds"; blue_led { label = "licheepi:blue:usr"; gpios = <&pio 4 4 GPIO_ACTIVE_LOW>; /* PE4 */ }; green_led { label = "licheepi:green:usr"; gpios = <&pio 4 5 GPIO_ACTIVE_LOW>; /* PE5 */ default-state = "on"; }; red_led { label = "licheepi:red:usr"; gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PE6 */ }; };
添加电容触摸屏的支持
电容触摸屏的控制芯片为GT911,使用I2C接口,我们要在设备树文件中添加定义;
(笔者此处直接在 suniv.dtsi 内进行修改)
// 添加在soc节点下
// 此处添加的属性与配置,来自于查找用户手册以及兼容设备
i2c0: i2c@1C27000 { compatible = "allwinner,sun6i-a31-i2c"; reg = <0x01C27000 0x400>; interrupts = <7>; clocks = <&ccu CLK_BUS_I2C0>; resets = <&ccu RST_BUS_I2C0>; pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; };
// 在pio节点下,添加i2c引脚定义
i2c0_pins: i2c0 { pins = "PE11", "PE12"; function = "i2c0"; };
在suniv-f1c100s-licheepi-nano.dts中添加引用
/* 首先要添加的头文件: */ #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/irq.h> /* 添加引用 */ &i2c0 { pinctrl-0 = <&i2c0_pins>; pinctrl-names = "default"; status = "okay"; gt911: touchscreen@14 { compatible = "goodix,gt911"; reg = <0x14>; interrupt-parent = <&pio>; interrupts = <4 10 IRQ_TYPE_EDGE_FALLING>; /* (PE10) */ pinctrl-names = "default"; pinctrl-0 = <&ts_reset_pin>; irq-gpios = <&pio 4 10 GPIO_ACTIVE_HIGH>; /* (PE10) */ reset-gpios = <&pio 4 9 GPIO_ACTIVE_HIGH>; /* RST (PE9) */ /* touchscreen-swapped-x-y */ }; }; &pio { ts_reset_pin: ts_reset_pin@0 { pins = "PE9"; function = "gpio_out"; }; };
完成添加~若测试的触摸屏的xy方向颠倒,请添加或去掉gt911节点下的 touchscreen-swapped-x-y 属性。
编译生成 dtb文件
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- dtbs -j4
生成的 dtb文件 在 dts同级目录下,将其放入 TF卡第一分区。
使用buildroot构建根文件系统
buildroot可用于构建小型的linux根文件系统。
大小最小可低至2M,与内核一起可以放入最小8M的spi flash中。
buildroot中可以方便地加入第三方软件包(其实已经内置了很多),省去了手工交叉编译的烦恼。
下载安装
首先安装一些依赖,比如linux头文件:
apt-get install linux-headers-$(uname -r)
然后下载安装:
wget https://buildroot.org/downloads/buildroot-2017.08.tar.gz tar xvf buildroot-2017.08.tar.gz cd buildroot-2017.08/ make menuconfig
配置
此处为免去另外配置工具链的步骤,使用了 buildroot 自动下载工具链执行的选项;
同内核编译一样,请下载 buildroot 的 .config 文件,重命名为 .config 后放到 buildroot目录下;
若编译时,buildroot下载软件包速度太慢,请下载 dl.zip ,将其中的软件包解压至 buildroot ‣ dl 下;
使用:
make menuconfig
进行配置,添加或删除指定的软件包;
一些配置的简单说明
Target options ---> Target Architecture Variant (arm926t) ---> // arm926ejs架构 [ ] Enable VFP extension support // Nano 没有 VFP单元,勾选会导致某些应用无法运行 Target ABI (EABI) ---> Floating point strategy (Soft float) ---> // 软浮点 System configuration ---> (Lichee Pi) System hostname // hostname (licheepi) Root password // 默认账户为root 密码为licheepi [*] remount root filesystem read-write during boot // 启动时重新挂在文件系统使其可读写 编译 make
>>> 有时候构建会出现莫名其妙的错误,make clean下会ok?
编译的过程如果带上下载软件包的时间比较漫长,很适合喝杯茶睡个午觉;(buildroot不能进行多线程编译)
编译完成的镜像包,是在 buildroot-2017.08 ‣ output ‣images ‣ rootfs.tar 中找到;
安装到第二分区
将镜像包复制到第二分区后,解压即可
# 请修改设备号
sudo umount /dev/sdX2 sudo mount /dev/sdX2 /mnt sudo cp ./rootfs.tar /mnt/ sudo tar -xf /mnt/rootfs.tar sudo rm /mnt/rootfs.tar sync sudo umount /dev/sdX2
另:检查 rootfs文件下的 /etc/inittab 是否已有以下声明:
ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100 # GENERIC_SERIAL // 串口登录使能
spi-flash 启动适配
对于从spi-flash启动系统,需要对 uboot / dts / 内核配置都有所修改,打包与烧写请参考 一键烧录及脚本使用说明
以下将以16M flash为例,介绍 spi flash 的适配过程。
分区规划
下表为分区规划表:
分区序号 | 分区大小 | 分区作用 | 地址空间及分区名 |
---|---|---|---|
mtd0 | 1MB (0x100000) | spl+uboot | 0x0000000-0x0100000 : “uboot” |
mtd1 | 64KB (0x10000) | dtb文件 | 0x0100000-0x0110000 : “dtb” |
mtd2 | 4MB (0x400000) | linux内核 | 0x0110000-0x0510000 : “kernel” |
mtd3 | 剩余 (0xAF0000) | 根文件系统 | 0x0510000-0x1000000 : “rootfs” |
uboot 修改
以下是对 uboot 进行适配的流程描述;
bootcmd修改
在uboot源码目录下 进入 ./include/configs/
修改 suniv.h
#define CONFIG_BOOTCOMMAND "sf probe 0:50000000; " \ "sf read 0x80C00000 0x100000 0x4000; " \ "sf read 0x80008000 0x110000 0x400000; " \ "bootz 0x80008000 - 0x80C00000"
按照行数解释如下:
挂载 spi-flash
读取 spi-flash 1M(0x100000)位置 64KB(0x4000)大小的 dtb 到地址 0x80C00000
读取 spi-flash 1M+64K(0x110000)位置 4MB(0x400000)大小的 zImage 到地址 0x80008000
从 0x80008000 启动内核,从 0x80C00000 读取设备树配置
回到 uboot 源码一级目录,
make ARCH=arm menuconfig
进入TUI配置;
取消勾选 [ ] Enable a default value for bootcmd
bootargs修改
勾选 [*] Enable boot arguments;
在下方一项中填入 bootargs 参数:
console=ttyS0,115200 panic=5 rootwait root=/dev/mtdblock3 rw rootfstype=jffs2
(root=/dev/mtdblock3 指的是mtd设备第三分区,分区指定在dts中声明)
dts 修改
修改内核源码目录下的 ./arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts
&spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_pins_a>; status = "okay"; spi-max-frequency = <50000000>; flash: w25q128@0 { #address-cells = <1>; #size-cells = <1>; compatible = "winbond,w25q128", "jedec,spi-nor"; reg = <0>; spi-max-frequency = <50000000>; partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; partition@0 { label = "u-boot"; reg = <0x000000 0x100000>; read-only; }; partition@100000 { label = "dtb"; reg = <0x100000 0x10000>; read-only; }; partition@110000 { label = "kernel"; reg = <0x110000 0x400000>; read-only; }; partition@510000 { label = "rootfs"; reg = <0x510000 0xAF0000>; }; }; }; };
此处在dts中为mtd设备预先划分好了分区内容,内核将会自动解析
另一种通过bootargs传递给内核进行解析分区信息的方法,请参考 Lichee Zero spi-flash 启动
内核配置修改
勾选 File systems ‣ Miscellaneous filesystems ‣ Journalling Flash File System v2 (JFFS2) support
jffs2
修改源码下的 ./drivers/mtd/spi-nor.c
修改对应spi-flash;如 w25q128 :
{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, // 修改为 (不使用sector,使用块擦除): { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, 0) },
二进制bin 打包
以16M 大小flash镜像打包脚本为例:
dd if=/dev/zero of=flashimg.bin bs=1M count=16 &&\ dd if=$YOUR_UBOOT_FILE of=flashimg.bin bs=1K conv=notrunc &&\ dd if=$YOUR_DTB_FILE of=flashimg.bin bs=1K seek=1024 conv=notrunc &&\ dd if=$YOUR_KERNEL_FILE of=flashimg.bin bs=1K seek=1088 conv=notrunc &&\ mkdir rootfs tar -xzvf $YOUR_ROOTFS_FILE -C ./rootfs &&\ cp -r $YOUR_MOD_FILE rootfs/lib/modules/ &&\ # 为根文件系统制作jffs2镜像包 # --pad参数指定 jffs2大小 # 由此计算得到 0x1000000(16M)-0x10000(64K)-0x100000(1M)-0x400000(4M)=0xAF0000 mkfs.jffs2 -s 0x100 -e 0x10000 --pad=0xAF0000 -d rootfs/ -o jffs2.img &&\ dd if=jffs2.img of=$YOUR_IMG_FILE bs=1K seek=5184 conv=notrunc &&\
以上脚本通过对一个生成的16M空bin文件填充 uboot、dtb、kernel、rootfs 生成 16M 镜像,如需修改,请注意各个文件的大小,修改成对应地址(注意对齐)。
至此,SPI系统各部分已编译完成,通过sunxi-fel进行烧写即可;
bin 烧录
sudo sunxi-fel -p spiflash-write $YOUR_IMG_FILE
或请参考镜像包中的 write_flash.sh 烧录脚本;
启动后使用 账号:root 密码:licheepi 登录
1. 克隆uboot
git clone https://github.com/Lichee-Pi/u-boot.git -b nano-v2018.01
2. 载入默认配置
如果需要生成在sdram里启动的uboot
make ARCH=arm licheepi_nano_defconfig
如果需要生成在spiflash里启动的uboot
make ARCH=arm licheepi_nano_spiflash_defconfig
3. 编译时可能遇到的问题以及解决办法
/bin/sh: 1: cc: not found
sudo apt install gcc
*** Configuration file “.config” not found!
请检查当前用户是否有当前文件夹的读写权限,然后再次载入默认配置.
/bin/sh: 1: python: not found
sudo apt install python
unable to execute ‘swig’: No such file or directory
error: command ‘swig’ failed with exit status 1
apt install swig
scripts/dtc/pylibfdt/libfdt_wrap.c:149:11: fatal error: Python.h: No such file or directory
apt install python-dev
/bin/sh: 1: bc: not found
apt install bc
3. 测试uboot
编译和使用sunxi-tools
1. 克隆sunxi-tools
git clone https://github.com/Icenowy/sunxi-tools.git -b f1c100s-spiflash
2. 编译sunxi-tools
安装sunxi-tools依赖库
sudo apt install libz libusb-1.0-0-dev
编译
make
安装
make install
3. 使用sunxi-tools
查看芯片信息
sudo sunxi-fel ver AWUSBFEX soc=00001663(F1C100s) 00000001 ver=0001 44 08 scratchpad=00007e00 00000000 00000000
列出所有芯片的信息
sudo sunxi-fel -l
加载并执行uboot的spl
sudo sunxi-fel spl 文件名
把文件内容写入内存指定地址(-p是显示写入进度) ``sudo sunxi-fel -p write 地址 文件名
调用指定地址的函数 sudo sunxi-fel exec 地址
显示spiflash的信息 sudo sunxi-fel spiflash-info
读取spiflash指定地址的数据并写入到文件 sudo sunxi-fel spiflash-read 地址 长度 存放数据的文件路径
写入指定文件的指定长度的内容到spiflash的指定地址 sudo sunxi-fel spiflash-write 地址 长度 存放数据的文件路径