前言
本章节从 ARM 汇编基础、汇编 C 混合编程机制,过渡到 i.MX6ULL Cortex-A7 裸机环境搭建,最后完成裸机点灯完整工程。内容覆盖寄存器、指令集、异常向量表、启动代码、GPIO 硬件配置、交叉编译、烧录调试,是嵌入式 ARM 裸机入门核心内容。
整体学习链路:ARM 汇编基础 → 汇编 C 混合编程规范 → 启动代码与异常向量 → i.MX6ULL 硬件架构 → 裸机点灯实验(汇编实现 + 编译烧录)
一、ARM 汇编与 C 混合编程核心机制
1. CPSR (程序状态寄存器) 标志位
- N(Negative):运算结果为负数,置 1
- Z(Zero):运算结果等于 0,置 1
- C(Carry):加法进位、减法无借位、移位移出位,置 1
- V(Overflow):有符号数运算溢出,置 1
2. ARM 指令与栈机制
- 跳转指令
- B:普通跳转,不保存返回地址
- BL:带链接跳转,把 PC 保存到 LR (链接寄存器),用于函数调用
- BX:跳转,常用于BX LR实现函数返回,还可切换 ARM/Thumb 指令集
- ARM 默认栈:满减栈 Full Descending,栈顶指向有效数据,地址从高向低增长
- 立即数:12 位编码(8 位有效值 + 4 位旋转),不是所有 32 位数字都可以直接作为立即数。大数需要 LDR 伪指令加载。
3. 汇编与 C 混合编程调用规范
4. 汇编启动代码作用
C 语言不能直接操作 MMU、Cache 这类内核寄存器,必须汇编做底层初始化:
- 设置 SP 栈指针
- 搭建异常向量表
- 切换 CPU 工作模式(SVC→User)
- 初始化硬件环境,为 C 语言 main 函数运行做准备
二、ARM 指令、异常向量表与启动初始化流程
1. LDR / STR 数据访问指令
- LDR(Load):内存→寄存器,C 语言*p取值
- STR(Store):寄存器→内存,C 语言*p = val赋值
- 支持偏移寻址、后索引、前索引回写寻址模式
2. MRS / MSR 状态寄存器操作
CPSR 不是通用寄存器,普通指令不能读写
- MRS:CPSR → 通用寄存器(读状态寄存器)
- MSR:通用寄存器 → CPSR(写状态寄存器,修改模式位、标志位)
⚠️ 注意:写 CPSR 需要指定域后缀,操作风险高,谨慎使用
3. 异常向量表
固定放在0x00 ~ 0x1C地址,8 个入口:
复位 Reset、未定义指令 Undef、软中断 SWI/SVC、预取终止 Pabort、数据终止 Dabort、保留、IRQ、FIQ
- 严重异常(Undef/Pabort)一般直接死循环
- SWI 软中断,自定义处理逻辑,执行完成需要返回
4. 启动代码初始化流程
5. SWI/SVC 软中断
汇编中封装函数,使用 SWI 触发软中断,进入异常处理。
三、i.MX6ULL 裸机环境搭建 & start.S 启动代码
平台迁移:QEMU S3C2440 (ARMv5 ARM920T) → 真实硬件 i.MX6ULL Cortex-A7 (ARMv7-A)
1. 开发环境
- 编辑器:Ubuntu + VS Code,ARM Assembly 插件开启汇编语法高亮
- 汇编文件后缀推荐大写.S:编译前会做预处理,支持宏定义
- 编译工具:arm-linux-gnueabihf-gcc 交叉工具链
2. start.S 启动代码核心
- 先关闭 IRQ/FIQ 中断,避免栈未初始化时中断触发崩溃
- 给 SVC、IRQ、System 模式分别分配独立栈空间
- System 模式用于运行 C 主业务代码,必须分配栈
3. ARMv7 新增简化指令
- CPS指令:替代 MRS+MSR 组合,快速切换 CPU 模式、修改中断位
- CPS #0x12:切换 IRQ 模式
- CPSIE I:使能 IRQ 中断
- CPSID I:关闭 IRQ 中断
- LDR伪指令:加载 32 位大地址 / 大数,弥补 MOV 不能加载大立即数的局限
- BX LR:函数返回,自动识别地址最低位切换 ARM/Thumb
4. i.MX6ULL 内存与栈规划
- DDR3:512MB,起始地址0x80000000
- 栈类型:满减栈(高地址向低地址)
- 分配策略:每个模式分配独立栈,参考 Linux,可分配 32MB 保证安全
5. 业务框架(点灯工程)
模块化封装 LED 相关函数:led_init、led_on、led_off、delay
System 模式下死循环:开灯→延时→关灯→延时,循环闪烁。
四、i.MX6ULL 硬件架构、原理图与 GPIO 配置
1. 硬件层级(面试高频考点,别混淆)
开发板(正点原子 i.MX6U Mini)> SoC(NXP i.MX6ULL)> 内核 Cortex-A7
面试坑点:区分 SoC 型号、内核名称、指令集版本,不要混为一谈。
2. 开发板硬件与启动
- 供电 DC 6~16V,Type-C,网口;拨码开关选择启动方式
- SD 卡启动:拨码设置为10000010
- 核心板:SoC、DDR、ROM、高速总线;底板:外设接口;核心板 PCB 设计难度更高
3. LED 硬件电路
LED0 引脚网络标签:GPIO1_IO03
串联限流电阻,3.3V 稳压供电。
4. IOMUXC IO 复用控制器
引脚资源有限,IOMUXC 本质多路选择开关,实现引脚复用。
配置两步:
5. GPIO 寄存器
- GPIOx_GDIR:方向寄存器,置 1 = 输出模式
- GPIOx_DR:数据寄存器,写 0 输出低电平(点亮 LED),写 1 输出高电平(熄灭 LED)
五、裸机点灯完整工程:交叉编译、链接、烧录调试
1. LED 初始化完整步骤
2. 交叉编译工具链
工具链组件:预处理器、gcc 编译器、as 汇编器、ld 链接器、objcopy、objdump
安装配置:解压工具链,修改~/.bashrc,添加 bin 目录到 PATH 环境变量,终端全局调用命令。
3. 编译 & 链接流程
4. 烧录与调试
- imxdownload 工具,将 bin 写入 SD 卡;⚠️注意设备节点如/dev/sdb,千万不要误写入系统硬盘
- objdump 反汇编 ELF,查看汇编代码,调试程序执行流程
- 编写 Makefile,自动化编译、清理工程,提升开发效率
网硕互联帮助中心






评论前必须登录!
注册