使用内置bootloader进行串口IAP固件升级——STM32F103RCT6
注意:后续发现以下方法因为没有关闭中断,时钟等,可能在复杂程序中发生错误。有待后续修改。
STM系列有内置的bootloader,支持通过CAN、SPI、I2C、USB DFU、USART进行固件升级。
需配合STM32CubeProgrammer使用,以下为串口接收到0x55后,进入内置bootloader的例子,其中地址0x1FFFF000
需要查询《AN2606
Application note—STM32 microcontroller system memory boot mode》
/*
*********************************************************************************************************
* 函 数 名: JumpToBootloader
* 功能说明: 跳转到系统BootLoader
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void JumpToBootloader(void)
{
uint32_t i = 0;
void (*SysMemBootJump)(void); /* 声明一个函数指针 */
__IO uint32_t BootAddr = 0x1FFFF000; // STM32F1系列内置bootloader地址
/* 关闭全局中断 */
__set_PRIMASK(1);
/* 关闭滴答定时器,复位到默认值 */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/* 设置所有时钟到默认状态,使用HSI时钟 */
HAL_RCC_DeInit();
/* 关闭所有中断,清除所有中断挂起标志 */
for (i = 0; i < 8; i++)
{
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
/* 使能全局中断 */
__set_PRIMASK(0);
/* 跳转到系统BootLoader,首地址是MSP,地址+4是复位中断服务程序地址 */
SysMemBootJump = (void (*)(void))(*((uint32_t *)(BootAddr + 4)));
/* 设置主堆栈指针 */
__set_MSP(*(uint32_t *)BootAddr);
/* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */
__set_CONTROL(0);
/* 跳转到系统BootLoader */
SysMemBootJump();
/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
while (1)
{
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (aRxBuffer[0] == 0x55)
{
JumpToBootloader();
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
}
- 选择串口,“偶校验”
![](https://img2022.cnblogs.com/blog/1515886/202203/1515886-20220303183941196-570673947.png)
- 连接成功
![](https://img2022.cnblogs.com/blog/1515886/202203/1515886-20220303183902861-971431405.png)
3.选择文件,写入
![](https://img2022.cnblogs.com/blog/1515886/202203/1515886-20220303184250372-1432777374.png)
因为内置bootloader有通信安全设置,所以自己用普通串口调试助手发送的bin文件是无法被使用的,需要配合stm32cubeProgrammer使用。
![](https://img2022.cnblogs.com/blog/1515886/202203/1515886-20220314141943407-1899210435.png)
参考
《安富莱_STM32-V6开发板_用户手册 第28-30章》
《AN3155》