STM32F103RCT6基于CubeMX与XCP协议:从零构建openBLT BootLoader的工程实践
1. 硬件平台与工具链准备
STM32F103RCT6作为经典的Cortex-M3内核MCU,凭借其丰富的外设资源和稳定的性能,成为许多嵌入式开发者的首选。我手头用的是正点原子的Mini开发板,这块板子自带USB转串口芯片,调试起来特别方便。如果你用的是其他品牌的开发板,只需要注意USART1的引脚连接是否正确即可。
开发环境方面,我们需要准备以下工具:
- STM32CubeMX 6.x:图形化配置工具,能自动生成初始化代码
- Keil MDK 5.x:ARM编译器,建议安装最新补丁
- openBLT源码包:从官网下载最新稳定版(我用的v1.12)
- XCP协议栈:openBLT已内置基础实现
第一次接触BootLoader的开发者常犯的错误是忽略硬件兼容性。比如有些STM32F103板子使用外部晶振,而官方Demo默认用内部RC振荡器。我在初期就踩过这个坑,导致串口通信异常。建议先用CubeMX生成一个最简单的串口回环测试工程,确认硬件基础功能正常。
2. CubeMX工程配置详解
2.1 Boot工程创建
打开CubeMX新建工程时,关键是要选对芯片型号。STM32F103RCT6属于Medium-density系列,别选成High-density或别的系列。配置时钟树时有个小技巧:如果板载8MHz晶振,直接在RCC配置里选择Crystal/Ceramic Resonator,CubeMX会自动计算倍频参数。
USART1的配置需要特别注意三点:
- 波特率必须设为57600(与openBLT官方Demo保持一致)
- 硬件流控制选择Disable
- 使用LL库而不是HAL库(在Project Manager → Advanced Settings里修改)
我建议勾选"Generate peripheral initialization as a pair of .c/.h files"选项,这样生成的代码结构更清晰。最后生成工程时,记得选择MDK-ARM作为Toolchain/IDE。
2.2 关键外设配置
除了基本时钟和串口配置,还需要处理两个重要细节:
- GPIO配置:虽然Demo用不到LED,但建议保留一个调试用的LED引脚(比如PC13),方便后期排查问题
- 中断优先级:在NVIC配置里,确保USART1全局中断的优先级高于SysTick(openBLT依赖SysTick计时)
有个容易忽略的点是Flash分区设置。在Project Manager → Linker Settings里,建议将ROM起始地址设为0x08000000,大小设为0x10000(对应64KB)。这个值需要与后续的flash_layout.c文件完全一致。
3. openBLT源码移植实战
3.1 文件结构梳理
从官网下载的源码包解压后,重点看这几个目录:
openblt_v011200/ ├── Target/ │ ├── Demo/ # 参考实现 │ └── Source/ # 核心源码 └── Host/ # 上位机相关需要移植到工程的文件包括:
ARMCM3_STM32F1目录下的CPU相关文件blt_conf.h配置文件flash_layout.c存储布局文件- 协议栈文件(选择XCP协议)
我建议先在工程里新建一个OpenBLT分组,然后按功能添加文件。特别注意flash_layout.c需要放在工程根目录,这个文件定义了BootLoader占用的Flash空间。
3.2 关键文件修改
blt_conf.h里有几个必须修改的宏定义:
#define BOOT_COM_UART_ENABLE (1) #define BOOT_COM_UART_CHANNEL (0) // 对应USART1 #define BOOT_COM_UART_BAUDRATE (57600)在cpu_comp.c中需要实现硬件抽象层。重点修改串口发送函数:
void CpuComSendByte(blt_int8u data) { while(!LL_USART_IsActiveFlag_TXE(USART1)); LL_USART_TransmitData8(USART1, data); }遇到编译错误时,最常见的问题是LL库头文件冲突。解决方法是在stm32f1xx_it.c里注释掉#include "stm32f1xx_ll_gpio.h",因为openBLT有自己的GPIO操作实现。
4. XCP协议栈集成技巧
4.1 协议配置要点
openBLT默认支持XCP over UART,但需要手动启用。在blt_conf.h中添加:
#define BOOT_FILE_SYS_ENABLE (0) #define BOOT_XCP_ENABLE (1) #define BOOT_XCP_UART_ENABLE (1)XCP协议有个重要参数是包超时时间,建议设置为:
#define BOOT_COM_UART_RX_TIMEOUT_MS (100)实际测试中发现,如果开发环境有干扰,可以适当增大这个值。但要注意超过200ms会影响固件更新速度。
4.2 通信调试方法
连接硬件后,可以用串口助手发送XCP连接命令测试:
0xFF 0x00 0xFA 0x00 0xFB 0x00 0x00 0x00正常应该收到ECU返回的肯定响应。如果通信失败,建议:
- 用逻辑分析仪抓取波形,确认波特率准确
- 检查
CpuComReceiveByte()函数实现是否正确 - 验证RS232电平转换芯片是否工作
我在调试时发现一个典型问题:某些USB转串口芯片在高速率下不稳定。解决方法是在设备管理器里调整串口缓冲区大小,或者换用FTDI芯片的转换器。
5. APP工程与固件合成
5.1 APP工程配置
创建APP工程时,关键是要设置正确的Flash偏移地址。在Keil的Options → Target选项卡中:
- IROM1起始地址设为0x08010000(假设BootLoader占用64KB)
- 大小根据实际Flash容量调整
中断向量表偏移需要在system_stm32f1xx.c中修改:
#define VECT_TAB_OFFSET 0x10000有个实用技巧:在APP的main函数最开始添加延迟:
HAL_Delay(100); // 等待BootLoader超时这样可以避免频繁复位时意外进入BootLoader模式。
5.2 固件生成与下载
生成SREC格式固件的方法:
- 在Keil的User选项卡添加Post-build命令:
fromelf --m32 --output=@L.srec !L - 或者手动执行:
fromelf --m32 --output=app.srec .\Objects\app.axf
使用openBLT Host Tools下载时,如果遇到校验失败,可能是:
- Flash布局不匹配(检查flash_layout.c)
- 芯片写保护未解除(先用ST-Link Utility全片擦除)
- 电源不稳定(尤其无线模块供电时)
6. 联调问题排查指南
6.1 常见错误分析
问题1:BootLoader启动后无法跳转到APP
- 检查APP的向量表偏移量
- 确认APP的bin文件确实烧录到正确位置
- 用J-Link读取Flash内容验证
问题2:XCP通信时断时续
- 测量串口信号质量
- 降低波特率测试(如改为19200)
- 检查接地是否良好
问题3:Flash写入失败
- 确认
FLASH_Unlock()已调用 - 检查
flash_layout.c中的扇区定义 - STM32F103的Flash编程需要64位对齐
6.2 性能优化建议
加快固件传输:
- 在
blt_conf.h中增大BOOT_COM_UART_RX_MAX_DATA到256字节 - 上位机使用块传输模式
- 在
减小BootLoader体积:
- 移除不需要的协议(如CAN)
- 使用-Os优化等级
- 裁剪调试信息
增强可靠性:
- 添加Watchdog喂狗机制
- 实现Flash写操作的CRC校验
- 设计双备份固件回滚方案
移植过程中最耗时的往往是硬件兼容性问题。建议先用官方Demo验证硬件平台,再逐步替换为自己的实现。遇到异常时,用LED闪烁次数表示错误代码是个实用的调试方法。
