当前位置:首页 > 技术 > LINUX > 正文内容

荔枝派Nano 全流程指南

watrt2个月前 (07-26)LINUX640

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.zip,放入源码主目录进行替换 (若下载时文件名有变,请重命名回 .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

http://xn--bnq31s.xn--fiqs8s/zb_users/upload/2020/07/20200726093455_44164.png

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 地址 长度 存放数据的文件路径


发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。