Skip to main content

IAP 升级

IAP 建议

  • BootLoader 中不要有重试和死循环,出现异常后直接跳转到 APP 正常运行,等待下一次升级请求.
  • APP 中需要有标记位用于和 BootLoader 通信,让 BootLoader 知道是否需要升级和升级信息相关(为什么在 APP 中去标记,因为通信等相关的代码会占用空间,所以把服务器查询)
  • BootLoader 跳转的时候一定要注意将其他外设 deinit。(如果用到某些应用类型的中断可以尝试关闭调试一下。我的代码在跳转程序过程中并没有关闭中断,仅仅将外设 deinit)

IAP 的 BootLoader 部分

  • 需要实现 flash 读写驱动,用于复制读写在 flash 区域中的固件数据
  • 需要跳转程序 APP 运行
  • 需要在跳转的过程中,将所用的外设全部 deinit
  • 设置栈指针,并跳转

核心代码


#define APPLICATION_ADDRESS (uint32_t)0x08004000 //APP地址定义
typedef void (*pFunction)(void); //定义一个函数类型的参数.
pFunction Jump_To_Application; //跳转函数变量

/*
*********************************************************************************************************
* 函 数 名: junp_to_app
* 功能说明: 跳转到APP
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void junp_to_app(void)
{
/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
uint32_t JumpAddress;
/* Jump to user application */

/* 如果初始化了外设,需要反向初始化外设 */

/* 设置所有时钟到默认状态,使用HSI时钟 */
HAL_RCC_DeInit();
/* 关闭滴答定时器,复位到默认值 */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/* 禁止全局中断 */
__set_PRIMASK(1);
/* 关闭所有中断,清除所有中断挂起标志 */
for (uint32_t i = 0; i < 8; i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
/* 使能全局中断 */
__set_PRIMASK(0);
/* 用户代码区第二个字为程序开始地址(复位地址) */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;

/* 初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);

// /* 在RTOS工程,这条语句很重要,设置为特权级模式,SP使用MSP指针 */
// __set_CONTROL(0);

/* 跳转到APP. */
Jump_To_Application();

/* 跳转不成功的处理,可以在这里添加代码 */
while (1)
{

}
}
}

IAP 的 APP 部分

  • 确认是否有更新请求(串口、AT 模块、485、232、SD 卡),如果有需要更新标志位。
  • 按照某种协议下载内容(SD 卡读取、Ymodem 协议、自定义协议)
  • 下载固件到指定位置(内部 flash、外置 spi flash、)
  • 校验固件
  • 设置栈顶指针,并跳转

keil 设置

  • BootLoader 项目工程需要将 target 里面的 IROM1 设置为 0x8000000(默认是这个)
  • APP 项目中需要将 target 里面的 IROM1 设置为 0x8004000(也就是你设置的实际偏移值,但是基础都是以 0x8000000 为主,然后|上偏移值)

通信协议部分

Ymodem 协议

Ymodem 协议是一个面向串行通信的文件传输协议,通常用于嵌入式系统、调试工具、设备固件更新和文件传输。它是 Xmodem 协议的改进版,同时保留了 Zmodem 协议的一些特性。Ymodem 的主要特点是它支持批量文件传输、更大的数据包以及更健壮的错误检测机制。下面详细讨论 Ymodem 协议的组成部分和工作原理。

Ymodem 协议组成部分

1. 数据包结构

Ymodem 使用固定格式的数据包来传输数据。每个数据包的基本结构如下:

  • 起始字符:通常为 SOH (0x01)STX (0x02),分别用于 128 字节或 1024 字节的数据包。
  • 包号:一个字节,标识数据包的序号,范围为 0-255,循环使用。
  • 包号的补码:包号的补码,用于增加包号的安全性。
  • 数据字段:实际的数据,长度为 128 或 1024 字节。如果数据包的长度小于指定长度,则使用填充字符(通常为 0x1A)。
  • CRC 校验:2 字节的 CRC 校验值,用于检测数据包中的错误。

数据包的结构如下所示:

起始字符 | 包号 | 包号补码 | 数据字段 | CRC 校验
1字节 | 1字节 | 1字节 | 128/1024字节 | 2字节

2. 文件信息包

在 Ymodem 的多文件传输中,第一个数据包包含文件的元数据(文件名、文件大小等),而不是实际的数据。文件信息包的结构如下:

  • 起始字符:同样为 SOH (0x01)
  • 文件名:以 NUL 字符(0x00)结尾的字符串,表示文件名。
  • 文件大小:紧随文件名之后,表示文件的大小,以 ASCII 字符串表示,并以 NUL 字符结尾。
  • 填充字符:如果文件名和文件大小信息不足 128 字节,则剩余部分用填充字符 0x00 填充。

