一、ARM 微处理器概览

1.1 ARM 公司与 Cortex 系列

  • ARM 公司
    • 成立于1990年11月,原名 Advanced RISC (精简指令集)Machines。
      • 与复杂指令集(CISC)不同,RISC的每条指令长度相同且指令格式简单,而CISC使用变长指令且指令功能复杂。RISC的简化设计使处理器能以更高的时钟频率运行,实现更高的指令吞吐量。
    • 主要设计 RISC 处理器核心,也提供IP核、软件工具、模型和单元库等。
    • ARM 公司不制造芯片,而是授权其设计给合作伙伴
    • 截至2020年,合作伙伴已出货超过1800亿颗基于ARM的芯片。
  • Cortex 系列命名与分类
    • 2004年后,ARM 处理器采用 Cortex 命名。
    • Cortex-A 系列:用于高性能开放应用平台
    • Cortex-R 系列:用于实时控制系统
    • Cortex-M 系列:用于传统微控制器系统
      • 2020年第三季度出货67亿颗基于ARM的芯片,其中44亿为 Cortex-M 处理器。
  • ARM 架构版本演进
    • 主要版本包括 v4, v4T, v5, v5E, v6, v7, 直至最新的 v9。
    • notion image
    • Thumb 指令集在 v4T 问世。
    • Thumb-2 指令集在 v6 架构开始支持时问世。
    • v5E 架构加入了增强型 DSP 指令。
    • v6 架构开始支持 SIMD (单指令多数据流)。

1.2 Cortex-M3/M4 处理器特性

数据宽度与寻址 :❗

  • 32位 RISC 处理器。
  • 32位寄存器、32位内部数据路径、32位总线接口。
  • 32位寻址,地址空间高达 4GB
    • ARM的地址是32位的
    • 每个唯一的32位地址对应内存中一个8位(1字节)的数据存储位置
  • 支持处理字节 (8位/byte)、半字 (16位/2 bytes)、字 (32位/4 bytes) 和双字 (64位/8 bytes)

指令集 - Thumb-2 技术

  • 传统 ARM 指令集包含32位 ARM 指令和16位 Thumb 指令,两者需切换模式
  • Cortex-M 采用 Thumb-2 指令集技术,同时支持16位和32位指令,无需切换状态
  • Thumb-2 兼顾了 ARM 指令的性能Thumb 指令的优秀代码密度
    • 代码尺寸比 ARM 指令小约26%。
    • 性能比 Thumb 指令快约25%。
notion image
notion image

三级流水线

  • 取指 (Fetch)
    • 考点:PC会指向下一个取指的地址(当前地址+4)
    • 51中PC指向下一个执行的指令,因为流水线的缘故这里的PC手伸得更长
  • 译码 (Decode)
  • 执行 (Execute)
可一次读取两条16位指令。(因为系统是32位的)
某些指令执行多个周期时,流水线会暂停。
跳转到分支后流水线清空。
notion image
notion image
  • Flash 访问速度限制 :Flash 读取速度较慢 (典型20-50ns)。
    • 解决策略增加 Flash 读取数据宽度 (如128位) 和指令预取
    • STM32F4 的 Flash 访问加速器 (ART Accelerator) 包含指令预取和缓存机制。
      • 也就是在空闲的时候将Flash中的指令读取好放到某一个高速缓冲区域内
      思路:一遍执行一遍读,读好了先存起来
      思路:一遍执行一遍读,读好了先存起来
      notion image

字节顺序 (Endianness)

字节在内存中的存储顺序
  • ARM中内存仍然byte(8bits)为基本单位储存
  • 一个字有4个字节,也就有4个地址;👉这就带来了问题
  • 小端模式 (Little-endian)字的最低有效字节存储在最低地址。Cortex-M 一般采用小端模式。
notion image
  • 大端模式 (Big-endian):字的最低有效字节存储在最高地址。
notion image
Cortex-M4 理论上支持两种模式,但通常采用小端模式。

