复习——ARM Cortex-A 裸机开发深度解析

ARM Cortex-A 裸机开发深度解析笔记

一、ARM架构:不仅是CPU,而是一个完整的生态系统

1. 系统分层与裸机开发本质

典型ARM系统软件/硬件分层结构:

复制代码
应用层(APP) → 系统调用(SYS) → 内核 → 硬件(SoC)

裸机开发的核心:

  • 去除内核层:程序直接在SoC硬件上运行

  • 需要手动管理:寄存器、栈、外设等所有硬件资源

  • 完全控制权:无操作系统开销,执行效率最高

SoC组成:

  • CPU核心:Cortex-A处理器核心

  • 外设模块:GPIO、UART、PWM、定时器等

  • 集成优势:高集成度,适合嵌入式产品量产

2. 关键处理单元对比(明确开发定位)

名称 全称 核心特性 应用场景
CPU 中央处理器 强大的通用计算能力 所有嵌入式系统的核心场景
MCU 微控制器 丰富外设、低功耗 单片机开发(Cortex-M系列)
MPU 微处理器 高性能、需外接外设 裸机/Linux开发(Cortex-A系列)
SoC 片上系统 CPU+外设集成 量产嵌入式产品
DSP 数字信号处理器 专注信号处理 音视频处理

本文重点:Cortex-A系列

  • 平衡性能和可扩展性

  • 既是裸机开发基础,也是Linux开发基石

  • 适合需要较高性能的嵌入式应用

3. RISC架构:ARM指令集的核心优势

RISC(精简指令集) vs CISC(复杂指令集)对比:

特性 RISC (ARM) CISC (x86)
指令长度 固定(ARM状态32位) 可变长度
执行效率 高,单周期执行多数指令 相对较低
内存访问 只有LDR/STR访问内存 多种内存访问方式
寄存器 丰富的通用寄存器 寄存器数量有限
功耗 低功耗设计 功耗较高

ARM RISC核心特性:

  1. 固定指令长度:ARM状态下统一为32位,解码简单高效

  2. 加载/存储架构

    • 只有LDR/STR指令可以访问内存

    • 其他指令只操作寄存器

    • 减少内存访问频率,提高效率

  3. 丰富寄存器:16个通用寄存器(r0-r15)

  4. 低功耗设计:适合移动设备和工业控制

二、ARM寄存器系统:程序执行的"基础"

1. 通用寄存器(r0-r15)

寄存器 核心作用 关键注意事项
r0-r3 函数参数传递、返回值存储 可被调用函数修改,无需保护
r4-r12 通用数据存储 调用函数必须保护(push/pop)
r13 (SP) 栈指针 指向当前栈顶,裸机中必须手动初始化
r14 (LR) 链接寄存器 存储函数返回地址,嵌套调用需保护
r15 (PC) 程序计数器 指向当前取指地址,不能手动修改

寄存器使用规则:

  • 调用者保存:r0-r3可由被调函数任意修改

  • 被调者保存:r4-r12必须由被调函数保存恢复

  • 特殊寄存器:SP、LR、PC有特殊用途

2. 状态寄存器(CPSR/SPSR)

CPSR(当前程序状态寄存器):

  • 所有模式共享,存储核心状态信息

  • 条件标志位

    • N(负标志):结果为负时置1

    • Z(零标志):结果为零时置1

    • C(进位标志):加法进位或减法借位时置1

    • V(溢出标志):有符号溢出时置1

  • 中断禁止位

    • I位:IRQ中断使能控制(1=禁止)

    • F位:FIQ中断使能控制(1=禁止)

  • 模式位:M[4:0],指定CPU当前工作模式

SPSR(保存的程序状态寄存器):

  • 仅特权模式可用

  • 异常发生时备份CPSR

  • 异常返回时恢复CPSR

三、核心汇编指令:从数据操作到流程控制

1. 数据传送与移位指令(MOV/LDR)

核心功能:数据在寄存器间、寄存器与内存间移动

复制代码
; 1. 立即数/寄存器传送(MOV)
mov r1, #0x08          ; r1 = 8(立即数传送,必须符合12位规则)
mov r3, r1             ; r3 = r1(寄存器复制)
mov r4, r1, lsl #2     ; r1左移2位(×4)存入r4(r4=32)
mov r4, r4, lsr #2     ; r4右移2位(÷4)存入r4(r4=8)
mov r4, r1, ror #4     ; r1循环右移4位

