云计算百科
云计算领域专业知识百科平台

# ARM 裸机开发|ARM 汇编 + C 混合编程 + i.MX6ULL 点灯实验

前言

本章节从 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 个参数用 R0~R3,多于 4 个,剩余参数压栈传递
  • 返回值:统一通过R0返回
  • 导入导出:汇编调用 C 函数用IMPORT;C 调用汇编函数,汇编代码中用EXPORT导出函数名
  • 栈对齐:PRESERVE8伪操作,保证 8 字节栈对齐,保证 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. 启动代码初始化流程

  • 复位默认 SVC 模式,先初始化 SVC 栈 SP
  • MRS/MSR 修改 CPSR 的 M 域,切换 CPU 模式(SVC→User)
  • 切换模式后,单独分配 User 模式栈,不同模式栈空间相互独立,防止冲突
  • 初始化全部完成,跳转 C 语言 main 函数
  • 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 主业务代码,必须分配栈
  • 初始化结束后,打开 IRQ 总开关
  • 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 本质多路选择开关,实现引脚复用。
    配置两步:

  • IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03:设置 ALT5,把引脚复用为 GPIO 功能
  • IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03:配置上下拉、驱动能力、压摆率,实验可使用默认值
  • 5. GPIO 寄存器

    • GPIOx_GDIR:方向寄存器,置 1 = 输出模式
    • GPIOx_DR:数据寄存器,写 0 输出低电平(点亮 LED),写 1 输出高电平(熄灭 LED)

    五、裸机点灯完整工程:交叉编译、链接、烧录调试

    1. LED 初始化完整步骤

  • IOMUX 配置,引脚复用为 GPIO
  • 配置 PAD 电气属性(驱动、上下拉)
  • GDIR 寄存器设为输出
  • DR 寄存器输出高低电平控制 LED 亮灭
  • 2. 交叉编译工具链

    工具链组件:预处理器、gcc 编译器、as 汇编器、ld 链接器、objcopy、objdump
    安装配置:解压工具链,修改~/.bashrc,添加 bin 目录到 PATH 环境变量,终端全局调用命令。

    3. 编译 & 链接流程

  • arm-linux-gnueabihf-gcc -c xxx.S -o xxx.o:编译生成目标文件,只汇编不链接
  • ld 链接,-Ttext指定代码加载地址,例0x87800000,避开栈区域
  • objcopy:ELF 文件 → .bin 二进制镜像,去掉符号、调试信息,用于烧录开发板
  • 4. 烧录与调试

    • imxdownload 工具,将 bin 写入 SD 卡;⚠️注意设备节点如/dev/sdb,千万不要误写入系统硬盘
    • objdump 反汇编 ELF,查看汇编代码,调试程序执行流程
    • 编写 Makefile,自动化编译、清理工程,提升开发效率

    🔥 本章易错点 & 面试速记清单

  • ARM 栈:满减栈 FD,栈顶指向有效数据,地址从高→低
  • CPSR 四个标志:N 负、Z 零、C 进位、V 有符号溢出
  • 函数传参:R0~R3 存前 4 参数,R0 返回结果
  • BL 保存 LR,BX LR 实现返回;B 不会保存返回地址
  • i.MX6ULL DDR 起始地址:0x80000000
  • IOMUXC 负责引脚复用;GDIR 设置 GPIO 方向;DR 输出电平
  • 大写.S 汇编文件:支持预处理;小写.s 不做预处理
  • 启动顺序:汇编初始化硬件、栈、异常向量 → 跳转 C 语言 main
  • 交叉编译流程:.S → .o → ELF → .bin
  • SD 卡烧录务必核对设备节点,防止破坏电脑磁盘
  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » # ARM 裸机开发|ARM 汇编 + C 混合编程 + i.MX6ULL 点灯实验
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!