数据对齐

  • 内存系统为32位 (4字节),地址按字节定义
  • 对齐传输:字访问地址应为4的倍数,半字访问地址应为2的倍数。
    • notion image
  • 非对齐传输:对字和半字的地址无此限制。Cortex-M3/M4 支持非对齐数据访问,但可能会牺牲性能,因为硬件会将其转换为多次对齐访问。
    • notion image
    • 多加载/存储指令 (LDM/STM) 和栈操作不支持非对齐传输。
    • 尽量避免非对齐传输

存储器保护单元 (MPU)

  • 一种硬件机制,通过定义内存区域的访问权限和属性来增强系统安全性和可靠性。
  • 作用:防止任务访问未授权内存避免非法操作导致系统崩溃辅助调试
  • STM32 M3 存储器访问缺省设置对不同区域有不同用户级许可权限

二、ARM Cortex-M 处理器架构

2.1 寄存器组❗❗

notion image

通用寄存器 (R0-R12)

  • R0-R7 (低组寄存器):一些16位Thumb指令只能访问这些寄存器。
  • R8-R12 (高组寄存器):可用于32位和16位指令。

栈指针 (R13, SP)

  • 用于 PUSH 和 POP 操作
  • 物理上存在两个栈指针:
    • 主栈指针 (MSP):复位后默认使用,通常在处理模式和特权级线程模式下使用。
    • 进程栈指针 (PSP):通常在用户级线程模式下使用,特别是在 RTOS 环境中。
    • 处理器模式
      CONTROL[1] (SPSEL)
      当前活动的堆栈指针
      场景说明
      处理模式 (Handler Mode)
      任意值
      MSP
      任何中断、异常服务程序都在此模式下运行
      线程模式 (Thread Mode)
      0 (默认)
      MSP
      运行简单的裸机程序,或RTOS内核本身
      线程模式 (Thread Mode)
      1
      PSP
      运行在RTOS(实时操作系统)下的用户任务

链接寄存器 (R14, LR)

  • Link Register
  • 存储函数或子程序调用时的返回地址。
  • 执行了函数或者子程序调用的时候,LR的数值会自动更新
NOTE THAT:
中断中LR的行为较为特殊,具体参见异常和中断部分笔记

程序计数器 (R15, PC)

  • 可读可写
  • 读操作返回当前指令地址+4(由于流水线)
  • 写 PC 会引起跳转。

特殊寄存器

  • 不能直接通过内存地址访问,需使用 MRS (读) 和 MSR (写) 指令。

程序状态寄存器 (xPSR)

notion image
物理上,这是一个32位的寄存器。 逻辑上,这个寄存器又可以分为以下三个部分。我们可以像访问独立的寄存器一样单独访问他们。
  • 应用PSR (APSR):包含算术逻辑单元 (ALU) 的状态标志 (N, Z, C, V, Q, GE[3:0])。
  • 中断PSR (IPSR):包含当前中断服务例程 (ISR) 的异常编号。
  • 执行PSR (EPSR):包含 ICI/IT (中断继续指令/IF-THEN 指令状态) 和 T (Thumb状态) 位。T位恒为1,清除会导致错误。
notion image

中断屏蔽寄存器

  • PRIMASK: 置1后关闭所有可屏蔽异常,仅NMI和HardFault可响应。
  • FAULTMASK: 置1后关闭所有可屏蔽异常和HardFault,仅NMI可响应。
  • BASEPRI: 定义被屏蔽优先级的阈值,高于此值(数值上,优先级越低)的中断被关闭。0表示不关闭任何中断。
  • 这些寄存器只能在特权等级下操作。
notion image

控制寄存器 (CONTROL)

  • nPRIV (位[0]): 定义线程模式的特权等级 (0=特权级, 1=用户级)。
  • SPSEL (位[1]): 选择线程模式下的栈指针 (0=MSP, 1=PSP)。处理模式下固定使用MSP。
  • FPCA (位[2]): (仅M4F) 浮点上下文活动标志,指示异常发生时是否需要保存浮点寄存器。
