ARM Cortex-M 向量表详解

文章目录

ARM Cortex-M 向量表详解

一、什么是向量表?

向量表是一个存储在代码存储器(通常是 Flash)起始区域的字对齐数组。其中的每一个字(32位数据)都代表一个特定的地址,称为"向量"。

当处理器发生异常(如复位、中断、系统调用)时,内核硬件会自动查询这个表,并根据异常类型跳转到对应的地址执行程序。这是 Cortex-M 处理器处理异常和启动的基石。

二、向量表的结构与核心内容

下表列出了 Cortex-M 向量表的标准布局。其起始地址默认为 0x00000000,但可通过 VTOR(向量表偏移寄存器)重定位。

地址偏移量 向量名称 简要说明 重要性/备注
0x00000000 初始主栈指针 (MSP) 硬件加载到主栈指针寄存器的初始值。 至关重要。决定了程序启动后栈的起始位置(通常指向内部 RAM 顶端)。
0x00000004 复位向量 (Reset_Handler) 程序执行的入口点。芯片复位后,PC 指针被设置为此地址。 至关重要 。包含 main() 函数调用的起点,负责初始化 C 运行时环境。
0x00000008 非屏蔽中断 (NMI_Handler) 不可被屏蔽的中断处理函数地址。 高优先级异常,用于处理严重硬件故障。
0x0000000C 硬错误 (HardFault_Handler) 所有严重错误的默认处理函数。 重要。用于调试,如内存访问违规、非法指令等。
0x00000010 内存管理错误 (MemManage_Handler) MPU 访问违规触发的异常(Cortex-M3/4/7 等)。 可选,但启用 MPU 后非常重要。
0x00000014 总线错误 (BusFault_Handler) 总线访问错误(如访问不存在的地址)。 可选,用于高级错误诊断。
0x00000018 用法错误 (UsageFault_Handler) 未定义指令或非法状态等错误。 可选,用于高级错误诊断。
0x0000001C 保留
0x00000020 保留
0x00000024 保留
0x00000028 SVCall 异常 (SVC_Handler) SVC 指令触发的系统调用。 重要。用于实现操作系统(如 FreeRTOS)的系统 API。
0x0000002C 调试监控 (DebugMon_Handler) 调试监控异常。 主要用于调试器。
0x00000030 保留
0x00000034 PendSV 异常 (PendSV_Handler) 可挂起的系统服务中断。 极其重要。常用于操作系统(如 FreeRTOS)的上下文切换。
0x00000038 SysTick 异常 (SysTick_Handler) 系统定时器中断。 极其重要。为操作系统提供心跳时钟,也可用于裸机程序延时。
0x0000003C 及以后 外设中断 (IRQ Handlers) EXTI0_IRQHandler, TIM2_IRQHandler, USART1_IRQHandler 等。 重要。数量由芯片型号决定,是用户处理外部事件的关键。

三、关键概念深入解析
1. __initial_sp(初始栈指针)详解
  • 值从哪里来?
    __initial_sp 的值由链接器(如 ARM GCC 的链接脚本 *.ld 文件)计算得出,通常被设置为内部 RAM 的末地址+1 。例如,如果 RAM 地址范围是 0x20000000 ~ 0x20007FFF(32KB),则 __initial_sp 通常为 0x20008000

  • 存储在哪里?

    链接器会将计算好的 __initial_sp 值放置在最终程序映像的最开头 ,即物理地址 0x08000000(Flash 起始地址)。

  • 处理器如何读取?

    • Cortex-M 处理器硬件设计为:上电或复位后,首先从逻辑地址 0x00000000 读取第一个字作为 MSP 初始值,从逻辑地址 0x00000004 读取第二个字作为复位向量。
    • 在 STM32 等芯片中,通过启动模式配置 (如 BOOT 引脚),逻辑地址 0x00000000 在启动阶段会被重映射 到某个物理存储器(如主 Flash 0x08000000、系统存储器或 SRAM)。
    • 结论__initial_sp 的值存储在 Flash 的 0x08000000 处,但处理器在启动时通过地址重映射,从 0x00000000 这个"窗口"读取到它。
