ARM-驱动-02-Linux 内核开发环境搭建与编译

一、开发环境准备

1.1 文件准备

bash 复制代码
# 1. 将内核镜像和设备树拷贝到 TFTP 服务目录
cp arch/arm/boot/zImage ~/tftpboot/
cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ~/tftpboot/1.dtb
改成1.dtb的原因是我文件夹里面的是这个名字
# 2. 将根文件系统解压到 NFS 服务目录
cd /home/linux/nfs
(sudo) tar -xvf rootfs.tar.bz2

⚠️ 建议独立存放,避免混淆。不可将文件放于系统根目录,应使用专用目录并设置权限。

1.2 服务验证

验证 TFTP 服务:

bash 复制代码
# 在主机终端登录 tftp,验证文件可正常下载
tftp <服务器IP>
get zImage       # 下载文件
put xxx.dtb      # 上传文件

验证 NFS 服务:

bash 复制代码
# 在宿主机挂载验证
mount -t nfs <服务器IP>:/home/linux/nfs /mnt

# 验证完毕后必须卸载!否则原目录文件会被隐藏
umount /mnt

二、uboot 命令行

⚠️ 进入方式:开发板上电后,倒计时归零前按回车键,即可进入 uboot 命令行。

2.1 基础命令

命令 说明
help? 查看所有命令列表
reset 重启开发板
printenv 查看所有环境变量
setenv ipaddr 192.168.1.122 设置环境变量(有值=设置)
setenv ipaddr 删除环境变量(无值=删除)
saveenv 保存环境变量到存储介质
ping <IP> 网络连通性测试

⚠️ 所有环境变量必须执行 saveenv 保存,否则重启后全部失效!

2.2 网络参数配置

bash 复制代码
# 设置开发板 IP(uboot 阶段使用)
setenv ipaddr   192.168.1.122

# 设置 TFTP 服务器 IP(ubuntu 主机 IP)
setenv serverip 192.168.1.3

# 设置 MAC 地址(避免网络通信失败)
setenv ethaddr  xx:xx:xx:xx:xx:xx

# 保存
saveenv

# 测试网络
ping 192.168.1.3

网络失败排查:检查 IP 是否与服务器同网段、子网掩码是否匹配。

2.3 内核与设备树下载(tftp)

bash 复制代码
# 下载 zImage 到内存 0x80800000 地址处
tftp 0x80800000 zImage

# 下载设备树 dtb 到内存 0x83000000 地址处
tftp 0x83000000 1.dtb

下载过程中 # 号表示数据包传输,每个 # 代表一个数据包,无错误提示即为成功。

⚠️ 下载地址必须与 bootz 启动命令中的地址完全一致,否则内核无法正确加载。

2.4 启动内核

bash 复制代码
# 启动内核(zImage地址 - ramdisk地址 dtb地址)
# 中间的 - 表示没有 ramdisk
bootz 0x80800000 - 0x83000000

2.5 设置启动参数 bootargs(重点)

bash 复制代码
setenv bootargs root=/dev/nfs \
    nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3 \
    ip=192.168.1.123 \
    console=ttymxc0,115200 \
    init=/linuxrc

bootargs 参数详解:

参数 说明 示例值
root 根文件系统类型和位置 /dev/nfs(NFS类型)
nfsroot NFS 文件系统的 IP + 路径 192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3
ip 内核启动阶段使用的 IP 地址 192.168.1.123(与uboot中ipaddr不同!)
console 控制台串口设备及波特率 ttymxc0,115200
init 根文件系统挂载完成后启动的第一个进程(1号进程) /linuxrc

⚠️ 注意:ip(内核IP)和 uboot 中的 ipaddr(uboot IP)是两个独立参数,可以不同!

2.6 启动验证

bash 复制代码
# 成功启动后终端会显示完整的 Linux 根目录结构

# 在开发板上创建文件
touch 123456

# 在宿主机 NFS 目录中验证文件是否同步生成
ls /home/linux/nfs/imx6/rootfs/
# 能看到 123456 文件,说明 NFS 文件系统同步正常 ✓

三、内核编译

3.1 准备工作

bash 复制代码
# 拷贝内核源码到 ubuntu 并解压
tar -xvf linux-imx-xxx.tar.bz2    # 支持自动识别压缩格式
cd linux-imx-xxx/

推荐使用 Ctrl+Shift+T 开多个终端,Alt+1/2/3/4 切换,提升开发效率。

3.2 内核配置机制

内核通过 Kconfig + Makefile 两个文件协作决定编译哪些模块:

Kconfig --- 定义配置选项(菜单结构)

kconfig 复制代码
# 示例 Kconfig 片段
config DEMO
    bool "Demo driver"
    default y
    help
      Enable demo driver.

Makefile --- 根据配置决定是否编译

makefile 复制代码
# 示例 Makefile 片段
obj-$(CONFIG_MOD1) += mod1.o    # CONFIG_MOD1=n 则不编译
obj-$(CONFIG_MOD2) += mod2.o    # CONFIG_MOD2=y 则编译

.config 文件 --- 所有配置项的汇总,由工具自动生成

复制代码
CONFIG_MOD1 = n
CONFIG_MOD2 = y

⚠️ .config 文件由 make menuconfig 工具自动生成,禁止手动修改!

Kconfig 配置类型说明:

类型 含义
bool 布尔型,只能 y(编译进内核)或 n(不编译)
tristate 三态,可以 y(内核)、m(模块)或 n(不编译)
depends on 弱依赖,依赖项不满足时此选项不显示
select 强依赖,选中此项时自动选中依赖项

3.3 内核编译标准流程

⚠️ 所有操作均在内核源码的顶层目录下执行!

