首页 智能穿戴

STM32串口Bootloader:从零开始,快速上手指南

分类:智能穿戴
字数: (0730)
阅读: (9989)
内容摘要:STM32串口Bootloader:从零开始,快速上手指南,

在嵌入式开发中,固件更新是绕不开的一环。面对频繁的需求变更和 bug 修复,传统的 JLink/ST-Link 在开发阶段显得笨重且效率低下。这时,一个简单易用的 STM32 串口 Bootloader 就显得尤为重要。它可以让我们摆脱对调试器的依赖,直接通过串口更新固件,极大地提升开发效率。本文将带你从零开始,一步步构建一个 STM32 串口 Bootloader,并分享实战中的避坑经验。

Bootloader 底层原理:从 Flash 启动说起

要理解 Bootloader 的工作原理,首先需要了解 STM32 的启动过程。上电后,STM32 会根据 BOOT 引脚的配置,从不同的启动区域启动。通常情况下,我们会选择从 Flash 启动,而 Bootloader 实际上就是在 Flash 的起始地址放置的一段程序。

这段程序负责接收通过串口发送过来的固件数据,并将数据写入 Flash 中的指定区域。写入完成后,Bootloader 会跳转到应用程序的起始地址,开始执行应用程序。这个过程类似于 PC 上的 Grub 或 Windows 的引导程序。

理解这个过程至关重要,它直接影响到 Bootloader 的设计和实现。例如,我们需要 carefully 地选择 Bootloader 和应用程序的起始地址,避免地址冲突。同时,还要考虑到 Flash 的擦除和写入操作,确保数据的完整性和可靠性。这和开发 Linux 驱动类似,需要深入理解硬件特性。

STM32串口Bootloader:从零开始,快速上手指南

硬件准备:搭建一个最小系统

本文以 STM32F103C8T6(俗称小蓝板)为例,介绍 STM32 串口 Bootloader 的实现。当然,其他型号的 STM32 也适用,只需要根据具体的芯片手册进行相应的配置即可。

硬件连接非常简单,只需要将 STM32 的串口引脚(通常是 USART1 的 PA9 和 PA10)连接到 USB 转 TTL 模块上即可。同时,还需要准备一个 USB 转 TTL 模块,用于将 PC 端的串口信号转换为 STM32 可以识别的 TTL 电平。

为了方便调试,建议使用面包板搭建一个最小系统,包括 STM32、USB 转 TTL 模块、电源和一些必要的电阻电容。这样可以避免焊接带来的麻烦,方便我们进行实验和调试。

STM32串口Bootloader:从零开始,快速上手指南

代码实现:一步步构建 Bootloader

下面,我们将一步步构建 STM32 串口 Bootloader 的代码。这里我们使用 Keil MDK 作为开发工具,当然,也可以使用其他 IDE,例如 IAR 或 STM32CubeIDE。

1. 初始化串口

首先,我们需要初始化串口,配置波特率、数据位、停止位和校验位。下面是一个简单的串口初始化函数:

void USART1_Init(uint32_t baudrate) {
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN; // 使能 GPIOA 和 USART1 时钟
  GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_MODE9 | GPIO_CRH_CNF10 | GPIO_CRH_MODE10); // 清除 PA9 和 PA10 的配置
  GPIOA->CRH |= GPIO_CRH_MODE9_1 | GPIO_CRH_CNF9_1; // PA9 作为 TX,复用推挽输出
  GPIOA->CRH |= GPIO_CRH_CNF10_1; // PA10 作为 RX,浮空输入

  USART1->BRR = SystemCoreClock / baudrate; // 设置波特率
  USART1->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 使能发送、接收和 USART1
}

2. 接收固件数据

接下来,我们需要编写代码来接收通过串口发送过来的固件数据。这里我们使用中断方式接收数据,当接收到数据时,会触发中断,在中断处理函数中将数据保存到缓冲区。

STM32串口Bootloader:从零开始,快速上手指南
void USART1_IRQHandler(void) {
  if (USART1->SR & USART_SR_RXNE) { // 接收到数据
    uint8_t data = USART1->DR; // 读取数据
    // 将数据保存到缓冲区
  }
}

3. 擦除 Flash

在写入新的固件数据之前,我们需要先擦除 Flash 中原来的数据。这里我们使用 STM32 的 Flash 擦除函数来实现。