该数据包传递文件的元数据,通知接收方如何处理接下来的数据。

3. 数据包

实际的文件内容被分割成多个数据包进行传输,每个数据包最大为 1024 字节(可以是 128 字节)。数据包的结构如前所述,其中包含起始字符、包号、数据字段和 CRC 校验。

4. 结束包

当文件传输完成后,发送方发送一个特殊的空数据包,标志传输结束。这是一个起始字符 EOT (0x04),接收方应当响应 ACK 信号,表示传输结束。

Ymodem 传输流程

1. 握手阶段

  • 接收方通过发送字符 C 开始握手过程。这表示接收方准备使用 CRC 校验进行接收。
  • 发送方收到 C 后,准备发送文件信息包,作为握手的开始。

2. 文件信息包传输

  • 发送方先发送一个包含文件名、文件大小等信息的文件信息包。
  • 接收方接收到文件信息包后,解析其中的元数据,并响应 ACK 表示准备接收文件数据。

3. 数据传输阶段

  • 发送方开始逐包发送文件数据。每个数据包按照指定大小(128 或 1024 字节)传输。
  • 接收方收到数据包后,对数据包进行 CRC 校验,如果校验正确则发送 ACK,表示继续接收下一个数据包。如果校验失败,则发送 NAK 请求重传该数据包。
  • 传输过程中,包号会递增,并在 0 到 255 之间循环使用。

4. 结束阶段

  • 当文件数据传输完毕后,发送方发送 EOT(结束标志),表示文件传输完成。
  • 接收方接收到 EOT 后,响应 ACK 并结束传输。
  • 如果有多个文件要传输,Ymodem 会重复上述流程,每次从握手阶段开始,直到所有文件传输完毕。

5. 错误处理

  • 如果某个数据包在指定的时间内没有被 ACK 确认,发送方会尝试重新发送该数据包。
  • 如果连续重试多次失败,Ymodem 可能会中止传输并放弃剩余数据。

Ymodem 与 Xmodem、Zmodem 的比较

参考

  • Xmodem:Xmodem 是最基础的协议,支持 128 字节的数据包,但不支持批量文件传输。它使用简单的错误检测机制(CRC 或校验和)。
  • Ymodem:Ymodem 是 Xmodem 的增强版本,支持 1024 字节数据包和多文件传输,具有更高的传输效率。Ymodem 引入了文件信息包,能在一次连接中传输多个文件。
  • Zmodem:Zmodem 是一个更现代化的协议,支持动态数据包大小、错误恢复和流控制。Zmodem 允许在传输中断后恢复未完成的传输,这是 Ymodem 不具备的功能。

应用场景

Ymodem 协议广泛应用于需要稳定且可靠的串口通信环境中,特别是在嵌入式系统、调试工具和固件更新过程中。它的多文件传输功能使其在批量传输数据的场景中非常有用。常见应用包括:

  • 嵌入式系统的固件更新:利用 Ymodem 协议,通过串口将新的固件传输到设备上。
  • 设备调试和通信:用于通过串口与嵌入式设备通信,传输数据或进行文件交互。

整体可选方案

APP 下载的问题,可以全下载,可以一半存下载一半存原始程序,使用第三方 SPI FLASH 存储备份程序,使用 SD CARD 进行更新。

keil 生成 bin 文件

$K\ARM\ARMCC\bin\fromelf.exe --bin --output=Bin\@L.bin !L

备注

  • 编写的 IAP 测试程序 D:\HAL_Temp\iap_test

  • 扫地机的程序,里面有关于 IAP 的部分,使用了 FREERTOS C:\Users\Administrator\Downloads\扫地机程序\小米扫地机程序

  • 别人写的关于 IAP 的样例,最后参考 C:\Users\Administrator\Downloads\Bootloader_Stm32F103rbt6-master

  • ST 官方 IAP 的 demo E:\参考程序\IAP 升级 ST 官方程序\en.stm32f0_programming_usart

  • 工控板里面也有关于 IAP 的部分 E:\参考程序\工控板\48.STM32F407 控制板 PLC 工控板\STM32F407 控制板 PLC 工控板

  • 正点原子开发指南,参考 IAP 思路 E:\嵌入式\【正点原子】战舰 STM32F103 开发板 V4 资料盘(A 盘)

参考网址