你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【stm32U3测评】使用FDCAN进行IAP升级----【1】Bootloader的实现

[复制链接]
短笛君 发布时间:2026-6-21 16:30

1. bootloader项目实现

整体运行逻辑:

  1. 上电或复位后,程序先从 0x08000000 进入 bootloader。
  2. bootloader 完成系统时钟、GPIO、LED、KEY、COM1 串口初始化。
  3. bootloader 只在启动阶段读取一次 KEY 状态。
  4. 如果 KEY 未按下,并且 APP 有效,则跳转到 APP。
  5. APP 启动后打印 APP 状态,并控制 LED1 慢闪。
  6. 如果 KEY 已按下,则停留在 bootloader。
  7. bootloader 停留时打印状态,并控制 LED2 慢闪。

完成以上逻辑 我们就可以实现在bootloder内更新任意的用户APP (在线IAP的内容会在后面讲解实现包裹UART方式和FDCAN方式,本期测评首先实现基础的Bootloader)

2. 硬件资源

项目直接使用Nucleo-U3的默认BSP实现 初始化VCP串口用于Log信息打印

因此该部分硬件配置不再赘述

3. Flash 地址规划

bootloader 和 APP 我们需要放在不同 Flash 区域,防止后下载的程序会覆盖前一个程序。

区域 起始地址 大小 说明
Bootloader 0x08000000 64 KB APP 校验、APP 跳转
APP 0x08010000 0x001F0000 用户应用程序
Flash 结束地址 0x08200000 2 MB 末尾 用于 APP 有效性检查

我们可以现在代码中提前定义好这三个宏定义

image.png

在keil中 我们可以需要直接更改链接设置 或者编写sct文件来将boot或者APP代码链接到指定位置

image.png

bootloader 链接地址:

LR_IROM1 0x08000000 0x00010000
ER_IROM1 0x08000000 0x00010000

4. 启动和跳转原理

STM32U3 是 Cortex-M33 内核。程序启动依赖中断向量表,向量表的前两个 32 位数据非常关键:

向量表偏移 内容 作用
0x00 初始 MSP 值 程序启动后的主栈指针
0x04 Reset_Handler 地址 程序复位入口函数

正常上电时,CPU 从 bootloader 的向量表启动:

0x08000000: bootloader 初始 MSP
0x08000004: bootloader Reset_Handler

当 bootloader 要跳转到 APP 时,需要模拟一次从 APP 启动的过程。APP 的向量表位于 0x08010000

0x08010000: APP 初始 MSP
0x08010004: APP Reset_Handler

bootloader 跳转 APP 的步骤如下:

读取 APP 向量表中的初始 MSP。

读取 APP 向量表中的 Reset_Handler。

校验 MSP 是否位于有效 SRAM。

校验 Reset_Handler 是否位于 APP Flash 区域。

关闭中断,避免 bootloader 的中断在跳转过程中打断流程。

反初始化 HAL 和 RCC,让 APP 从干净状态重新初始化外设。

关闭 SysTick,并清除 NVIC 中断使能和挂起标志。

设置 SCB->VTOR = 0x08010000,让中断向量表切换到 APP。

设置 MSP 为 APP 向量表中的初始栈地址。

重新打开中断。

跳转到 APP 的 Reset_Handler。

在跳转前 一定要校验APP是否完整合法 不然会出现各种情况

校验和跳转的核心代码如下

static uint8_t Bootloader_IsAppValid(void)
{
  const uint32_t appStackPointer = *(__IO uint32_t *)APP_START_ADDRESS;
  const uint32_t appResetHandler = *(__IO uint32_t *)(APP_START_ADDRESS + 4U);

  if ((appStackPointer < SRAM_START_ADDRESS) || (appStackPointer >= SRAM_END_ADDRESS))
  {
    return 0U;
  }

  if ((appResetHandler < APP_START_ADDRESS) || (appResetHandler >= FLASH_END_ADDRESS))
  {
    return 0U;
  }

  if ((appResetHandler & 0x1U) == 0U)
  {
    return 0U;
  }

  return 1U;
}

static void Bootloader_JumpToApp(void)
{
  uint32_t index;
  const uint32_t appStackPointer = *(__IO uint32_t *)APP_START_ADDRESS;
  const uint32_t appResetHandler = *(__IO uint32_t *)(APP_START_ADDRESS + 4U);
  pFunction jumpToApp = (pFunction)appResetHandler;

  __disable_irq();

  HAL_RCC_DeInit();
  HAL_DeInit();

  SysTick->CTRL = 0U;
  SysTick->LOAD = 0U;
  SysTick->VAL = 0U;

  for (index = 0U; index < 8U; ++index)
  {
    NVIC->ICER[index] = 0xFFFFFFFFU;
    NVIC->ICPR[index] = 0xFFFFFFFFU;
  }

  SCB->VTOR = APP_START_ADDRESS;
  __set_MSP(appStackPointer);
  __DSB();
  __ISB();

  __enable_irq();
  jumpToApp();
}

核心运行代码如下

image.png

实现效果

整理来说最关键的部分就是理清APP跳转的原理 其余部分代码十分简单 难度不大

另外 因为代码中使能了串口打印Log 所以需要勾选MicroLib来实现串口的重定向功能 不然会出现各种奇怪的问题

实现效果(暂未烧录APP部分)

image.png

可以看到Bootloadder已经完成APP校验以及跳转判断的逻辑了 接下来我们烧录APP到指定位置看下效果

image.png

APP工程中已经提前设置好了向量偏移部分,APP 并不是从 0x08000000 启动,而是从 0x08010000 启动。如果 APP 仍然使用默认向量表地址,APP 中断会错误地去 0x08000000 查找中断入口,导致中断异常或程序跑飞。

因此 APP 工程需要在 SystemInit() 中设置向量表偏移:

image.png

APP成功运行

这个时候如果我们手动按住KEY 然后按下复位键 MCU默认也停留在Bootloader中

image.png

image.png
收藏 评论0 发布时间:2026-6-21 16:30

举报

0个回答

所属标签

相似分享

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版