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 盘)