一、嵌入式Linux整体组成
嵌入式Linux系统由4大部分构成:Bootloader(U-Boot)、Linux内核Kernel、根文件系统rootfs、应用程序APP
- U-Boot:引导加载程序,初始化硬件,把内核镜像加载到内存,传递启动参数,启动内核。
- Linux内核:管理硬件资源、进程、内存、驱动,提供系统调用,向上给应用层提供接口。
- 根文件系统:存放系统配置、库、命令程序、设备节点,内核启动后挂载rootfs。
- 应用程序:用户层代码(我们写的led/beep/key测试APP),通过系统调用操作驱动。
二、系统完整启动流程
- 上电 → CPU复位,执行固化在ROM里的一级启动代码(i.MX6ULL的BOOT ROM)
- 加载U-Boot到内存,运行U-Boot
- U-Boot初始化时钟、DDR、串口等基础硬件
- 读取环境变量,设置bootargs启动参数
- 从SD卡/TFTP/NAND读取zImage内核镜像、dtb设备树到DDR内存
- 调用内核入口,启动Linux内核
- 内核启动
- 内核自解压,初始化内存管理、进程调度
- 解析设备树dtb,根据DTS节点自动创建platform设备
- 初始化内置驱动、字符设备、misc子系统
- 挂载根文件系统rootfs
- 根文件系统启动
- 执行
/linuxrc或/sbin/init - 启动shell,进入串口命令行,开发板终端可用
- 执行
- 用户操作:
insmod加载驱动 → 运行APP测试硬件
三、U-Boot部分核心知识点
- U-Boot两大核心任务:硬件初始化 + 引导内核
- 关键命令:
printenv:打印环境变量setenv:设置环境变量saveenv:保存环境变量tftpboot:网络加载镜像bootz:启动zImage内核(附带dtb设备树)
- bootargs启动参数:告诉内核根文件系统位置、控制台串口。
四、设备树DTS
- 作用:描述板载硬件资源(引脚、GPIO、中断、寄存器),代替旧时代硬编码。
- 编译流程:
.dts源文件 → 编译器dtc →.dtb二进制文件,U-Boot把dtb一起传给内核。 - 节点结构:
node{ 属性; };,核心属性compatible用于platform总线匹配。 - 内核启动阶段解析dtb,自动生成platform设备。
五、Linux内核驱动三大版本(和前面笔记衔接)
驱动本质:内核模块,给用户APP提供访问硬件的接口,依赖内核,运行在内核态
版本1:纯Misc驱动(无设备树)
硬件信息GPIO号硬编码写在驱动代码
- 模块加载
insmod直接执行module_init入口函数 - 直接gpio_request申请引脚,misc_register注册杂项设备
- 缺点:软硬件耦合,换引脚要改驱动代码重编译
版本2:Misc + DTS(无Platform)
硬件信息写到设备树,驱动代码里使用of_find_node_by_name主动查找DTS节点,读取GPIO
- 不用硬编码GPIO
- 没有总线匹配机制,模块加载就直接初始化,写法不标准
版本3:Platform + DTS + Misc(标准企业写法)
Platform总线分离设备(DTS描述) 和驱动(platform_driver代码)
- DTS节点 = 设备,带compatible匹配字符串
- platform_driver里of_match_table存放匹配字符串
- 内核自动对比compatible,匹配成功自动调用probe函数
- probe函数:读取DTS硬件资源、申请GPIO、注册misc设备
- rmmod卸载驱动,自动调用remove释放资源
三者关系:
- Misc:负责生成
/dev/xxx设备节点,提供read/write供用户APP调用- DTS:描述硬件信息,软硬件解耦
- Platform总线:管理设备驱动匹配、驱动生命周期
六、内核态与用户态
- 用户态:APP程序,权限低,不能直接操作硬件。通过**系统调用(open/read/write/close)**陷入内核态。
- 内核态:驱动代码,拥有全部硬件访问权限,管理硬件寄存器。
- 数据交互:
- 用户→内核:
copy_from_user(LED/BEEP写操作) - 内核→用户:
copy_to_user(KEY读操作)
- 用户→内核:
七、模块操作命令(开发板shell)
sh
insmod xxx_drv.ko #加载内核模块
lsmod #查看已加载模块
rmmod xxx_drv #卸载模块
mdev -s #自动创建设备节点 /dev/xxx
dmesg #查看内核打印信息,调试驱动
八、根文件系统rootfs
- 包含:基础命令(ls、echo、cat)、动态库、配置脚本、设备目录模板
- 内核启动的最后一步:挂载rootfs,之后才能启动shell。
- 目录:
/dev设备节点、/proc内核信息、/syssysfs文件系统、/bin命令
九、补充:驱动的两种开发思路
- 模块方式(我们实验用的):驱动编译成
.ko,动态加载,不需要重新编译整个内核,调试方便。 - 内置到内核:驱动直接编译进zImage内核镜像,内核启动自动加载,适合产品正式发布。
十、整体逻辑串联一句话
上电U-Boot引导内核,内核解析设备树生成platform设备;我们写的Platform驱动加载后,内核匹配设备,执行probe,注册misc设备生成/dev节点;用户APP调用open/read/write系统调用进入内核驱动,控制LED/蜂鸣器/按键硬件。