; 2. 非法立即数加载(LDR伪指令)
ldr r0, =0x1FB0        ; 0x1FB0违反12位规则,使用LDR加载大立即数

关键规则:

  • 12位立即数规则:立即数必须能被扩展为"偶数位循环右移"的形式

  • 移位范围:0-31位

  • 移位类型

    • LSL:逻辑左移,低位补0

    • LSR:逻辑右移,高位补0

    • ROR:循环右移,移出的位补到高位

2. 算术逻辑指令(ADD/SUB/CMP)

核心功能:数据运算和比较,S后缀更新CPSR标志

复制代码
; 1. 算术运算(ADD/SUB)
mov r0, #0xA0          ; r0 = 160
mov r1, #0x08          ; r1 = 8
add r5, r0, #1         ; r5 = 160 + 1 = 161(立即数运算)
add r6, r0, r1         ; r6 = 160 + 8 = 168(寄存器运算)
add r6, r0, r1, lsl #2 ; r6 = 160 + (8×4) = 192(带移位运算)
sub r3, r0, r1         ; r3 = 160 - 8 = 152
adds r3, r0, r1        ; 带S后缀,更新CPSR标志位(N/Z/C/V)

; 2. 比较指令(CMP)→ 实质是"减法但不保存结果,只更新CPSR"
mov r0, #200
mov r1, #100
cmp r0, r1             ; 相当于 subs r0, r1(不改变r0,只更新标志)
movge r3, r0           ; 如果 r0≥r1(N=V),则 r3 = r0
movlt r3, r1           ; 如果 r0<r1(N≠V),则 r3 = r1

