4. 中断向量表重定向

任务目标

在Bootloader与应用程序分层架构中,应用程序链接地址通常与Bootloader不同。当应用程序启动后,CPU仍默认从Bootloader所在地址读取中断向量表,导致应用程序的中断(如SysTick、UART等)无法正确响应。本案例实现应用程序启动时将中断向量表重定向至自身起始地址,确保中断正常触发。

核心原理

Cortex-M内核通过SCB->VTOR寄存器(地址0xE000ED08)定位中断向量表。重定向只需将VTOR设置为应用程序向量表所在地址,并满足地址按0x200(512字节)对齐要求。向量表首字为初始栈指针(MSP),第二个字为复位向量,应用程序链接脚本需保证向量表位于其Flash起始地址。

实现代码

/* app_main.c — 应用程序中断向量表重定向示例 */
#include "stm32f4xx.h"

/* 应用程序向量表起始地址(由链接脚本定义,此处以0x08010000为例) */
#define APP_VECTOR_TABLE_ADDR   0x08010000UL

/* 应用程序入口函数(由启动文件调用) */
void app_entry(void)
{
    /* 1. 检查当前是否已运行在目标向量表地址 */
    if (SCB->VTOR != APP_VECTOR_TABLE_ADDR)
    {
        /* 2. 关闭全局中断,防止重定向过程中断响应错乱 */
        __disable_irq();

        /* 3. 设置VTOR寄存器,完成向量表重定向 */
        SCB->VTOR = APP_VECTOR_TABLE_ADDR;

        /* 4. 数据同步屏障,确保写操作完成 */
        __DSB();

        /* 5. 重新使能全局中断 */
        __enable_irq();
    }

    /* 6. 验证重定向是否成功(可选,用于调试断言) */
    if (SCB->VTOR != APP_VECTOR_TABLE_ADDR)
    {
        /* 重定向失败,进入错误处理(实际工程可替换为断言或LED指示) */
        while (1);
    }

    /* 7. 应用程序主逻辑(此处仅演示中断响应) */
    SysTick_Config(SystemCoreClock / 1000);  /* 1ms SysTick中断 */
    while (1)
    {
        /* 主循环 */
    }
}

/* SysTick中断服务函数 — 验证重定向后中断是否正常响应 */
void SysTick_Handler(void)
{
    static uint32_t tick_count = 0;
    tick_count++;
    /* 实际工程中可在此翻转LED或发送调试信息 */
}

链接脚本关键配置

应用程序的链接脚本必须将FLASH起始地址设置为0x08010000(与APP_VECTOR_TABLE_ADDR一致),并确保向量表位于该地址首部。以GCC LD脚本为例:

/* app.ld — 应用程序链接脚本关键段 */
MEMORY
{
    FLASH (rx)  : ORIGIN = 0x08010000, LENGTH = 240K
    RAM   (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
}

SECTIONS
{
    .isr_vector :
    {
        . = ALIGN(4);
        KEEP(*(.isr_vector))   /* 向量表必须放在起始地址 */
        . = ALIGN(4);
    } >FLASH

    /* 其余段省略 */
}

编译与烧录

  1. 将应用程序编译链接到0x08010000起始地址,生成app.bin。
  2. 通过Bootloader或烧录器将app.bin写入Flash地址0x08010000。
  3. 复位芯片,Bootloader运行后跳转到0x08010000执行app_entry。

验证方法

  • 静态验证:在调试器中设置断点于SCB->VTOR = APP_VECTOR_TABLE_ADDR执行后,查看VTOR寄存器值是否为0x08010000。
  • 动态验证:在SysTick_Handler中设置断点,若程序能周期性进入该中断,说明向量表重定向成功且中断正常响应。
  • 失败判据:若未执行重定向,SysTick中断将无法触发(因为CPU仍从Bootloader向量表取中断入口),程序会卡死在启动文件默认Handler中。

常见问题

  • 对齐错误:若向量表地址未按0x200对齐,VTOR写入无效,需检查链接脚本中FLASH ORIGIN是否满足对齐。
  • 跳转前未重定向:Bootloader跳转到应用程序前,若应用程序入口代码未执行VTOR设置,则中断仍指向Bootloader区域,需确保app_entry在使能任何中断前完成重定向。
  • RAM中运行:若应用程序在RAM中调试运行,VTOR需设置为RAM中向量表地址,且需将向量表从Flash复制到RAM起始位置。