目录
QT上位机给STM32设备串口IAP升级固件
1,实现原理
2,程序流程
3,关键代码解析
4,相关工具及代码
废话不多说看看效果先
上位机源码连接:https://download.csdn.net/download/qq_28643619/10922262
应用编程IAP(In-Application-Programming)是应用在Flash程序存储器的一种编程模式,它可以在应用程序正常运行的情况下,通过调用特定的IAP程序对另外一段程序Flash空间进行读/写操作,甚至可以控制对某段、某页甚至某个字节的读/写操作。主要用于数据存储和固件升级。对于IAP应用,通常会有两个程序,第一个程序Bootloader程序不执行正常功能,只是通过某种方式(串口,usb,SD卡)接收第二个程序,并进行更新。第二个程序APP程序是执行的主体,用于实现应用功能。
对于stm32闪存模块,主要由主存储器、信息块和闪存存储器接口寄存器三部分构成。
主存储器,该部分用来存放代码和数据常数(如 const 类型的数据)。对于大容量产品,其被划分为 256 页,每页 2K 字节。注意, 小容量和中容量产品则每页只有 1K 字节。看出主存储器的起始地址就是 0X08000000, B0、 B1 都接GND 的时候,就是从 0X08000000开始运行代码的。
信息块,该部分分为 2 个小部分,其中启动程序代码,是用来存储 ST 自带的启动程序,用于串口下载代码,当 B0 接 V3.3, B1 接 GND的时候,运行的就是这部分代码。用户选择字节,则一般用于配置写保护、读保护等功能,本章不作介绍。
闪存存储器接口寄存器,该部分用于控制闪存读写等,是整个闪存模块的控制机构。
对主存储器和信息块的写入由内嵌的闪存编程/擦除控制器(FPEC)管理;编程与擦除的高电压由内部产生。
对于flash的读写的流程
这里要特别留意一个闪存等待时间,因为 CPU 运行速度比 FLASH 快得多, STM32F103的 FLASH 最快访问速度≤24Mhz,如果 CPU 频率超过这个速度,那么必须加入等待时间,比如我们一般使用72Mhz的主频,那么FLASH等待周期就必须设置为 2,该设置通过 FLASH_ACR寄存器设置。
编程流程
1、检查 FLASH_CR 的 LOCK 是否解锁,如果没有则先解锁,(向KEYR寄存器中写入特定序列KEY1和KEY2)
(实际中需要查看当前要写入的扇区是否有数据,如果有数据,则需要进行擦除操作,然后再进行下面的步骤)
2、检查 FLASH_SR 寄存器的 BSY 位,以确认没有其他正在进行的编程操作
3、设置 FLASH_CR 寄存器的 PG 位为’1’,用于表示接下来进行写操作
4、在指定的地址写入要编程的半字
5、等待 BSY 位变为’0’,表示编程完成
6、读出写入的地址并验证数据
我们在 STM32 的 FLASH 编程的时候,要先判断缩写地址是否被擦除了
下面介绍页擦除过程
读出被擦除的页并做验证
1、检查 FLASH_CR 的 LOCK 是否解锁,如果没有则先解锁(向KEYR寄存器中写入特定序列KEY1和KEY2)
2、检查 FLASH_SR 寄存器的 BSY 位,以确认没有其他正在进行的闪存操作
3、设置 FLASH_CR 寄存器的 PER 位为’1’,用于表示进行页擦除操作
4、用 FLASH_AR 寄存器选择要擦除的页
5、置 FLASH_CR 寄存器的 STRT 位为‘1’表示开始一次擦除操作
6、等待 BSY 位变为’ 0’
读出被擦除的页并做验证
我们来了解下stm32的程序运行流程,如下图所示
程序运行的地址从0x08000000(FLASH)开始运行
1程序开始运行后,从中断向量表中取出复位中断向量,并执行服务程序。
2执行完中断向量程序会跳转至主main函数入口执行,并在死循环中一直执行。
3当在主函数中发生中断时间时,系统强制PC指针指向对应中断向量表对应位置。
4PC指针在中断向量表处取出中断服务程序入口地址,并跳转至对应位置执行。
5中断服务程序执行完成后,PC指针跳回发生中断时系统在main函数中的位置,继续往下执行。
当加入IAP应用后stm32的程序流程变为下图所示
程序运行的地址从0x08000000(FLASH)开始运行
1程序开始运行后,从中断向量表中取出复位中断向量,并执行服务程序。执行完中断向量程序会跳转至Bootloader程序main函数入口执行。
2在main中系统检查是否需要对第二部分代码进行更新,如果需要则执行更新操作,如果不需要则跳过更新操作,跳转至APP程序的入口
3在APP程序入口首先进入重新映射的中断向量口,根据新的中断复位向量,执行复位中断程序,然后跳转至APP程序main入口。
4当在主函数中发生中断时间时,系统强制PC指针指向对应中断向量表对应位置(这里还是强制跳转到地址0x0800004中断向量表位置,而不是APP程序的中断向量表)。
两个注意点:
1) 新程序必须在 IAP 程序之后的某个偏移量为 x 的地址开始;
2) 必须将新程序的中断向量表相应的移动,移动的偏移量为 x;
对于程序的设置
IAP程序
通过串口设置程序的接收
根据要求设置存储APP程序的地址
APP程序
设置程序存储区,与数据存储区 在Target->Read/Only Memory Areas-> IROM与IRAM处设置,这里APP程序的存储首地址设为0x08010000,大小为0x70000(即前0x10000为存放IAP程序)
设置中断向量表偏移地址SCB->VTOR = FLASH_BASE | 0x10000;
生成BIN文件
STM32F103的IAP关键代码:
int main(void)
{
uint32_t tick1;
tick1 = SysTick_GetCurrent();
MCU_Init();
AreaFlagFirstLoadInit();
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x8000000); //iap初始都从0x8000000开始运行
printf("init success\r\n");
__enable_irq();
while(1)
{
iapLoop();
if((remainSend == 0x00) && (upgradeDoneFlag == 0xaa55aa55))
{
(currentAreaNum==areaA) ? (FlashDestination=ApplicationAddress_A) : (FlashDestination=ApplicationAddress_B);
if(((*(__IO uint32_t*)FlashDestination) & 0x2FFE0000 ) == 0x20000000) //binÎļþÉý¼¶
{
printf("Execute user APP1 Program upgradeDoneFlag=%x\r\n",upgradeDoneFlag);
USART_Cmd(USART1, DISABLE);
__disable_irq();
JumpAddress = *(__IO uint32_t*) (FlashDestination + 4);
Jump_To_Application = (pFunction) JumpAddress;
MSR_MSP(*(vu32*)FlashDestination);
Jump_To_Application();
}
else
{
if(SysTick_GetLapse(tick1)>1000)
{
printf("ÎÞFLASHÓ¦ÓóÌÐò,ÎÞ·¨Ö´ÐÐ!\r\n");
tick1 = SysTick_GetCurrent();
}
}
}
}
}
uint8_t AreaFlagFirstLoadInit(void)
{
uint8_t ret = 0;
STMFLASH_Read(ADDR_FLASH_LAST_PAGE,&upgradeDoneFlag,1);
FLASH_Unlock();
if(upgradeDoneFlag==0xffffffff || upgradeDoneFlag==0x00000000)
{
upgradeDoneFlag = 0xaa55aa55;
FLASH_ProgramWord(ADDR_FLASH_LAST_PAGE,0xaa55aa55);
}
STMFLASH_Read(AREA_NUM_ADDR,¤tAreaNum,1);
if(currentAreaNum == 0xffffffff || currentAreaNum==0x00000000)
{
printf("ÇøÓò±ê־λ³õʼ»¯");
currentAreaNum = areaA;
if(FLASH_COMPLETE!=FLASH_ProgramWord(AREA_NUM_ADDR,areaA))
{
printf("ÇøÓòA±ê־λÉϵç³õʼ»¯Ê§°Ü");
ret = 1;
}
}
FLASH_Lock();
switch(currentAreaNum)
{
case areaA:
addrCur = ApplicationAddress_B;
break;
case areaB:
addrCur = ApplicationAddress_A;
break;
default:
break;
}
printf("addrCur=%x currentAreaNum=%x upgradeDoneFlag=%x\n",addrCur,currentAreaNum,upgradeDoneFlag);
return ret;
}
单片机iap及app工程连接:
用到的工具软件:
1、固件编译生成工具(编译IAP和两个区域运行的app程序生产bin文件):keil5
2、固件拼接工具(初始iap和app1拼接,用于工厂生产烧写):
3、固件下载工具:STM32 ST-LINK Utility