notion image

Cortex-M4F 浮点寄存器 (FPU) : (若处理器包含浮点单元)

  • 32个单精度寄存器 (S0-S31)。
    • 可作为16个双精度寄存器 (D0-D15)。
  • 浮点状态和控制寄存器 (FPSCR)

2.2 工作模式与特权等级

两种工作模式

  • 线程模式 (Thread Mode):执行普通应用程序。可处于特权或非特权访问等级,由 CONTROL 寄存器控制
  • 处理模式 (Handler Mode):执行异常/中断服务例程。处理器总是处于特权访问等级
notion image

特权等级

  • 特权级:可以访问所有资源,执行所有指令。
  • 非特权级 (用户级):访问受限,不能执行某些指令(如修改 CONTROL 寄存器切换到特权级)。
  • 这种机制为嵌入式操作系统 (OS) 提供了基本的安全模型。
notion image

2.3 存储器映像

🌻
总共 4GB 的地址空间,被划分为不同的区域。

片上系统(前1.5GB)

  • 代码区 (Code),0.5GB:通常从 0x00000000 开始,主要存放程序代码。
  • SRAM 区,0.5GB:通常从 0x20000000 开始,主要存放数据,但也可以执行代码。
  • 外设区 (Peripheral),0.5GB:通常从 0x40000000 开始,用于访问片上外设。
notion image

外部拓展(后2GB)

  • RAM区 (1GB): 这个地址空间是预留给你外接 RAM 芯片使用的。如果你的应用需要比片内SRAM更大的内存,就可以通过FSMC(灵活的静态存储控制器)等接口外扩RAM,并将其映射到这个地址范围。
  • 设备区 (1GB): 这个地址空间同样是预留给你外接其他设备使用的,比如外接更大容量的Nor-Flash,或者其他需要内存映射的专用芯片。

系统/供应商定义区(0.5GB)

2.4 堆栈

Cortex-M4 堆栈概述

  • 采用“向下生长的堆栈”模型:SP 指向最后一个压入堆栈的32位数值。
    • PUSH 操作:SP 先自减4,再存入新数值。
      POP 操作:先读出 SP 指向的数据,SP 再自增4。
  • 堆栈指针 (R13) 分为主栈指针 (MSP) 和进程栈指针 (PSP)。
  • 操作为32位,对齐到4字节边界,SP 最低两位恒为0。

堆栈应用

  • 函数调用时保存寄存器和返回地址 (LR)。
  • PUSH {reg_list, LR}POP {reg_list, PC} 是常用的函数进入和返回方式。
notion image
notion image

三、Cortex-M 指令集 (Thumb-2)

3.1 指令集特点与格式

语言格式

  • 32位或16位的 RISC 指令集。
  • 指令格式:标号 操作码 操作数1, 操作数2, ... ;注释
    • 标号可选,顶格写。
    • 操作码前至少一个空白符。
    • 第一个操作数通常是结果存储处。
  • 立即数以 # 开头。
  • 注释以 ; 开头。
  • 可使用 EQU 定义常数。

指令后缀 ❗

  • S❗: 要求更新 APSR 中的状态标志 (N, Z, C, V, S)。
