ARM嵌入式Linux教程是嵌入式开发领域的重要学习路径,结合ARM架构的高效性能与Linux系统的开源灵活性,广泛应用于物联网、工业控制、智能设备等场景,本文将从基础概念、环境搭建、开发流程、关键组件及实践案例等方面,系统介绍ARM嵌入式Linux的开发要点,帮助初学者快速入门。

ARM嵌入式Linux基础概念
ARM嵌入式Linux是以ARM架构处理器为核心硬件,裁剪并定制Linux内核及根文件系统,形成适用于嵌入式环境的操作系统,其核心优势包括:
- 低功耗设计:ARM架构采用RISC(精简指令集)设计,功耗控制优异,适合移动设备和嵌入式场景;
- 高性能计算:新一代ARM Cortex-A系列支持多核、64位运算,可满足复杂应用需求;
- 开源生态:Linux内核及工具链完全开源,开发者可自由裁剪、定制,降低开发成本;
- 丰富的外设支持:ARM处理器普遍集成UART、I2C、SPI、GPIO等接口,便于连接传感器、显示屏等外设。
学习ARM嵌入式Linux需掌握ARM体系结构(如Cortex-M/A/R系列区别)、Linux内核机制(进程管理、内存管理、驱动模型)及嵌入式开发流程(交叉编译、系统移植、调试)。
开发环境搭建
硬件环境
- 开发板:选择主流ARM开发板,如树莓派(Cortex-A系列)、STM32MP1( Cortex-A7+M4)、Tiny4412(Cortex-A9)等,初学者建议从树莓派入手,社区资源丰富;
- 调试工具:JTAG/SWD调试器(如J-Link、ST-Link)用于硬件级调试;串口模块(USB转TTL)用于打印系统日志(波特率通常为115200);
- 存储介质:SD卡(用于树莓派等板卡启动)、eMMC或NAND Flash(工业级设备常用)。
软件环境
- 宿主机系统:推荐Ubuntu 20.04/22.04 LTS,兼容多数开发工具;
- 交叉编译工具链:用于在宿主机(x86架构)上生成目标平台(ARM架构)的可执行文件,常用工具链包括:
- Linaro GCC:ARM官方推荐,支持Cortex-A/R/M系列;
- ARM Compiler 6:ARM自研工具链,性能优化更佳;
- Buildroot/Yocto Project:自动生成包含工具链、内核、根文件系统的完整镜像。
| 常用工具链 | 适用架构 | 特点 | 下载地址 |
|---|---|---|---|
| Linaro GCC 9.2 | ARMv7-A/Aarch64 | 开源免费,社区支持好 | Linaro官网 |
| ARM Compiler 6 | ARMv8-A/Aarch64 | 商业工具,性能优化强 | ARM Developer官网 |
| Buildroot 2023.02 | ARM/PowerPC等 | 自动化构建,支持数百种外设驱动 | Buildroot官方仓库 |
宿主机配置
安装必要依赖:
sudo apt update && sudo apt install -y build-essential git make libncurses-dev bison flex
配置交叉编译工具链环境变量(以Linaro GCC为例):
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin export CROSS_COMPILE=arm-linux-gnueabihf-
核心开发流程
ARM嵌入式Linux开发流程可分为“硬件适配→系统移植→应用开发”三大阶段,具体步骤如下:
硬件适配与BSP开发
板级支持包(BSP)是连接硬件与操作系统的桥梁,需完成:

- 原理图分析:梳理开发板处理器型号、外设接口(如LCD、摄像头、网络芯片);
- 设备树(Device Tree)编写:描述硬件资源(内存地址、中断号、外设节点),替代传统硬编码,避免内核与硬件强耦合。
示例(简单节点):/ { memory@40000000 { device_type = "memory"; reg = <0x40000000 0x80000000>; /* 2GB内存 */ }; uart0: serial@13800000 { compatible = "ns16550a"; reg = <0x13800000 0x1000>; interrupts = <10>; clock-frequency = <24000000>; }; };
Bootloader移植
Bootloader是系统启动的第一段代码,负责初始化硬件、加载内核,常用Bootloader为U-Boot,移植步骤:
- 获取U-Boot源码:从官网下载最新稳定版(如v2023.07);
- 配置开发板:执行
make menuconfig,选择目标板卡(如Configurations -> TI -> beaglebone)或自定义配置; - 编译与烧录:执行
make生成u-boot.bin,通过SD卡或烧录工具写入启动介质。
Linux内核移植与裁剪
- 内核配置:使用
make ARCH=arm menuconfig开启必要功能(如支持SD卡、串口、设备树); - 编译内核:执行
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf -j4生成zImage(内核镜像)和.dtb(设备树 blob); - 裁剪优化:关闭不需要的驱动(如 unused USB devices)、文件系统(如 JFFS2),减小内核体积。
根文件系统构建
根文件系统包含用户空间程序、库文件及配置,常用构建方式:
- BusyBox:精简工具集,提供基础命令(ls、cd、mount等),适合小型系统;
- Buildroot:自动化构建工具,可集成BusyBox、dropbear(SSH)、lighttpd(Web服务器)等;
- Yocto Project:适合大型项目,支持高度定制化,但学习曲线较陡。
示例(Buildroot构建):
make savedefconfig make menuconfig # 选择目标架构(ARM little endian)、根文件系统类型(ext4) make -j4
生成output/images/目录下的rootfs.tar(根文件系统镜像)和boot.vfat(引导分区)。
应用程序开发
嵌入式应用通常分为用户空间程序(如C/C++脚本)和内核驱动(如字符设备、平台驱动),开发流程:
- 交叉编译应用:使用工具链编译用户程序,如
arm-linux-gnueabihf-gcc hello.c -o hello; - 部署到目标板:通过NFS网络文件系统或TFTP将应用及根文件系统烧录到开发板;
- 调试:通过串口打印日志(
printf/dmesg)或GDB远程调试。
关键组件详解
U-Boot启动流程
U-Boot启动过程分为:

