ARM 架构中的复位(Reset)与复位流程

ARM 架构中的复位(Reset)与复位流程

文章目录

一、复位的基本概念

复位(Reset)是ARM处理器从初始状态开始执行的硬件机制,确保系统从一个已知的、确定的状态启动。复位会将处理器核心、外设和系统恢复到预定义的状态。

二、复位类型

1. 上电复位(Power-on Reset)
  • 系统首次上电时触发
  • 最彻底的复位形式
  • 初始化所有逻辑和状态
2. 系统复位(System Reset)
  • 通过外部复位引脚触发
  • 复位处理器核心和部分外设
  • 内存内容可能保留(取决于配置)
3. 软件复位(Software Reset)
  • 通过写系统控制寄存器触发
  • 如写AIRCR.SYSRESETREQ(Cortex-M)
  • 或通过看门狗定时器触发
4. 调试复位(Debug Reset)
  • 通过调试接口触发
  • 用于调试和开发

三、ARM复位向量表

复位向量位置
  • Cortex-M系列:向量表起始地址(VTOR寄存器指向)

    • 第一个条目:初始堆栈指针(SP)
    • 第二个条目:复位向量(程序计数器初始值)
  • Cortex-A/R系列

    • 复位时从固定地址(如0x00000000或0xFFFF0000)获取第一条指令
    • ARMv8可能从实现定义的地址启动(配置寄存器指定)

四、复位流程(以Cortex-M为例)

阶段1:硬件自动初始化
  1. 取初始SP:从向量表第一个条目加载初始栈指针
  2. 取复位向量:从向量表第二个条目加载PC值
  3. 设置寄存器
    • CONTROL寄存器设为0
    • PRIMASK、FAULTMASK、BASEPRI设为0
    • 处理器进入Thread模式
    • 优先级设为最低
阶段2:启动代码执行
c 复制代码
/* 典型的启动序列 */
Reset_Handler:
    // 1. 初始化数据段(从Flash到RAM)
    LDR r0, =_sdata     // RAM数据段起始
    LDR r1, =_edata
    LDR r2, =_sidata    // Flash中初始值位置
    BL  memcpy
    
    // 2. 清零BSS段
    LDR r0, =_sbss
    LDR r1, =_ebss
    MOV r2, #0
    BL  memset
    
    // 3. 配置系统时钟
    BL  SystemInit
    
    // 4. 配置堆栈指针(可选)
    // 5. 跳转到main函数
    BL  main
    B   .
阶段3:时钟系统初始化
c 复制代码
void SystemInit(void) {
    // 配置时钟树
    // 1. 启用HSI/HSE振荡器
    // 2. 配置PLL
    // 3. 设置Flash等待状态
    // 4. 切换系统时钟源
    // 5. 配置AHB/APB分频器
}

五、多核处理器的复位

引导核心(Primary Core)启动流程:
  1. 所有核心同时从复位释放
  2. 仅引导核心继续执行
  3. 从核等待事件(WFE)或中断
  4. 引导核心配置从核的启动地址
  5. 通过SEV指令或中断唤醒从核
ARMv8多核启动示例:
assembly 复制代码
// 主核执行
primary_core:
    BL  system_init
    // 设置从核入口地址
    LDR x0, =secondary_entry
    MSR RVBAR_EL1, x0    // 设置从核复位向量
    SEV                   // 唤醒从核
    
// 从核入口
secondary_entry:
    WFE                  // 等待事件
    BL  secondary_init

六、复位相关的关键寄存器

系统控制寄存器(Cortex-M)
  • AIRCR:应用中断和复位控制寄存器

    • SYSRESETREQ位:请求系统复位
    • VECTRESET位:仅复位处理器核心
    • VECTCLRACTIVE位:清除活动中断
  • CSR:配置和控制寄存器(ARMv8)

    • 控制复位行为、启动地址等

七、复位流程中的关键考虑

1. 内存初始化顺序
复制代码
Flash/ROM → 数据段复制 → BSS清零 → 堆栈初始化
2. 时钟配置时机
  • 先使用内部低速时钟(HSI/HSI)
  • 再配置和切换到高速时钟(PLL/HSE)
  • 注意Flash访问时间的配置
3. 向量表重定位
  • 可通过VTOR寄存器重定位向量表
  • 常用于从Flash启动到RAM执行的场景
4. 低功耗模式恢复
  • 从休眠/深度睡眠唤醒时,执行部分复位流程
  • 保留RAM内容,重新初始化外设

八、调试与故障处理

复位原因识别
c 复制代码
// 读取复位状态寄存器
uint32_t get_reset_reason(void) {
    return RCC->CSR;  // STM32中的复位状态寄存器
    // 包含:上电复位、软件复位、看门狗复位等标志
}
常见的复位问题
  1. 复位循环:启动代码错误导致持续复位
  2. 时钟配置失败:系统锁死
  3. 堆栈溢出:栈指针设置错误
  4. 向量表错误:VTOR指向无效地址

