一、环境搭建
1. 双网卡配置
嵌入式开发中,Ubuntu 需要同时满足两个需求:
上外网:用 apt-get 下载软件。
和开发板通信:用 tftp 传文件、nfs 挂载根文件系统。
所以需要双网卡:
| 网卡 | 模式 | 用途 |
|---|---|---|
ens33 | NAT | 上外网 |
ens37 | 桥接 | 连接开发板 |
配置要点:
桥接模式必须桥接到有线网卡,不能选“自动”。
Windows 端有线网卡 IP 设为
192.168.1.200,子网掩码255.255.255.0,网关留空。关闭 Windows 防火墙。
Ubuntu 端
ens37设为192.168.1.100。
2. tftp 服务器
tftp 用于从 Ubuntu 下载内核镜像和设备树到开发板。
bash
sudo apt-get install tftpd-hpa tftp sudo mkdir -p /home/linux/tftpboot sudo chmod 0777 /home/linux/tftpboot sudo vim /etc/default/tftpd-hpa
配置文件:
text
TFTP_USERNAME="tftp" TFTP_DIRECTORY="/home/linux/tftpboot" TFTP_ADDRESS=":69" TFTP_OPTIONS="--secure -l -c"
重启服务:
bash
sudo systemctl restart tftpd-hpa
3. nfs 服务器
nfs 用于开发板挂载 Ubuntu 的根文件系统。
bash
sudo apt-get install nfs-kernel-server sudo vim /etc/exports
添加:
text
/home/linux/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
重启服务:
bash
sudo systemctl restart nfs-kernel-server sudo showmount -e
4. 交叉工具链
PDF 指定的是gcc-linaro-4.9.4-2017.01,不能用 Ubuntu 自带的 11.4.0(会导致GLIBC_2.34 not found)。
bash
sudo mkdir -p /home/linux/tools/opt sudo tar -xvf gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz -C /home/linux/tools/opt vim ~/.bashrc
添加(放在 $PATH 前面):
bash
export PATH=/home/linux/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin:$PATH
生效并验证:
bash
source ~/.bashrc arm-linux-gnueabihf-gcc -v # 应显示 4.9.4
二、模式三:U-Boot + tftp + nfs
模式三是开发阶段最常用的方式:
U-Boot 烧写到 SD 卡。
zImage 和 dtb 通过 tftp 下载。
rootfs 通过 nfs 挂载。
U-Boot 配置
bash
setenv ipaddr 192.168.1.50 setenv ethaddr 00:04:9f:04:d2:35 setenv gatewayip 192.168.1.1 setenv netmask 255.255.255.0 setenv serverip 192.168.1.100 saveenv # 分段设置 bootcmd,避免单条命令过长被截断 setenv bootcmd1 'tftp 80800000 zImage' setenv bootcmd2 'tftp 83000000 imx6ull-alientek-emmc.dtb' setenv bootcmd3 'bootz 80800000 - 83000000' setenv bootcmd 'run bootcmd1; run bootcmd2; run bootcmd3' setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.100:/home/linux/nfs/rootfs rw ip=192.168.1.50:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off' saveenv
启动成功
text
VFS: Mounted root (nfs filesystem) on device 0:14. Please press Enter to activate this console. / #
三、四个核心文件
模式三启动依赖四个关键文件,各自作用不同:
1. U-Boot(u-boot.imx)
作用:引导加载程序,负责硬件初始化、加载内核镜像、传递参数。
烧写位置:SD 卡。
启动流程:芯片上电 → bootROM → SPL → U-Boot → 内核。
核心功能:
初始化 DDR、时钟、串口、网卡。
提供命令行交互(
=>提示符)。通过 tftp 下载内核和设备树。
通过
bootz启动内核。
2. zImage(zImage)
作用:Linux 内核镜像,操作系统的核心。
加载方式:通过 tftp 下载到内存地址
80800000。功能:进程调度、内存管理、虚拟文件系统、网络接口、进程间通信。
启动后:根据
bootargs挂载根文件系统。
3. 设备树(imx6ull-alientek-emmc.dtb)
作用:描述硬件平台的资源信息(寄存器地址、中断、时钟、GPIO 等)。
加载方式:通过 tftp 下载到内存地址
83000000。来源:由
.dts文件编译生成。意义:Linux 3.x 以后,硬件信息从内核独立出来,驱动通过设备树获取硬件信息,实现设备与驱动分离。
4. 根文件系统(rootfs.tar.bz2)
作用:Linux 系统运行的基础,提供文件资源管理、用户交互等功能。
挂载方式:通过 nfs 挂载 Ubuntu 的
/home/linux/nfs/rootfs。内容:
/bin、/dev、/etc、/lib、/usr等目录。制作方式:用 BusyBox 构建(后续章节会讲)。
四个文件的关系
text
U-Boot (SD卡) ↓ 初始化硬件,提供命令行 ↓ tftp 下载 zImage (内存 80800000) + 设备树 (内存 83000000) ↓ bootz 启动 内核启动 ↓ 根据 bootargs 根文件系统 (nfs 挂载 /home/linux/nfs/rootfs) ↓ 进入 Linux 系统
简单理解:
U-Boot:搬运工,负责把内核和设备树搬到内存。
zImage:操作系统核心,负责管理硬件和进程。
设备树:硬件说明书,告诉内核硬件长什么样。
根文件系统:用户空间,提供命令、库、配置文件。
四、内核编译及裁剪
内核编译是驱动开发的基础,重点搞懂:
1. 编译流程
bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
生成:
arch/arm/boot/zImage:内核镜像。arch/arm/boot/dts/imx6ull-alientek-emmc.dtb:设备树。
2. 内核源码结构
| 目录 | 内容 |
|---|---|
arch | 架构相关代码 |
drivers | 设备驱动(重点) |
fs | 文件系统 |
kernel | 内核核心 |
mm | 内存管理 |
net | 网络协议栈 |
3. 设备树
Linux 3.x 以后,硬件信息从内核独立出来,称为设备树:
.dts:设备树源码。.dtb:编译后的二进制。驱动通过设备树获取寄存器地址、中断、GPIO 等信息。
4. 内核里的汇编
内核里 95% 以上是 C 语言,汇编只在:
架构相关启动代码(
head.S)。上下文切换。
原子操作。
写驱动不需要汇编,用 C 语言就行。
五、总结
嵌入式开发环境搭建是驱动开发的基础,核心要点如下:
双网卡配置:Ubuntu 需要同时满足上外网和与开发板通信两个需求。NAT 模式负责上外网,桥接模式负责与开发板连接,桥接必须桥接到有线网卡。
tftp 服务器:用于开发板从 Ubuntu 下载内核镜像和设备树文件,管理目录为
/home/linux/tftpboot。nfs 服务器:用于开发板挂载 Ubuntu 的根文件系统,共享目录为
/home/linux/nfs/rootfs,实现 Ubuntu 与开发板之间的文件实时同步。交叉工具链:PDF 指定的是 gcc-linaro-4.9.4,用于在 x86 平台上编译能在 ARM 平台运行的代码,是驱动开发和应用程序编译的基础。
四个核心文件:
U-Boot:引导加载程序,负责硬件初始化和加载内核。
zImage:Linux 内核镜像,操作系统的核心。
dtb:设备树,描述硬件资源信息,实现设备与驱动分离。
rootfs:根文件系统,提供文件资源和用户交互。
内核编译及裁剪:内核里 95% 以上是 C 语言,汇编只涉及启动代码、上下文切换、原子操作。写驱动不需要汇编,用 C 语言即可。设备树是重点,驱动通过设备树获取硬件信息。
模式三:U-Boot 烧写到 SD 卡,zImage 和 dtb 通过 tftp 下载,rootfs 通过 nfs 挂载。这是开发阶段最常用的方式,修改内核或文件系统后无需重新烧录,重启即可加载最新版本。