STM32串口Bootloader实现方案(含Ymodem协议与Flash操作)
一、系统架构设计
+---------------------+ +---------------------+
| 串口Bootloader | | 应用程序(APP) |
|---------------------| |---------------------|
| - 接收Ymodem协议数据 |<------| - 用户业务逻辑 |
| - Flash擦写控制 | | - 中断向量表偏移 |
| - 升级标志管理 | | - 跳转入口地址 |
+---------------------+ +---------------------+
二、硬件配置
-
芯片选型
-
推荐STM32F103系列(Flash≥256KB,如F103ZET6)
-
时钟配置:外部8MHz晶振,PLL倍频至72MHz
-
-
外设配置
// USART1配置(115200波特率) huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; HAL_UART_Init(&huart1); -
Flash分区方案
区域 起始地址 大小 功能 Bootloader 0x08000000 16KB 接收固件+校验 APP 0x08004000 240KB 用户程序 参数区 0x08030000 8KB 存储版本/校验值
三、核心代码实现
1. Ymodem协议接收
#define BUFFER_SIZE 2048
uint8_t rx_buffer[BUFFER_SIZE];
volatile uint32_t rx_count = 0;
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE)) {
uint8_t data = USART_ReceiveData(USART1);
if (rx_count < BUFFER_SIZE) {
rx_buffer[rx_count++] = data;
}
}
}
// Ymodem数据包解析
void parse_ymodem_packet() {
if (rx_buffer[0] == SOH) {
uint8_t packet_num = rx_buffer[1];
uint8_t packet_num_inv = rx_buffer[2];
if (packet_num_inv != ~packet_num) return; // 校验失败
// 写入Flash
Flash_Write(0x08004000 + packet_num*128, &rx_buffer[3], 128);
rx_count = 0;
}
}
2. Flash操作函数
void Flash_Erase(uint32_t addr) {
FLASH_Unlock();
FLASH_ErasePage(addr);
FLASH_Lock();
}
void Flash_Write(uint32_t addr, uint8_t* data, uint16_t len) {
FLASH_Unlock();
for (int i=0; i<len; i+=2) {
uint16_t word = (data[i]<<8) | data[i+1];
FLASH_ProgramWord(addr+i, word);
}
FLASH_Lock();
}
3. 应用程序跳转
typedef void (*app_func)(void);
void Jump_To_App() {
// 关闭中断
__disable_irq();
// 设置栈顶指针
__set_MSP(*(uint32_t*)0x08004000);
// 获取复位向量
app_func jump = (app_func)*(uint32_t*)(0x08004000 + 4);
// 跳转执行
jump();
}
四、工程配置要点
-
MDK工程设置
-
设置APP起始地址:
0x08004000 -
生成BIN文件:
fromelf --bin -o app.bin app.axf
-
-
启动文件修改
; startup_stm32f10x_hd.s .word _estack ; 栈顶地址 .word Reset_Handler ; 重置处理函数 .word NMI_Handler ; NMI中断 .word HardFault_Handler; 硬错误处理
参考代码 实现stm32串口bootloader www.youwenfan.com/contentcnr/101718.html
五、调试与验证
-
串口调试技巧
// 打印调试信息 printf("Flash写入地址: 0x%08X\r\n", addr); -
错误处理机制
-
CRC校验:对接收的每个数据包计算CRC16
-
重传机制:超时未收到ACK则重传数据包
-
-
验证流程
1. 按下BOOT按键进入Bootloader 2. 串口发送Ymodem命令 3. 接收完整BIN文件(显示进度条) 4. 校验Flash数据完整性 5. 跳转到APP执行
六、安全增强方案
-
双重校验机制
-
Bootloader CRC32校验
-
APP SHA-256签名验证
-
-
防降级攻击
// 比较当前版本与备份版本 if (current_version < backup_version) { Jump_To_Backup_App(); } -
密钥存储
-
使用STM32的OTP区域存储加密密钥
-
通过安全启动链验证
-
七、常见问题解决
| 问题现象 | 解决方案 |
|---|---|
| 串口接收数据乱码 | 检查波特率设置与硬件流控 |
| Flash写入失败 | 确保擦除地址对齐扇区边界 |
| 程序跳转后复位 | 检查中断向量表偏移设置 |
| 校验失败 | 添加CRC16校验代码 |

浙公网安备 33010602011771号