2. 向量表偏移寄存器 (VTOR)
  • 作用 :允许软件将向量表从默认的地址(如 0x00000000重定位到 RAM 或其他 Flash 区域。
  • 应用场景
    1. Bootloader 程序 :Bootloader 位于 0x08000000,其向量表也在此。当跳转到用户应用程序(如位于 0x08010000)时,需要先将 VTOR 设置为 0x08010000,以便中断能正确跳转到用户程序的中断服务函数。
    2. 动态修改中断函数:将向量表复制到 RAM 中,并修改 VTOR 指向 RAM。这样可以在运行时动态更改某个中断的服务函数,实现灵活的插件机制。
3. 中断优先级 (NVIC) 与向量表的关系
  • 关系 :向量表存储的是中断服务函数(ISR)的地址 ,而 NVIC 管理的是这些中断的优先级和使能状态
  • 在 STM32CubeMX 工程中的体现
    • 向量表内容 :在 Startup/startup_stm32fxxxx.s 汇编文件中定义。例如:

      c 复制代码
      g_pfnVectors:
        .word  _estack                   /* 0x00000000: __initial_sp */
        .word  Reset_Handler             /* 0x00000004: Reset Vector */
        .word  NMI_Handler               /* 0x00000008: NMI */
        .word  HardFault_Handler         /* 0x0000000C: Hard Fault */
        // ... 其他向量
        .word  TIM2_IRQHandler          /* 某个外设中断向量 */
    • NVIC 配置(优先级和使能)

      • 优先级设置 :在 main.cMX_NVIC_Init() 函数中,通过 HAL_NVIC_SetPriority(IRQn, preemptPriority, subPriority) 为每个中断源设置优先级。
      • 中断使能 :在 stm32fxxxx_hal_msp.c 的各外设 MspInit 函数中,通过 HAL_NVIC_EnableIRQ(IRQn) 使能中断。

四、总结要点
  1. 向量表是地址表:它存的是函数指针,不是代码本身。
  2. 前两个向量是硬性要求MSP初始值复位向量 是芯片能正常启动的绝对必要条件。
  3. 地址是逻辑映射的0x00000000 是硬件的"入口",其背后映射的物理存储器由芯片的启动配置决定。
  4. 向量表是可移动的:通过 VTOR 寄存器,可以灵活地将向量表放置在需要的位置,这是高级应用(如 Bootloader、OS)的基础。
  5. 向量表与 NVIC 分工明确:向量表负责"去哪儿执行"(地址),NVIC 负责"何时执行"以及"谁先执行"(优先级和使能)。
相关推荐
碧海银沙音频科技研究院5 小时前
DiVE长尾识别的虚拟实例蒸馏方法
arm开发·人工智能·深度学习·算法·音视频
炸膛坦客9 小时前
Cortex-M3-STM32F1 开发:(十一)ARM Cortex-M 内核中的 MPU 和 FPU
arm开发·stm32·嵌入式硬件
GilgameshJSS14 小时前
STM32H743-ARM例程29-HTTP
c语言·arm开发·stm32·单片机·http
Despacito0o1 天前
Keil MDK-ARM 5.42a 完整安装指南(2025.4.19最新版)
arm开发·stm32·单片机·嵌入式硬件·物联网·51单片机·嵌入式实时数据库
去往火星1 天前
基于 Windows 平台利用 QEMU 部署 ARM 架构的虚拟机
arm开发
wanhengidc2 天前
传奇手游可以使用云手机挂机搬砖吗
服务器·arm开发·智能手机·玩游戏·1024程序员节
GilgameshJSS2 天前
STM32H743-ARM27例程-TCP_Server
c语言·arm开发·stm32·单片机·tcp/ip
切糕师学AI2 天前
ARM Cortex-M 中的断点单元FPB是什么?
arm开发·cortex-m
碰大点3 天前
Ubuntu 16.04交叉编译arm-linux-gnueabihf的QT5.6.2
linux·arm开发·qt·ubuntu·arm-linux