ARM Linux 驱动开发简述
前面学习了 Ubuntu 操作系统、 Petalinux 工具的使用、系统移植,就是为了ARM Linux 驱动开发 做准备。
本篇将学习Linux 中的三大类驱动:字符设备驱动、块设备驱动和网络设备驱动。
其中字符设备驱动是占用篇幅最大的一类驱动,因为字符设备最多,从最简单的 LED 到 I2C、SPI、音频等都属于字符设备驱动的类型。
块设备和网络设备驱动要比字符设备驱动复杂,就是因为其复杂所以半导体厂商一般都给我们编写好了,大多数情况下都是直接可以使用的。
所谓的块设备驱动就是存储器设备的驱动,比如 EMMC、NAND、SD 卡和U 盘等存储设备,因为这些存储设备的特点是以存储块为基础,因此叫做块设备。
网络设备驱动就更好理解了,就是网络驱动,不管是有线的还是无线的,都属于网络设备驱动的范畴。
一个设备可以属于多种设备驱动类型,比如 USB WIFI 使用 USB 接口,所以属于字符设备,但是其又能上网,所以也属于网络设备驱动。
本篇围绕着三大设备驱动类型展开,尽可能详细的学习每种设备驱动的开发方式。
Linux 内核版本为 4.14.0,其支持设备树(Device tree),所以本篇所有例程均采用设备树。设备树将是本篇的重点。
(这段注没看明白,不抄过来了)
20另一种方式编译 ZYNQ 镜像
虽然 petalinux 功能上比较全面,但是在编译速度上太慢了!
采用分步式的方式编译启动开发板所需要的各种镜像文件,虽然步骤比较繁琐,但灵活性比较高。
1 创建 Petalinux 工程,生成 BOOT.BIN

对于 ZYNQ 而言,一个完整的 linux 系统包含 PS 和 PL 两个构件,其中 PS 构件包含 fsbl、uboot、设备树文件、linux 内核、根文件系统共 5 个要素,PL 构件包含 bit 文件一个要素,当不使用 PL 的时候,该要素非必须。
编写 linux 驱动的时候,经常改动的要素有设备树文件、linux 内核、根文件系统,当然如果改动 PL 的话还需改动 bit 文件。因而我们将这些要素独立出来,从而方便修改变更。也就是说我们将 bit 文件从原先的 BOOT.BIN 文件独立出来,将 image.ub 文件分开为内核 zImage和设备树 dtb。另外将根文件系统放到 SD 卡的 EXT4 分区,加载启动速度。下面我们正式开始。
本实验以正点原子领航者7010 为例,
先将hdf文件拷贝到Ubuntu系统目录下:

该文件是Vivado “Export Hardware“所导出的文件,包含了我们所搭建的硬件平台的配置信息,其后缀名.hdf 的含义为“Hardware Definition File”,即硬件定义文件。
创建 Petalinux 工程,导入hdf文件
mkdir petalinux20 //创建 Petalinux 工程存放目录
cd petalinux20
source /opt/pkg/petalinux/2018.3/settings.sh //设置 petalinux 工作环境
petalinux-create -t project --template zynq -n ALIENTEK-ZYNQ //创建 Petalinux 工程
cd ALIENTEK-ZYNQ //进入到 petalinux 工程目录下
petalinux-config --get-hw-description /home/wurao/petalinux/hdf //导入 hdf 文件
以上命令执行完成之后会自动在当前目录下创建一个名为 ALIENTEK-ZYNQ 的文件夹,也就是出厂镜像的 petalinux 工程对应的工程目录。
注:后面更新vivado工程的时候,只需要从vivado工程中导出hdf文件,并在该Petalinux工程下使用“petalinux-config --get-hw-description hdf 文件路径”命令即可。
hdf 文件导入成功之后会自动弹出 petalinux 工程配置窗口,跟着教程将 dtb 文件从 image.ub 文件中独立开来,并将根文件系统放到 SD 卡的 EXT4分区。(这一步直接看正点原子开发指南)

配置完成后,编译 fsbl 和 uboot,及生成 BOOT.BIN 文件,命令如下:
petalinux-build -c bootloader
petalinux-build -c u-boot
petalinux-package --boot --fsbl --u-boot --force
执行结果如下图所示:

可以看到 BOOT.BIN 文件仅包含 zynq_fsbl.elf 和 u-boot.elf 文件,而没有包含 bit 文件,而这两个文件我们基本不会再改动,所以后面无论编写任何 linux 驱动以及更改 Vivado工程,都不会改动 BOOT.BIN 文件了。
2 生成设备树文件
在Petalinux工程中执行编译uboot 后,会在工程的components/plnx_workspace/device-tree/device-tree/目录下生成设备树文件,如下图所示:

上图中红框圈出的是我们需要用到的设备树文件,skeleton.dtsi 文件我们一般不用。
Linux 设备树是是一个很重要的知识点,将会在后面的章节给大家详细说明,本章先不讲,这些文件后面我们会用到。
如果需要使用新 vivado 工程的时候,BOOT.BIN 文件是不需要变动的,但设备树文件会随着 Vivado 工程的不同而需要改动,所以需要重新生成设备树文件。重新生成设备树文件的方法有如下两种:(后面再回来看)
3 编译 kernel
不使用前面移植后的 Linux 内核源码,用一份新的 xilinx 官方 2018.3 版本(这个版本是 xilinx 设定的版本,其 linux 版本为 4.14.0)的内核源码。(下载见开发指南)
将内核源码压缩包文件拷贝到 Ubuntu 系统目录中,并解压:

直接在内核源码目录下进行编译,而不使用 petalinux 工具,因为内核也是经常改动的,而 Petalinux 编译慢。
1、添加设备树文件
将前面生成的设备树文件:
pcw.dtsi
pl.dtsi
system-top.dts
zynq-7000.dtsi
四个文件直接拷贝到内核源码目录下的 arch/arm/boot/dts 目录中。
cd /home/wurao/petalinux20/ALIENTEK-ZYNQ/components/plnx_workspace/device-tree/device-tree
cp pcw.dtsi pl.dtsi system-top.dts zynq-7000.dtsi /home/wurao/linux/kernel/linux-xlnx-xilinx-v2018.3/arch/arm/boot/dts
cd /home/wurao/linux/kernel/linux-xlnx-xilinx-v2018.3/arch/arm/boot/dts
vi system-top.dts
需要对 system-top.dts 文件进行一个简单地修改,修改之前内容如下:

修改之后如下所示:
/*
* CAUTION: This file is automatically generated by Xilinx.
* Version: HSI
* Today is: Mon Mar 16 02:51:23 2020
*/
/dts-v1/;
#include "zynq-7000.dtsi"
#include "pl.dtsi"
#include "pcw.dtsi"
/{
model = "Alientek ZYNQ Development Board";
chosen {
bootargs = "console=ttyPS0,115200 earlyprintk root=/dev/mmcblk0p2 rw rootwait";
stdout-path = "serial0:115200n8";
};
aliases {
ethernet0 = &gem0;
i2c0 = &i2c2;
i2c1 = &i2c0;
i2c2 = &i2c1;
serial0 = &uart0;
serial1 = &uart1;
spi0 = &qspi;
};
memory {
device_type = "memory";
reg = <0x0 0x20000000>;
};
};
&gem0 {
local-mac-address = [00 0a 35 00 1e 53];
};
&qspi {
#address-cells = <1>;
#size-cells = <0>;
flash0: flash@0 {
compatible = "n25q512a","micron,m25p80";
reg = <0x0>;
#address-cells = <1>;
#size-cells = <1>;
spi-max-frequency = <50000000>;
partition@0x00000000 {
label = "boot";
reg = <0x00000000 0x00500000>;
};
partition@0x00500000 {
label = "bootenv";
reg = <0x00500000 0x00020000>;
};
partition@0x00520000 {
label = "kernel";
reg = <0x00520000 0x00a80000>;
};
partition@0x00fa0000 {
label = "spare";
reg = <0x00fa0000 0x00000000>;
};
};
};
gg//到达顶部
dG//全部删除
鼠标中键//粘贴
修改完成之后保存退出即可!
以上主要修改了 bootargs 属性、添加了 model 属性、网口 0 的 MAC 地址以及给 qspi 进行了分区操作。修改完成之后,我们还需要修改 arch/arm/boot/dts 目录下的 Makefile 文件,将设备树添加上去,如下:

修改完成之后保存退出即可!
2、defconfig 配置
cd /home/wurao/linux/kernel/linux-xlnx-xilinx-v2018.3
在内核源码目录下执行下面这条命令对内核进行 defconfig 配置:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xilinx_zynq_defconfig

3、menuconfig 配置
这里我们暂时就不进行配置,以后有需要的时候再配,先保持默认!
4、编译内核
执行下面这条命令编译内核源码:
sptl
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j10