- 第一阶段(BL1):硬件初始化(时钟、内存),跳转到第二阶段;
- 第二阶段(BL2):加载U-Boot主程序,设置设备树,启动内核。
常用命令:printenv # 查看环境变量(如bootcmd:启动命令) setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2' # 设置启动参数 saveenv # 保存环境变量 bootz 0x82000000 - 0x88000000 # 加载zImage(地址0x82000000)和设备树(地址0x88000000)
Linux内核模块
内核模块用于动态加载/卸载驱动,无需重启系统,示例(字符设备驱动):
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "hello_dev"
static int major_num;
static ssize_t hello_read(struct file *file, char __user *buf, size_t len, loff_t *offset) {
printk(KERN_INFO "Hello, ARM Linux!n");
return 0;
}
static struct file_operations fops = {
.read = hello_read,
};
static int __init hello_init(void) {
major_num = register_chrdev(0, DEVICE_NAME, &fops);
printk(KERN_INFO "Hello module loadedn");
return 0;
}
static void __exit hello_exit(void) {
unregister_chrdev(major_num, DEVICE_NAME);
printk(KERN_INFO "Hello module unloadedn");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL"); 编译模块:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf -C /path/to/linux M=$(pwd) modules,加载模块:insmod hello.ko。
根文件系统类型对比
| 文件系统类型 | 特点 | 适用场景 |
|---|---|---|
| initramfs | 内存根文件系统,无需存储介质 | 系统救援、临时启动 |
| ext4 | 日志文件系统,可靠性高 | SD卡、eMMC等存储设备 |
| JFFS2 | 适用于NAND Flash,支持磨损均衡 | 嵌入式存储(如路由器) |
| SquashFS | 只读压缩文件系统,体积小 | 固件存储(如OpenWrt) |
实践案例:树莓派4B最小系统移植
准备工作
- 开发板:树莓派4B(Cortex-A72,8GB RAM);
- 宿主机:Ubuntu 22.04,安装Buildroot 2023.02。
步骤
- 配置Buildroot:
make raspberrypi4_defconfig # 加载树莓派4B默认配置 make menuconfig # 开启串口(Serial port support -> enable)
- 编译镜像:
make -j4,生成output/images/sdcard.img(SD卡镜像); - 烧录镜像:使用
dd命令将镜像写入SD卡:sudo dd if=output/images/sdcard.img of=/dev/sdX bs=4M status=progress
- 启动验证:将SD卡插入树莓派,通过串口工具连接(波特率115200),登录用户名
root,无密码,执行uname -a查看内核版本。
调试与优化技巧
- 串口调试:通过
printk打印内核日志,设置日志级别(printk(KERN_INFO "xxx")); - JTAG调试:使用OpenOCD连接J-Link,加载GDB调试内核或应用;
- 性能优化:关闭内核不必要的功能(如
CONFIG_DEBUG_INFO=n)、使用cacheflush优化内存访问; - 常见问题:
- 无法启动:检查设备树节点是否正确、U-Boot环境变量
bootargs是否匹配根文件系统分区; - 驱动加载失败:确认模块签名(
MODULE_LICENSE)、设备号是否冲突。
- 无法启动:检查设备树节点是否正确、U-Boot环境变量
FAQs
Q1:初学者如何选择ARM开发板?
A1:建议从社区活跃、资料丰富的开发板入手,如树莓派(适合入门,生态完善)、STM32MP1(结合Cortex-A7+M4,适合学习RTOS与Linux双系统)、Allwinner H6(性价比高,支持4K视频),若预算有限,可选择二手开发板或国产板卡(如香橙派、nanopi)。
Q2:交叉编译工具链如何安装与配置?
A2:推荐使用Linaro GCC,步骤如下:
- 下载工具链:
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz; - 解压并移动到
/opt:sudo tar xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt; - 配置环境变量:在
~/.bashrc中添加export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH,执行source ~/.bashrc生效; - 验证:执行
arm-linux-gnueabihf-gcc --version,显示版本号即安装成功。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复