1 简介-STM32 IAP
- IAP(In Application Programming,应用内编程),是指程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。
- 下面针对STM32 IAP功能。在设计固件程序时,需要建立两个MDK工程。
MDK工程 |
IAP工程 |
APP工程 |
代码功能 |
通过某种通信管道(USART等)接收数据,写入APP程序对应的Flash,修改参数或程序 |
正常的目标功能 |
存放位置 |
Flash的开始区域(一般会设置写保护,正常响应中断) |
Flash中IAP代码空间之后(需要重映射中断向量表) |
执行顺序 |
上电执行 |
等待IAP程序跳转 |
下载方式 |
ISP、SWD等 |
ISP、SWD等、IAP |
2 实例-STM32F103C8T6
2.1 IAP工程主要部分
#include "stm32f10x.h"
typedef void(*pFunction)(void);
#define IAP_ADDRESS 0x8000000
#define APP_ADDRESS 0x8004000
uint32_t jumpAddress;
pFunction Jump_To_App;
int main(void)
{
FLASH_Unlock();
if(((*(__IO uint32_t*)APP_ADDRESS) & 0x2FFE0000) == 0x20000000)
{
jumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4);
Jump_To_App = (pFunction)jumpAddress;
__set_MSP(*(__IO uint32_t*)APP_ADDRESS);
Jump_To_App();
}
while (1)
{
}
}
2.2 APP工程主要部分
#include "stm32f10x.h"
#define IAP_ADDRESS 0x8000000
#define APP_ADDRESS 0x8004000
int main(void)
{
NVIC_SetVectorTable(NVIC_VectTab_FLASH, APP_ADDRESS - IAP_ADDRESS);
while (1)
{
}
}
2.3 程序通过IAP方式下载
- 需要先将APP MDK工程生成的HEX文件(十六进制)转为BIN文件(二进制)。可以使用
hex2bin.exe
,例如在CMD窗口中输入hex2bin.exe .\Output\app.hex
,即可生成app.bin
。
- 生成二进制文件后,即可通过通信管道(USART等),将数据发送给STM32,STM32运行在IAP程序中,接收并烧写到对应的Flash中。
- 为此,自定义了上位机(PC)将APP程序下载到下位机(STM32)的分包下载协议。
上位机 |
|
|
|
名称 |
字节数(Byte) |
值 |
备注 |
指令码 |
1 |
0xEE |
任意,暂定为0xEE |
数据包总数 |
1 |
0x00~0xFF |
总包数=值+1 |
当前数据包序号 |
1 |
0x00~0xFF |
包序号=值+1 |
数据段长度 |
1 |
0x01~0xFC |
4字节对齐,长度为4的倍数,最后一包长度不大于单包发送长度则不受限制,但至少为1Byte |
数据段 |
1~252 |
0x00~0xFF |
|
校验码(偶校验) |
1 |
0x00、0x01 |
仅数据内容偶校验 |
合计 |
260 |
- |
最大可下载文件大小为 255*256 = 65280 Byte < 64KB |
下位机 |
|
|
|
名称 |
字节数(Byte) |
值 |
备注 |
ACK/NACK |
1 |
0xEE/其他值 |
返回0xEE表示ACK,其他值为NACK |
- |
- |
- |
上位机收到NACK则重发当前数据包 |
- 上位机(Delphi 7)
if(Key1_GetStatus())
{
pageNbr = Flash_PagesMask(FULL_ADDRESS - APP_ADDRESS);
for(cnt = 0; (cnt < pageNbr) && (flashStatus == FLASH_COMPLETE); cnt++)
{
flashStatus = FLASH_ErasePage(APP_ADDRESS + (PAGE_SIZE * cnt));
}
}
while (1)
{
if(bt_rc_flag)
{
isNotBinFrame = Iap_CheckFrame(flashDataPackCnt);
if(isNotBinFrame)
{
if(isNotBinFrame == 3)
{
bt_rc_flag = 0;
}
else
{
bt_rx_len = 0;
bt_rc_flag = 0;
Bt_SendByte(0xFF);
}
}
else
{
Iap_CopyFrame(&binFrame);
allFlashDataSize += binFrame.dataSize;
for(cnt = 0; (cnt < binFrame.dataSize) && (flashAddress < APP_ADDRESS + allFlashDataSize); cnt += 4)
{
FLASH_ProgramWord(flashAddress, *(uint32_t*)(binFrame.data + cnt));
flashAddress += 4;
}
flashDataPackCnt += 1;
bt_rx_len = 0;
bt_rc_flag = 0;
Bt_SendByte(0xEE);
if(flashDataPackCnt == binFrame.packAll)
{
printf(">>>Reboot!\r\n");
Stm32_SoftReset();
}
}
}
}
- 整体工程代码见 码云Gitee 。
注意:没有上传工程配置文件,工程下载后需要修改一下ROM地址设置(如前文两张图片)。
程序启动时如果Key0按下则进入IAP模式,此时等待Key1按下;当Key1按下时,擦除对应Flash并从USART2接收程序,校验并写入到Flash中;最后软复位,即下载完自动重启。