编译完成之后会在 arch/arm/boot/目录下生成一个名为 zImage 的内核镜像文件,后面我们在用。
5、编译设备树
在内核里边我们需要单独编译出设备树的 dtb 文件,前面已经将我们所需要的设备树文件拷贝到内核的 arch/arm/boot/dts 目录下了,接下来执行下面这条命令编译 system-top.dtb文件:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- system-top.dtb -j10

编译成功之后会在 arch/arm/boot/dts 目录下生成 system-top.dtb 文件。
4 编译 rootfs
根文件系统我们直接使用 petalinux 进行编译即可。
进入到 Petalinux 工程目录下,为了免去后面每次启动 linux 都要手动输入密码进入系统,所以我们先配置根文件系统免密码登录,进入根文件系统配置界面的命令如下:
cd ~/petalinux20/ALIENTEK-ZYNQ
sptl
petalinux-config -c rootfs
具体操作看开发指南
配置完成后,保存退出。
接下来直接编译根文件系统:
petalinux-build -c rootfs
等待其编译完成,完成之后产生的根文件系统压缩包在 images/linux 目录下,如下所示:
cd images/linux/
ls

因为我们要使用 SD 卡启动,并且 SD 卡会有一个 EXT4 格式的分区专门存放根文件系统,所以我们要使用压缩格式的根文件系统,例如 rootfs.tar.gz 或 rootfs.tar.bz2。
5 启动开发板
经过上面一系列的过程之后,我们就已经得到了启动开发板的所有所需的镜像文件了。例如我们使用 petalinux 工具会生成 image.ub 和 BOOT.BIN 文件,使用这两个文件我们就可以启动开发板了,但是这里我们不这样做。
前面学习过 image.ub 这个文件的本质,那么它其实是多个文件组合在一起的,包括内核镜像、dtb 以及根文件系统,这样的做法有一个弊端,不够灵活,一个变了整个 image.ub文件就得重新制作一遍,很麻烦。同样 BOOT.BIN 文件是 fsbl 镜像、u-boot 镜像以及 pl 端 bit文件集合在一起的,那么既然是集合在一起的,那么我们单独使用也是可以的。
所以我们这里的思路就是将内核镜像文件 zImage、内核设备树文件以及根文件系统从image.ub 文件中分离出来;而将 bit 文件从 BOOT.BIN 文件中分离出来,这样做之后我们的 SD卡中将会存在 5 部分内容:zImage、dtb、rootfs、bit 以及 BOOT.BIN(fsbl 镜像与 u-boot 镜像的集合体),明确之后我们将他们拷贝到我们的 SD 卡中。
1、制作 SD 启动卡
前面制作过,有时间再总结一下。
2、拷贝镜像到 FAT 分区
将前面过程当中生成的各种镜像文件拷贝到 SD 启动卡的 FAT 分区,包括:
文件 | 描述 | 所在目录 |
zImage | 内核镜像 | 内核源码目录arch/arm/boot/zImage |
system-top.dtb | 内核设备树 dtb 文件 | 内核源码目录arch/arm/boot/dts/system-top.dtb |
system.bit | pl 端 bitstream 文件 | Petalinux工程目录下的 images/linux/system.bit |
cd /home/wurao/linux/kernel/linux-xlnx-xilinx-v2018.3
cp arch/arm/boot/zImage /media/wurao/boot
cp arch/arm/boot/dts/system-top.dtb /media/wurao/boot
cd /home/wurao/petalinux20/ALIENTEK-ZYNQ
cp images/linux/system.bit /media/wurao/boot
接下来我们需要将 BOOT.BIN 文件拷贝到 FAT 分区
cd /home/wurao/petalinux20/ALIENTEK-ZYNQ/images/linux
cp BOOT.BIN /media/wurao/boot

为了方便、好看,将 system-top.dtb 文件进行了重命名 system.dtb。
cp system-top.dtb system.dtb
rm system-top.dtb
3、将根文件系统解压到 EXT4 分区
cd /home/wurao/petalinux20/ALIENTEK-ZYNQ/images/linux
sudo tar -xzf rootfs.tar.gz -C /media/wurao/rootfs
解压完成之后执行 sync 命令将数据同步到 SD 卡中,之后卸载 SD 启动卡,卸载成功之后拔掉它。
sync
umount /dev/sdb1 /dev/sdb2
4、启动开发板
将我们做好的启动卡插入开发板,连接电源、串口启动。
需要对 U-Boot 环境变量进行修改,具体见教程。
变量设置完成之后,执行 saveenv 命令保存环境变量到 QSPI Flash 中,那么下次就不用再设置了。
已经设置好了,下次就不用设置了。