第一步:拷贝默认配置文件

bash 复制代码
cp arch/arm/configs/imx6_alientek_emmc_defconfig   .config

第二步:图形化配置(可选,确认配置)

bash 复制代码
make menuconfig
# 配置完的结果保存在 .config 中
# 可通过 / 搜索配置项
# 退出时选择保存

第三步:编译内核镜像

bash 复制代码
make zImage             # 仅编译 zImage
make zImage -j20        # 多线程编译,n 代表线程数,推荐 CPU 核心数的2倍

第四步:编译设备树

bash 复制代码
make dtbs               # 编译所有设备树(生成 .dtb 文件)
make all                # 全编译(包含 zImage + dtbs + modules)

输出文件位置:

复制代码
arch/arm/boot/zImage                          ← 内核镜像
arch/arm/boot/dts/imx6ull-alientek-emmc.dtb   ← 设备树文件

第五步:拷贝到 TFTP 目录,重启验证

bash 复制代码
cp arch/arm/boot/zImage ~ /tftpboot/
cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ~ /tftpboot/1.dtb

3.4 向内核新增文件(完整流程)

以向 drivers/char 目录下新增 demo.c 为例:

第一步:创建源文件

bash 复制代码
# 在 drivers/char 目录下创建并编辑 demo.c
vim drivers/char/demo.c

第二步:修改同目录 Makefile,新增一行

makefile 复制代码
# drivers/char/Makefile 中添加:
obj-$(CONFIG_DEMO) += demo.o

第三步:修改同目录 Kconfig,新增配置项

kconfig 复制代码
# drivers/char/Kconfig 中添加:
config DEMO
    bool "Demo driver"
    default y
    help
      Enable demo driver.

第四步:运行 menuconfig 使能新选项

bash 复制代码
make menuconfig
# 找到 DEMO 选项,选中(Y)
# 保存退出 → .config 中出现 CONFIG_DEMO=y

第五步:重新编译内核

bash 复制代码
make zImage -j20
# 无需重新编译 dtb(设备树未改动)

第六步:验证

bash 复制代码
# 拷贝到 TFTP 目录
cp arch/arm/boot/zImage ~/tftpboot/

# 重启开发板,内核启动日志中出现 demo 模块的打印信息即表示成功
# 如:demo: init

四、完整操作流程速查

4.1 首次启动开发板(NFS + TFTP 方式)

bash 复制代码
# ===== ubuntu 主机端 =====
# 1. 准备文件
cp zImage ~/tftpboot/
cp imx6ull-alientek-emmc.dtb ~/tftpboot/
tar -xvf rootfs.tar.bz2 -C  /home/linux/nfs/imx6/rootfs/

# ===== 开发板 uboot 端 =====
# 2. 设置网络(首次需要,之后 saveenv 保存了可跳过)
setenv ipaddr   192.168.1.122
setenv serverip 192.168.1.3
setenv ethaddr  xx:xx:xx:xx:xx:xx
saveenv

# 3. 测试网络
ping 192.168.1.3

# 4. 下载内核和设备树
tftp 0x80800000 zImage
tftp 0x83000000 imx6ull-alientek-emmc.dtb

# 5. 设置启动参数
setenv bootargs root=/dev/nfs nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3 ip=192.168.1.123 console=ttymxc0,115200 init=/linuxrc
saveenv

# 6. 启动内核
bootz 0x80800000 - 0x83000000

4.2 修改内核并验证(日常开发)

bash 复制代码
# 1. 修改代码 / 新增文件
# 2. 编译
make zImage -j20
# 3. 拷贝到 TFTP
cp arch/arm/boot/zImage ~/tftpboot/
# 4. 开发板 uboot 下重新下载并启动
tftp 0x80800000 zImage
bootz 0x80800000 - 0x83000000

五、关键概念速查

概念 说明
zImage 压缩后的内核镜像,加载到 0x80800000
dtb 设备树二进制文件,描述硬件信息,加载到 0x83000000
bootz uboot 启动 zImage 格式内核的命令
bootargs uboot 传给内核的启动参数字符串
nfsroot 指定 NFS 根文件系统的服务器IP和路径
.config 内核所有配置项的汇总文件,由 menuconfig 生成
Kconfig 定义 make menuconfig 的可配置选项和菜单结构
make menuconfig 图形化内核配置工具,结果保存到 .config
defconfig 厂商提供的默认配置文件,位于 arch/arm/configs/
obj-$(CONFIG_XXX) Makefile 中根据配置变量决定是否编译对应 .o 文件
-j20 make 多线程编译参数,20 为线程数

相关推荐
蜡台6 小时前
Python包管理工具pip完全指南-----2
linux·windows·python
^—app5668666 小时前
游戏运存小启动不起来临时解决方法
运维·服务器
Ujimatsu6 小时前
虚拟机安装Debian 13.x及其常用软件(2026.4)
linux·运维·ubuntu
千百元6 小时前
zookeeper启不来了
linux·zookeeper·debian
志栋智能7 小时前
超自动化安全:构建智能安全运营的核心引擎
大数据·运维·服务器·数据库·安全·自动化·产品运营
AnalogElectronic8 小时前
linux 测试网络和端口是否连通的命令详解
linux·网络·php
Edward111111119 小时前
4月28日防火墙问题
linux·运维·服务器
想学后端的前端工程师9 小时前
【补充内外网突然不通的情况】
运维·服务器
面汤放盐9 小时前
何时使用以及何时不应使用微服务:没有银弹
java·运维·云计算
子琦啊9 小时前
【算法复习】字符串 | 两个底层直觉,吃透高频题
linux·运维·算法