void Flash_EraseSector(uint32_t sector_address) {
  FLASH->KEYR = FLASH_KEY1; // 解锁 Flash
  FLASH->KEYR = FLASH_KEY2;

  FLASH->CR |= FLASH_CR_PER; // 扇区擦除使能
  FLASH->AR = sector_address; // 设置擦除扇区地址
  FLASH->CR |= FLASH_CR_STRT; // 启动擦除

  while (FLASH->SR & FLASH_SR_BSY); // 等待擦除完成

  FLASH->CR &= ~FLASH_CR_PER; // 扇区擦除失能
  FLASH->CR |= FLASH_CR_LOCK; // 锁住 Flash
}

4. 写入 Flash

擦除 Flash 后,我们就可以将接收到的固件数据写入 Flash 中了。这里我们使用 STM32 的 Flash 写入函数来实现。

void Flash_WriteWord(uint32_t address, uint32_t data) {
  FLASH->KEYR = FLASH_KEY1; // 解锁 Flash
  FLASH->KEYR = FLASH_KEY2;

  FLASH->CR |= FLASH_CR_PG; // 编程使能
  *(volatile uint32_t *)address = data; // 写入数据

  while (FLASH->SR & FLASH_SR_BSY); // 等待写入完成

  FLASH->CR &= ~FLASH_CR_PG; // 编程失能
  FLASH->CR |= FLASH_CR_LOCK; // 锁住 Flash
}

5. 跳转到应用程序

当固件数据写入完成后,我们需要跳转到应用程序的起始地址,开始执行应用程序。这里我们使用函数指针来实现。

STM32串口Bootloader:从零开始,快速上手指南
typedef void (*app_entry)(void);

void JumpToApp(uint32_t app_address) {
  app_entry app = (app_entry)(*(__IO uint32_t*)(app_address + 4)); // 获取应用程序入口地址
  __set_MSP(*(__IO uint32_t*)app_address); // 设置 MSP 指针
  app(); // 跳转到应用程序
}

实战避坑:注意 Flash 读写保护和地址偏移

在实际开发中,需要注意以下几点:

  1. Flash 读写保护:STM32 的 Flash 有读写保护机制,需要先解锁 Flash 才能进行擦除和写入操作。如果不解锁,会导致擦除和写入失败。
  2. 地址偏移:Bootloader 和应用程序的起始地址需要 carefully 地选择,避免地址冲突。通常情况下,我们会将 Bootloader 放在 Flash 的起始地址,然后将应用程序放在 Bootloader 后面的一段地址空间。计算偏移量时要特别注意,否则会导致程序跑飞。
  3. 数据校验:为了保证数据的完整性和可靠性,建议在接收固件数据后进行校验,例如使用 CRC 校验或 MD5 校验。如果校验失败,则重新发送数据。
  4. 中断优先级:串口中断的优先级需要 carefully 地设置,避免影响其他中断的执行。尤其是在 Bootloader 中,需要保证串口中断的及时响应。
  5. Watchdog:为了防止 Bootloader 进入死循环,建议开启 Watchdog 定时器。如果 Bootloader 在一定时间内没有完成固件更新,则会触发 Watchdog 复位,重新启动 Bootloader。

这些技巧类似于我们在进行高并发服务开发时,对 Nginx 的配置优化(调整 worker 进程数、设置合理的 keepalive 超时时间、开启 gzip 压缩等),目的都是为了保证系统的稳定性和性能。例如,Flash 读写保护就像 Nginx 的访问控制列表(ACL),可以防止未经授权的访问。

总结

通过本文的介绍,相信你已经对 STM32 串口 Bootloader 有了一个初步的了解。掌握 Bootloader 的开发,不仅可以提升嵌入式开发的效率,还可以加深对 STM32 启动过程和 Flash 操作的理解。希望本文能帮助你快速入门 STM32 串口 Bootloader,并在实际项目中灵活应用。

STM32串口Bootloader:从零开始,快速上手指南

转载请注明出处: 夜雨听风

本文的链接地址: http://m.acea2.store/blog/162188.SHTML

本文最后 发布于2026-04-18 20:07:45,已经过了9天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 春风十里 2 天前
    写得很详细,正好最近在研究这个,感谢大佬!