核心规则:

  • 非法操作 :不能直接对两个立即数运算(如 add r0, #3, #2

  • 编译优化:常数运算在编译时优化

  • 条件执行:条件指令依赖CMP或带S后缀的算术指令

3. 位操作指令(BIC/ORR)

核心功能:精确控制寄存器特定位,硬件外设配置的关键

复制代码
; 1. 清除指定位(BIC:Rd = Rn & ~Operand2)
mov r0, #0xFFFFFFFF     ; r0 = 全1
bic r1, r0, #(1 << 15)  ; 清除第15位(r1 = 0xFF7FFFFF)
bic r1, r0, r2, lsl #15 ; 使用寄存器移位进行灵活清除

; 2. 设置指定位(ORR:Rd = Rn | Operand2)
orr r4, r1, #(1 << 15)  ; 设置第15位(r4 = 0xFFFFFFFF)

应用场景:

  • GPIO引脚方向配置

  • 外设寄存器位控制

  • 修改目标位而不影响其他位

四、程序流程控制:循环与分支指令

循环三要素:

  1. 终止条件:循环何时结束

  2. 迭代步长:每次循环如何变化

  3. 循环体:重复执行的代码

1. while循环(先检查,后执行)

特点:循环次数不确定时使用

复制代码
mov r0, #1              ; 循环变量 i = 1
mov r1, #0              ; 累加和 sum = 0

loop_label
cmp r0, #1000           ; 检查 i ≤ 1000?
bgt loop_finish         ; 如果 i > 1000,退出循环
add r1, r1, r0          ; sum += i(循环体)
add r0, r0, #1          ; i++(迭代步长)
b loop_label            ; 跳回循环开始

loop_finish
b loop_finish           ; 无限循环暂停(裸机程序无退出机制)

2. do-while循环(先执行,后检查)

特点:至少执行一次循环体

复制代码
mov r0, #1              ; 循环变量 i = 1
mov r1, #0              ; 累加和 sum = 0

do_loop
add r1, r1, r0          ; sum += i(先执行循环体)
add r0, r0, #1          ; i++
cmp r0, #1000           ; 检查 i ≤ 1000?
ble do_loop             ; 如果条件满足,继续循环

loop_finish
b loop_finish

3. 跳转指令对比

指令 核心功能 应用场景 关键区别
B 无条件跳转 循环、一般分支 不保存返回地址
BL 带返回地址的跳转 函数调用 自动保存返回地址到LR
BX 带状态切换的跳转 函数返回、状态切换 支持ARM/Thumb模式切换

特殊用法bx lr = 函数返回


五、函数调用与栈机制:裸机开发的核心保障

1. ARM栈模型:满递减栈(FD)

核心规则:

  • 满栈:入栈前SP指向有效数据,入栈时先减4再存数据

  • 递减栈:栈指针从高地址向低地址增长

  • 初始化ldr sp, =0x40001000(非法立即数需用LDR加载)

栈配置示例:

  • 栈基地址:0x40001000

  • 栈大小:0x1000(4KB)

  • 栈顶随着入栈逐渐减小

2. 完整函数调用流程(含嵌套调用)

(1) 基本函数定义与返回

复制代码
; 无参数无返回值函数
asm_fun0
    mov r0, #10         ; 内部逻辑:r0=10, r1=20
    mov r1, #20
    bx lr               ; 函数返回(LR存放返回地址)

(2) 嵌套函数调用(需要LR保护)

复制代码
; 函数1:返回r0和r1的最大值,嵌套调用asm_fun0
asm_twoNumMax
    cmp r0, r1          ; 比较输入参数r0和r1
    movge r3, r0        ; 将较大值存入r3
    movlt r3, r1
    
    stmfd sp!, {lr}     ; 将LR压栈(嵌套调用需要保护LR)
    bl asm_fun0         ; 调用asm_fun0(LR自动更新为PC+4)
    ldmfd sp!, {lr}     ; 恢复LR
    
    bx lr               ; 函数返回

; 主函数:初始化栈指针,调用嵌套函数
asm_main
    ldr sp, =0x40001000 ; 初始化栈指针(满递减栈)
    mov r0, #50         ; 参数1:a=50
    mov r1, #20         ; 参数2:b=20
    stmfd sp!, {r0-r12, lr} ; 保存主函数上下文
    bl asm_twoNumMax    ; 调用嵌套函数
    ldmfd sp!, {r0-r12, lr} ; 恢复主函数上下文
    
finish
    b finish            ; 无限循环暂停

3. 函数调用核心规则

规则项 具体内容
参数传递 前4个参数通过r0-r3传递,超过4个使用栈传递
返回值 通过r0返回
上下文保存 r4-r12和LR在嵌套调用中必须压栈保护
栈对齐 调用C函数时需8字节对齐,使用preserve8伪指令
函数返回 使用bx lr,嵌套函数需先恢复LR

调用约定总结:

  • 调用者责任:保存r0-r3(如果需要)

  • 被调者责任:保存r4-r12和LR(如果修改)

  • 栈平衡:函数返回前必须恢复栈指针

六、裸机开发陷阱指南(关键实践提醒)

1. 立即数合法性陷阱

问题:直接使用非法立即数

复制代码
; 错误:0x1FB0违反12位规则
mov r0, #0x1FB0        ; 编译错误!

; 正确:使用LDR伪指令
ldr r0, =0x1FB0        ; 编译器会自动处理

12位立即数规则详解

  • 立即数必须能被表示为:8位数值 × 2^(2×n),其中n=0-15

  • 即:高24位全0,低8位为有效数据

  • 编译器会将非法立即数转为LDR指令加载

2. 栈初始化陷阱

复制代码
; 错误:立即数可能非法
mov sp, #0x40001000    ; 可能编译错误

; 正确:使用LDR伪指令
ldr sp, =0x40001000    ; 安全可靠

3. 条件指令依赖陷阱

复制代码
; 错误:条件指令前无标志更新
mov r0, #100
mov r1, #50
movge r2, r0           ; 错误!CPSR标志未更新

; 正确:使用CMP或带S后缀的指令
mov r0, #100
mov r1, #50
cmp r0, r1             ; 更新CPSR标志
movge r2, r0           ; 正确!基于CMP结果

4. 函数返回约定

复制代码
; 常规函数返回
bx lr                  ; 标准返回方式

; 嵌套函数必须保护LR
nested_function
    stmfd sp!, {lr}    ; 保存LR
    ...                ; 函数体
    ldmfd sp!, {lr}    ; 恢复LR
    bx lr              ; 返回

5. 裸机程序终止

无操作系统时的处理方式:

  1. 无限循环b finish(最简单)

  2. 低功耗模式:进入WFI/WFE状态

  3. 等待中断:进入中断等待状态

七、C与汇编混合调用(实践扩展)

1. 汇编调用C函数

汇编端代码:

复制代码
; 1. 导入C函数(Keil环境)
import c_add

; 2. 栈对齐伪指令(避免编译错误)
preserve8

; 3. 调用流程
asm_call_c
    ldr sp, =0x40001000     ; 初始化栈
    stmfd sp!, {r0-r12, lr} ; 保存上下文
    mov r0, #1              ; C参数1:a=1
    mov r1, #2              ; C参数2:b=2
    bl c_add                ; 调用C函数
    ldmfd sp!, {r0-r12, lr} ; 恢复上下文
    bx lr

C端函数:

复制代码
// C函数定义
int c_add(int a, int b) {
    return a + b;
}

2. C调用汇编函数

汇编端代码:

复制代码
; 导出汇编函数
export asm_fun1

asm_fun1
    add r0, r0, r1         ; 实现a+b,结果存r0
    bx lr                   ; 返回

C端代码:

复制代码
// 声明汇编函数
extern int asm_fun1(int a, int b);

// 调用汇编函数
int main(void) {
    int res = asm_fun1(10, 20);  // res = 30
    while(1);                     // 无限循环
    return 0;
}

3. 混合调用关键规则

规则项 汇编调用C C调用汇编
参数传递 r0-r3传递前4个参数 r0-r3接收前4个参数
返回值 r0接收返回值 r0返回结果
栈对齐 需要8字节对齐 编译器自动处理
寄存器保护 保护r4-r12和LR 保护必要寄存器
函数声明 使用import伪指令 使用export伪指令

八、总结:裸机开发核心要点

1. 架构层面

  • 理解RISC优势:固定指令、加载/存储架构、丰富寄存器

  • 明确SoC组成:CPU核心 + 外设模块的集成系统

  • 定位开发层次:去除OS层,直接控制硬件

2. 指令层面

  • 掌握核心指令:MOV/LDR、ADD/SUB/CMP、BIC/ORR

  • 理解条件执行:基于CPSR标志的条件分支

  • 熟练位操作:硬件寄存器配置的关键

3. 流程控制层面

  • 实现循环结构:while、do-while循环

  • 掌握函数调用:参数传递、返回值、上下文保护

  • 理解栈机制:满递减栈的工作方式

4. 实践层面

  • 避免常见陷阱:立即数、栈初始化、条件依赖

  • 实现混合编程:C与汇编相互调用

  • 设计程序结构:裸机环境下的程序组织

5. 核心思维转变

应用开发系统开发的思维转变:

  • 直接控制硬件:无操作系统抽象层

  • 手动资源管理:寄存器、栈、内存全手动管理

  • 极致性能优化:无OS开销,执行效率最高

  • 完全系统控制:对整个硬件系统有完全控制权

裸机开发的真正价值

  1. 深入理解硬件:从底层理解计算机工作原理

  2. 系统级调试能力:能够调试最底层的硬件问题

  3. 性能极致优化:无OS开销,发挥硬件最大性能

  4. 特殊应用支持:实时性要求极高或资源极度受限的场景

相关推荐
JavaLearnerZGQ2 小时前
我的Redis笔记2【分布式缓存】
redis·笔记·缓存
吗喽1543451882 小时前
渗透高级第一次作业(笔记整理)
笔记·安全·网络安全
清风6666662 小时前
基于单片机的燃气热水器智能控制系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
小+不通文墨2 小时前
“示波器的调节和使用”实验报告
经验分享·笔记·学习·学习方法
鸢尾掠地平2 小时前
如何制作一个简单的学习教务系统?
css·学习·css3
2501_937798392 小时前
2026年GEO行业趋势与企业服务选型指南
笔记
Jerry_Gao9212 小时前
【成长笔记】【web安全】深入Web安全与PHP底层:四天实战课程笔记
笔记·安全·web安全·php·漏洞
努力搬砖的咸鱼3 小时前
Kubernetes 核心对象详解:Pod、Deployment、Service
微服务·云原生·容器·架构·kubernetes
套码汉子3 小时前
从 “重复造轮子” 到 “搭积木式开发”:活动系统架构如何支撑业务高效迭代
架构·系统架构·游戏开发·组件化