位号
标志位
功能描述
31
N
负数标志 (Negative): ALU 运算结果为负数,即结果的最高位 (bit[31]) 为 1 时,N 位置 1 。
30
Z
零结果标志 (Zero): ALU 运算结果为 0 时,Z 位置 1 。
29
C
进位/借位标志 (Carry):无符号数运算溢出标志:如果无符号数运算产生进位(加法)或借位(减法),C 位置 1 。 对于加法指令,如果产生了超出 32 位范围的进位,C 位置 1。 对于减法指令,如果没有发生借位(即结果为正或零),C 位置 1。
28
V
溢出标志 (oVerflow): 有符号数运算溢出标志:如果算术运算结果超出了有符号数的表示范围(例如两个正数相加得到负数,或两个负数相加得到正数),V 位置 1 。
27
S
饱和标志 (Saturation):仅在 Cortex-M4F 中可用,表示饱和运算是否发生饱和。它不做条件转移的依据 。
  • 条件后缀❗ (如 EQ, NE, LT, GT 等):用于条件执行,主要用于转移指令 (B)。
    • 条件码基于 APSR 中的 N, Z, C, V 标志。
    • 后缀
      含义 (英文)
      含义 (中文)
      标志位条件
      解释
      EQ
      Equal
      等于
      Z = 1
      如果结果为零(通常表示比较的两个数相等)
      NE
      Not Equal
      不等于
      Z = 0
      如果结果不为零(通常表示比较的两个数不相等)
      GE
      Greater than or Equal
      有符号大于等于
      N = V
      如果有符号数A >= B (即N位和V位相同)
      GT
      Greater Than
      有符号大于
      Z=0 和 (N = V)
      如果有符号数A > B
      LT
      Less Than
      有符号小于
      N != V
      如果有符号数A < B (即N位和V位不同)

统一汇编语言 (UAL)

  • 规范了汇编语言格式,解决传统 Thumb 到 Thumb-2 的兼容问题。
  • 允许汇编器自动选择16位或32位指令,或手动指定 (.N 为窄指令/16位,.W 为宽指令/32位)。
  • 16位和32位指令的立即数范围不同。

3.2 主要指令类型与示例

处理器内部数据传送指令

🌻
MOV是寄存器之间传送数据的指令
  • MOV Rd, Rn: Rd = Rn❗
  • MOV Rd, #imm: Rd = imm❗
  • MOVS: 带S后缀,更新标志位。❗
  • MOVW Rd, #imm16: 将16位立即数存入Rd低16位,高16位清零。❗
  • MOVT Rd, #imm16: 将16位立即数存入Rd高16位,低16位不变。❗
  • MVN Rd, Rn: Rd = ~Rn (按位取反)❗

存储器访问指令 :❗

🌻
所有对寄存器操作都是用指针
基础指令:LDR (Load,读存储器),STR (Store,写存储器)。

数据大小后缀

  • B (Byte, 8位无符号),SB (Signed Byte, 8位有符号)
  • H (Halfword, 16位无符号),SH (Signed Halfword, 16位有符号)
  • 无后缀 (Word, 32位)
  • D (Doubleword, 64位)
  • M(多个32位)
notion image

寻址模式

