1. 串口IAP基础框架搭建

串口IAP基础框架搭建 学习卡片

任务说明

本案例实现一个最小可用的STM32 Bootloader,核心功能是:上电后检查应用程序区首字是否为合法栈顶地址,若合法则跳转到应用程序执行。通过一个LED闪烁程序作为应用程序,验证跳转是否成功。

环境与依赖

  • 硬件:STM32F103C8T6(Blue Pill)开发板,板载LED(PC13)
  • 软件:STM32CubeIDE 或 Keil MDK-ARM(本文以STM32CubeIDE为例)
  • 所需库:STM32CubeF1固件包(HAL库)

实现原理

Bootloader与应用程序分别编译,链接到不同的Flash地址。Bootloader位于0x08000000,应用程序位于0x08008000(偏移32KB)。跳转前需完成:

  1. 检查应用程序首字(栈顶地址)是否在RAM范围内(0x20000000~0x20010000)
  2. 关闭全局中断
  3. 设置主栈指针(MSP)为应用程序的栈顶地址
  4. 获取应用程序复位向量并跳转执行

关键完整代码

Bootloader主程序(main.c核心部分)

/* 应用程序起始地址:Flash偏移32KB */
#define APP_ADDRESS  0x08008000U

/* 跳转函数 */
typedef void (*pFunction)(void);

void JumpToApp(void)
{
    uint32_t app_stack_addr;
    pFunction app_reset_handler;
    
    /* 1. 检查应用程序首字是否为合法栈顶地址(RAM范围) */
    app_stack_addr = *(volatile uint32_t *)APP_ADDRESS;
    if ((app_stack_addr & 0x2FFE0000) != 0x20000000)
    {
        /* 栈顶地址非法,停留在Bootloader */
        while (1)
        {
            /* 可在此处添加错误指示,如LED快闪 */
        }
    }
    
    /* 2. 关闭全局中断 */
    __disable_irq();
    
    /* 3. 设置主栈指针 */
    __set_MSP(app_stack_addr);
    
    /* 4. 获取复位向量并跳转 */
    app_reset_handler = (pFunction)(*(volatile uint32_t *)(APP_ADDRESS + 4));
    app_reset_handler();
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    
    /* 简单延时后跳转(便于调试观察) */
    HAL_Delay(100);
    JumpToApp();
    
    /* 正常情况下不会执行到这里 */
    while (1)
    {
    }
}

应用程序链接脚本修改(STM32F103C8Tx_FLASH.ld)

/* 修改Flash起始地址和长度 */
FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 96K
/* 原为 ORIGIN = 0x08000000, LENGTH = 128K */

应用程序向量表重定位(system_stm32f1xx.c中修改)

/* 在SystemInit函数末尾添加 */
#define VECT_TAB_OFFSET  0x8000U  /* 偏移32KB */
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

编译与烧录步骤

  1. 编译Bootloader工程:使用默认链接脚本(起始地址0x08000000),编译生成Bootloader.hex
  2. 编译应用程序工程:修改链接脚本起始地址为0x08008000,添加向量表重定位代码,编译生成App.hex
  3. 烧录Bootloader:使用ST-Link或串口ISP将Bootloader.hex烧录到0x08000000
  4. 烧录应用程序:使用ST-Link将App.hex烧录到0x08008000(注意烧录地址需与链接脚本一致)

验证方法

应用程序代码中让PC13引脚上的LED以1Hz频率闪烁。完成烧录后复位开发板,观察现象:

  • 通过标准:复位后约100ms,LED开始以1Hz频率闪烁,说明Bootloader成功跳转到应用程序
  • 失败表现:LED不闪烁或保持常亮/常灭,说明跳转失败,可能原因包括:应用程序地址配置错误、向量表未重定位、栈顶地址校验失败

常见问题

  • 跳转后程序跑飞:检查应用程序是否已重定位向量表(SCB->VTOR),以及链接脚本起始地址是否与烧录地址一致
  • 栈顶地址校验失败:确认应用程序确实烧录在0x08008000,且该地址首字为有效的RAM地址(0x20000000~0x20010000范围内)
  • 跳转后中断不工作:跳转前需确保已关闭全局中断,跳转后应用程序的SystemInit会重新配置系统时钟和中断