九、安全扩展中的复位(TrustZone)

  • 安全复位:仅复位安全世界
  • 非安全复位:复位整个系统
  • 双世界独立复位控制
  • 安全监控调用可触发特定复位

十、实际应用示例(Cortex-M4启动)

示例代码:
c 复制代码
// 链接脚本定义
MEMORY {
    FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
    RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 128K
}

SECTIONS {
    .isr_vector : { *(.isr_vector) } > FLASH
    .text       : { *(.text*) }       > FLASH
    .data       : AT(ADDR(.text) + SIZEOF(.text)) {
        _sdata = .;
        *(.data*)
        _edata = .;
    } > RAM
    .bss : {
        _sbss = .;
        *(.bss*)
        _ebss = .;
    } > RAM
}
示例代码解读:

上面一个嵌入式系统的链接器脚本(Linker Script) ,用于定义内存布局和程序段的分配。

1、首先看MEMORY部分,它定义了两个物理内存区域:

第一个是FLASH区域,属性为rx即可读可执行,起始地址是0x08000000,长度512K。这是ARM Cortex-M处理器的典型Flash起始地址。

第二个是RAM区域,属性为rwx即可读可写可执行,起始地址是0x20000000,长度128K。这是Cortex-M处理器的SRAM典型起始地址。

2、接下来是SECTIONS部分,它定义了各个程序段的布局:

第一个是.isr_vector段,包含中断向量表,放在FLASH内存区域的开头位置。

第二个是.text段,包含程序代码,也放在FLASH中。

第三个是.data段,这个比较复杂。它定义在RAM中,但使用AT关键字指定了加载地址在Flash中,具体位置是跟在.text段之后。这里还定义了两个符号:_sdata标记RAM中.data段的起始地址,_edata标记结束地址。这种设计意味着.data段的初始值在编译时存储在Flash中,系统启动时需要将其复制到RAM。

第四个是.bss段,也放在RAM中,定义了两个符号:_sbss标记BSS段起始地址,_ebss标记结束地址。BSS段存储未初始化的全局变量和静态变量,启动时需要清零,不占用Flash空间。

3、这个链接器脚本适用于ARM Cortex-M系列微控制器,如STM32F1/F4系列等,通常配合GCC ARM工具链使用。在实际使用中,启动代码会利用这里定义的符号来初始化内存:将.data段从Flash复制到RAM,将.bss段清零。这是嵌入式系统开发中管理有限内存资源的重要机制。

内存映射示意图:

Text 复制代码
FLASH (0x08000000)        RAM (0x20000000)
+----------------+        +----------------+
| .isr_vector    |        |                |
| .text          |        |                |
| .data (初始值)  | -----> | .data (运行时)  |
|                |  复制   | .bss          |
+----------------+        +----------------+

总结

ARM架构的复位流程是一个精心设计的层次化过程:

  1. 硬件自动初始化核心状态
  2. 启动代码初始化运行环境
  3. 系统配置时钟、内存等关键资源
  4. 应用代码开始执行

理解复位流程对于嵌入式系统开发至关重要,特别是在处理启动时序、低功耗管理和故障恢复等场景时。不同的ARM处理器家族(Cortex-M/A/R)在复位细节上有所不同,但基本遵循相似的原理和模式。

相关推荐
llilian_163 小时前
信号发生器 多通道多功能脉冲信号发生器应用解决方案 多功能脉冲发生器
功能测试·单片机·嵌入式硬件·测试工具
梵刹古音3 小时前
【C语言】 格式控制符与输入输出函数
c语言·开发语言·嵌入式
VekiSon3 小时前
Linux内核驱动——基础概念与开发环境搭建
linux·运维·服务器·c语言·arm开发
yuanmenghao4 小时前
Classic AUTOSAR深入浅出系列 - 【第十六篇】MCAL:为什么 MCU 换了,上层几乎不用动
单片机·嵌入式硬件·autosar
MickyCode5 小时前
嵌入式开发调试之Traceback
arm开发·stm32·单片机·mcu
wwwlyj1233215 小时前
ARM CMSIS-DSP Q格式
arm开发
czwxkn6 小时前
3STM32(stdl)外部中断
stm32·单片机·嵌入式硬件
羽获飞6 小时前
从零开始学嵌入式之STM32——6.与GPIO相关的7个寄存器--重要知识
stm32·单片机·嵌入式硬件
嵌入小生0076 小时前
双向链表、双向循环链表之间的异同---嵌入式入门---Linux
linux·c语言·数据结构·链表·嵌入式·小白