这么设计的部分原因是为了和C语言方便的转化
  • 立即数偏移 (前序): LDR Rd, [Rn, #offset]
    • ! 后缀:指令执行后更新基址寄存器 Rn (Rn = Rn + offset)。
      • 以一个寄存器作为存储器的基准地址(指针),与一个立即数相加,和作为访问的存储器的地址。称为“前序”寻址
        notion image
  • 寄存器偏移 (前序): LDR Rd, [Rn, Rm, {LSL, #n}]
    • 以一个寄存器作为存储器的基准地址(指针),与一个从索引寄存器值相加,和作为访问的存储器的地址。从索引寄存器的值在相加前,可以左移0-3位。
      notion image
  • 后序 (Post-indexed): LDR Rd, [Rn], #offset
在存储器访问期间不使用偏移值,仅在数据结束后更新地址寄存器(指针)。指令无需使用感叹号
notion image
  • PC相对寻址: LDR Rd, [PC, #offset]
例1:

多重加载/存储指令

  • LDMIA Rd!, {reg_list}: 从 Rd 指向的地址开始,连续加载多个字到寄存器列表,Rd 每次递增 (Increase After)。
  • STMIA Rd!, {reg_list}: 连续存储多个寄存器到 Rd 指向的地址,Rd 每次递增。
  • LDMDB Rd!, {reg_list}: ... Rd 每次递减 (Decrease Before)。
  • STMDB Rd!, {reg_list}: ... Rd 每次递减。
    • STMDB SP!, {reg_list} 等效于 PUSH。
  • LDMIA SP!, {reg_list} 等效于 POP。

加载32位立即数/地址到寄存器的方法

  1. MOVW + MOVT
  1. ADR Rd, label: PC相对寻址,将标号地址加载到 Rd。偏移量有限制。
  1. LDR Rd, =value_or_label (伪指令):编译器自动选择合适方式加载,可能转换为 PC 相对加载或 MOVW+MOVT。
例2:对32位内存地址赋值
最好的方法似乎是伪指令
notion image
notion image

算术运算指令

  • ADD Rd, Rn, Rm: Rd = Rn + Rm
    • notion image
  • ADC Rd, Rn, Rm: Rd = Rn + Rm + Carry (带进位加法)
    • notion image
  • SUB Rd, Rn, Rm: Rd = Rn - Rm
  • SBC Rd, Rn, Rm: Rd = Rn - Rm - Carry (带借位减法)
  • RSB Rd, Rn, #imm: Rd = imm - Rn (反向减法)
  • MUL Rd, Rn, Rm: Rd = Rn * Rm (乘法)
  • MLA Rd, Rn, Rm, Ra: Rd = (Rn * Rm) + Ra (乘加)
  • MLS Rd, Rn, Rm, Ra: Rd = Ra - (Rn * Rm) (乘减)
  • UDIV Rd, Rn, Rm: 无符号除法,Rd = Rn /Rm
  • SDIV Rd, Rn, Rm: 有符号除法
  • 饱和运算指令 (如 SSAT, QADD):将结果限制在特定范围内。
notion image

逻辑运算指令

  • AND Rd, Rn, Rm: Rd = Rn & Rm
  • ORR Rd, Rn, Rm: Rd = Rn | Rm
  • EOR Rd, Rn, Rm: Rd = Rn ^ Rm (异或)
  • BIC Rd, Rn, Rm: Rd = Rn & (~Rm) (位清除)

移位和循环移位指令

  • LSL Rd, Rn, #countLSL Rd, Rn, Rm: 逻辑左移
    • LSR: 逻辑右移
      • ASR: 算术右移 (保留符号位)
        • ROR: 循环右移

          位处理指令 (略)

          数据转换指令 (如大小端转换) (略)

          比较和测试指令 : (不保存结果,只更新APSR标志)

          • CMP Rn, Rm: Rn - Rm
          • CMN Rn, Rm: Rn - (-Rm) (即 Rn + Rm)
          • TST Rn, Rm: Rn & Rm
          • TEQ Rn, Rm: Rn ^ Rm

          程序流控制指令

          跳转 (Branch):❗

          • B label❗: 无条件跳转到标号,范围±2KB
          • BX Rm❗: 跳转到 Rm 中的地址 (Rm最低位决定目标状态,Cortex-M中应为1,保持Thumb状态)。

          函数调用 (Branch with Link)

          • BL label: 跳转到标号,并将返回地址 (PC+4) 保存到 LR。
          • BLX Rm: 跳转到 Rm 中的地址,保存返回地址到 LR。
          B和BL系列指令的区别是:是否保留返回地址。

          条件跳转❗: B<cond> label

          • 比较和跳转:
            • CBZ Rn, label: 如果 Rn 为零则跳转。
            • CBNZ Rn, label: 如果 Rn 非零则跳转。
          • 条件执行 (IF-THEN 指令)
            • IT{<cond>}: If-Then. 下一条指令条件执行。
            • ITT{<cond>}: If-Then-Then.
            • ITE{<cond>}: If-Then-Else.
            • 最多支持4条条件指令 (e.g., ITTEE).
            • IT 指令最大的优势在于效率。传统的 if-else 通常用跳转指令实现(如 BEQ, BNE)。跳转指令会打乱CPU的指令流水线。
              示例:比较 R0 和 R1,如果相等则将 R2 设为1,否则将 R2 设为0。
              等价的C语言代码:
              注意:IT指令后的最多4条指令必须使用相应的条件后缀(如EQ、NE等),且必须符合IT指令指定的条件序列。

          C语言与汇编的对应

          • 函数参数通常通过 R0-R3 传递。
          • 函数返回值通常通过 R0 传递。
          • 局部变量优先使用寄存器,若寄存器不足则使用堆栈。
          notion image

          四、异常和中断

          4.1 异常概述

          • 异常 (Exception)改变程序正常执行流程的事件。处理器暂停当前任务,执行异常处理程序(异常服务例程, ESR),完成后返回原任务。
          💡
          异常不仅包括中断,也包括错误❌(例如往程序存储区写了数据)
          • 中断 (Interrupt):异常的一种,通常由外设、外部输入或软件触发。中断处理程序也称为中断服务例程 (ISR)。

          异常类型与优先级

          异常可以分为:
          1. 系统异常和外设异常
          1. 优先级可编程异常与优先级不可编程异常
          其中,优先级不可编程的都是系统异常,优先级最高(为负数);其余的可编程异常优先级为正数,分为抢占和响应优先级
          • 复位 (Reset):优先级 -3 (最高)。
          • NMI (Non-Maskable Interrupt):优先级 -2。来自外部 NMI 输入脚。
          • HardFault (硬件错误):优先级 -1。所有未被更具体错误类型捕获的错误。
          • MemManage Fault (存储器管理错误):可编程优先级。访问 MPU 定义的非法内存区域。
          • BusFault (总线错误):可编程优先级。指令预取或数据访问时的总线错误。
          • UsageFault (使用错误):可编程优先级。无效指令、非法状态转换等。
          • SVCall (系统服务调用):可编程优先级。执行 SVC 指令引发。
          • Debug Monitor (调试监控):可编程优先级。
          • PendSV (可挂起系统服务):可编程优先级。用于 RTOS 上下文切换。
          • SysTick (系统节拍定时器):可编程优先级。周期性时基定时器。
          • IRQ (外部中断):编号 0 至 239,可编程优先级。
          一共有256种中断
          一共有256种中断

          4.2 异常响应过程

          1. 入栈 (Stacking):硬件自动将8个寄存器的值压入当前活动堆栈 (MSP 或 PSP):
              • xPSR, PC, LR,(R14), R12, R3, R2, R1, R0
              NOTE THAT:
              主程序被中断的地址随PC一起压入堆栈
              notion image
          1. 取向量 (Vector Fetch):从向量表中读取对应异常服务例程的入口地址。
          1. 更新寄存器
              • SP (栈指针) 更新为当前活动栈 (MSP 或 PSP) 的新栈顶。
              • LR (链接寄存器) 更新为特殊的 EXC_RETURN 值 ( 如0xFFFFFFF9),用于异常返回时指示返回模式和栈
                • 这样做是为了区分普通的函数调用和异常
              • PC (程序计数器) 更新为服务例程的入口地址。
              • IPSR 更新为当前异常编号。

          4.3 异常返回

          • 当异常服务例程执行完毕,通过将 EXC_RETURN 值写入 PC 来触发异常返回序列
          • 常用的返回指令:BX LRPOP {..., PC} (如果LR已入栈)。
            • notion image
          • 硬件自动出栈之前保存的寄存器,恢复处理器状态,程序从被中断处继续执行。
          • HardFault 调试 :当进入 HardFault 时,可以通过查看当前 SP 指向的栈帧内容,特别是偏移 0x18 处 (即栈中保存的 PC 值),来定位导致错误的代码位置。

          4.4 嵌套向量中断控制器 (NVIC)

          • 负责异常和中断的配置、优先级管理、中断屏蔽
          • 位于存储器映像的系统控制空间 (SCS)。
          • 支持中断嵌套(抢占式):高优先级中断可以打断正在执行的低优先级中断服务例程。
          • 向量化的异常/中断入口。

          4.5 向量表

          当Cortex内核响应了一个发生的异常后,对应的异常服务程序(ESP)会开始执行。Cortex使用了向量表查表机制决定对应的ESP的入口地址
          • 该向量表实际上是一个32位整数数组,每个元素都是一个32位数,对应异常服务例程的入口地址。这个地址是可以手动编程设计的(类似51中我们LJMP去到的真正的中断服务程序地址)
          • 向量表的位置可以通过 NVIC 的向量表偏移寄存器 (VTOR) 进行重定位。
          • 复位后,VTOR 为0,因此在地址 0x00000000 处必须有一张有效的向量表。
          • 向量表结构
            • 0x00: 初始 MSP 值。
            • 0x04: 复位向量。
            • 0x08: NMI 向量。
            • 0x0C: HardFault 向量。
            • ...以此类推,每个向量占用4字节(32bits)。
            • 异常服务例程的地址最低位必须为1,以指示 Thumb 状态。
            • notion image

          4.6 复位流程

          Step1 处理器复位 (Reset)

          这可以是上电复位、手动按下复位按钮,或者由看门狗定时器等内部信号触发的系统复位。一旦复位信号有效,处理器会停止当前所有操作,进入复位状态。

          Step2 读取初始MSP值 (Fetch Initial MSP Value)

          复位后,处理器做的第一件事就是访问地址 0x00000000。它从这个地址读取一个32位的数据,并把这个数据加载到主堆栈指针寄存器 (MSP) 中。
          • 为什么? 这一步至关重要,它确保了在执行任何代码之前,系统堆栈就已经被正确初始化。这样,即将执行的启动代码(以及后续可能发生的任何中断)就立刻拥有了一个可用的、有效的堆栈空间。
          回忆:在51单片机中,SP的默认初始位置和工作寄存器组1是重合的,这实际上很危险,需要编程者手动调整。
          • 图中,0x00000000 地址存放的值是 0x20008000,这通常是片上SRAM的最高地址,因为Cortex-M的堆栈是向下生长的。

          Step3 读取复位向量 (Fetch Reset Vector)

          紧接着,处理器会访问地址 0x00000004。它从这个地址读取另一个32位的数据。这个数据就是复位向量,即复位服务例程 (Reset Handler) 的入口地址。

          Step4 跳转并执行启动代码 (Jump to Reset Handler)

          处理器将从 0x00000004 读取到的地址值加载到程序计数器 (PC) 中,然后从这个新的PC地址开始取指令并执行。这就是系统启动代码的开始。
          • 一个重要的细节:你图中标注了“最低位必须为1”。这是因为Cortex-M处理器只支持Thumb/Thumb2指令集。地址的最低位(LSB)被用作标志位(T-bit),当T-bit为1时,表示目标地址的代码是Thumb指令。实际地址是0x00000400
          notion image

          五、Cortex-M 存储器系统

          5.1 总线接口与结构

          • 32位总线,4GB 存储空间,指令和数据统一编址
          • 哈佛结构改进:通过多条总线实现指令和数据的并行访问。
          • 基于 AMBA (Advanced Microcontroller Bus Architecture) 总线协议:
            • AHB (Advanced High-performance Bus): 用于系统和存储器,支持流水线操作。
            • APB (Advanced Peripheral Bus): 用于连接低速外设。
          • Cortex-M3/M4 内部总线
            • I-Code 总线: AHB-Lite,负责 0x00000000 - 0x1FFFFFFF (代码区) 的取指
            • D-Code 总线: AHB-Lite,负责 0x00000000 - 0x1FFFFFFF (代码区) 的数据访问
              • I-Code 和 D-Code 总线的存在使得代码区的取指和数据访问可以同时进行。
            • 系统总线 (S-Bus): AHB-Lite,负责其他区域 (如SRAM、外设) 的所有数据传送(包括取指和数据访问)。
            • 外部私有外设总线 (PPB): APB,负责 0xE0040000 - 0xE00FFFFF 区域的私有外设访问 (如调试组件)。
            • 调试访问端口总线 (DAP Bus)。
          • 总线设备连接示例 (STM32) :处理器内核通过总线矩阵/复用器连接到 Flash、SRAM、外设等。
          notion image

          5.2 Flash 访问加速器 (如 STM32 ART Accelerator)

          • Flash 读取通常需要等待周期,影响性能。
          • 加速器通过指令预取、指令缓存和数据缓存来减少等待时间,提高执行速度。
          • CCM (Core Coupled Memory) RAM (如 STM32F407) :
            • 一块与内核紧密耦合的 SRAM,通常有更快的访问速度(零等待状态)。
            • 可以直接通过 I-Code 和 D-Code 总线访问,适合存放关键代码和数据。

          5.3 总线矩阵 (Bus Matrix)

          • 连接不同速度的总线主设备 (如 CPU, DMA) 和总线从设备 (如 Flash, SRAM, 外设)。
          • 允许多条总线同时传输数据 (例如 CPU 访问 SRAM1 的同时,DMA 控制器访问 SRAM2),提高系统并行性和吞吐量。
          • 支持 DMA (Direct Memory Access) 操作,数据传输无需 CPU 干预
          notion image

          5.4 位段操作 (Bit-Banding)

          51虽然也有位地址,但是位地址和普通地址是重合的,需要通过特殊的位指令区分;Cortex-M中,位段区、位段别名区都和普通的地址分开,因此用普通的指令就可以实现位段操作
          位段地址分配
          位段地址分配
          Cortex-M的位段操作是一种高级、强大的内存映射技巧,它巧妙地通过地址转换来实现对位的操作。
          • 实现方式:它并不是通过特殊的位指令,而是通过普通的字(32位)读写指令 (LDR, STR) 来实现的。它在内存中划定了两个区域 :
            • 位段区 (Bit-band Region):这是你想要操作单个比特的实际内存区域。在SRAM和外设区各有一块1MB的位段区 。
            • 位段别名区 (Bit-band Alias):这是一块32MB的内存区域。对这块区域中某个字地址的访问,会被硬件自动映射为对位段区中某一个比特位的访问 。
            • 1MB映射到32MB,这是因为每个字有32位
          • 寻址区域
            • 片上SRAM的起始1MB (0x20000000 - 0x200FFFFF) 。
            • 片上外设的起始1MB (0x40000000 - 0x400FFFFF) 。
          • 操作过程:假设你想将地址 0x40000000 的第 n 位置1。你不需要读-改-写,而是直接向这个比特位对应的别名地址写入一个非零值。硬件会自动完成定位和修改单个比特的操作。
          • 核心优势原子操作 (Atomic Operation) 。由于对单个位的操作是通过一次对别名区的单次总线写操作完成的,这个过程是不可中断的
          特性
          80C51 位寻址
          ARM Cortex-M 位段操作
          实现原理
          专用的位操作指令和布尔处理器。
          内存地址映射。通过访问一个“别名地址”来间接操作一个比特位。
          使用指令
          SETB, CLR, CPL, JB 等位指令。
          普通的字读写指令,如 LDR, STR
          可操作区域
          固定且较小(128位RAM + 部分SFR)。
          较大(SRAM和外设区各1MB)。
          原子性
          非原子操作。大部分是“读-修改-写”过程,可能被中断打断。
          原子操作 13。对单个位的操作是不可分割的,保证了数据一致性。
          效率与安全性
          编程直观,但在复杂系统中存在数据竞争风险。
          编程稍复杂(需要计算别名地址),但操作安全可靠,特别适合实时操作系统和复杂中断场景 14。

          例:将1写入SRAM的0x20000000的第2位

          不使用位段操作:
          使用位段操作:
          这两段代码都是将1写入SRAM的0x2000 0000地址的第2位,但使用位段操作的方法更简洁。
          💡
          优点:位段操作是原子操作不会被其它指令或者异常打断

          5.5 数据对齐与非对齐访问 (略)

           

          Cortex1作业

          Loading...