BOOT
1.
这是基于threadx的OTA
因为懒得新建程序,直接将app删减后来用,之后需要写boot程序也可以多任务来进行
声明一个函数指针
appxaddr是要偏移的地址 预留了64k给boot 从08010000之后为app程序
至于Message_ID.Message是我用来缓存串口接收的数据的数据,后期根据需求来搞
typedef void (*iapfun)(void);
iapfun jump2app;
uint32_t appxaddr =0X8010000;
void App_Led_BlueTask()
{
while(1)
{
HAL_UART_Transmit(&huart2,"这是BOOT\n",8,20);
tx_thread_sleep(1000);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_2);
jump2app = (iapfun) *(volatile uint32_t *)(appxaddr+4);
if(Message_ID.Message[0]=='0'&&Message_ID.Message[1]=='A')
{
jump2app();
}
}
}
2.
boot程序用烧录器烧录时候记得选择全片擦除
boot程序的起始地址不用变 默认0x08000000就行 根据不同芯片的flash去分配大小
我暂时不需要去精打细算内存 所以就给boot分配0x10000(64K)大小,等之后空间不够的话再去该 这个只需要去看boot程序的文件大小就行,随需求走。
boot最重要的就是实现地址之间的跳转,像升级系统之类的,都是在此基础上衍生,写逻辑代码和flash读写。
boot部分结束,用全片擦除的方式烧录进去就行,可以用串口去打印一个提示数据。
APP
中断向量表偏移,这部分的概念可以去查下资料
这行代码放在main函数开头就好
WRITE_REG(SCB->VTOR, 0x8010000);
这边需要注意的就是把IROM1这个位置的开始位置和大小设置下
开始位置和boot里你的偏移地址是一样的,我从0x08000000这个位置偏移了0x10000那么我这边就设置为0x08010000,大小和boot的一样,可以根据你需求去改,我为了方便随便写的够大就行 但是也不要超过你芯片的flash大小
OTA升级的原理就是将FLASH分为三部分
第一部分:BOOT 上电就启动 进行程序之间的跳转
第二部分 旧程序 原来系统上运行的程序
第三部分 新程序 希望更新的程序
将新程序生成的BIN文件通过串口,WIFI等各种通信方式传给旧的设备,旧设备识别到对应的标志或关键字,将这些BIN文件写入到新程序所在的FLASH里,就可以实现OTA远程更新!
特别重要的事说三遍 !
特别重要的事说三遍 !
特别重要的事说三遍 !
因为FLASH的读写都是按扇区去进行的,所以分配地址的时候一定要看自己开发板所对应的 FLASH扇区分区,按扇区分配,不然可能就会发生烧录APP2将APP1的一部分擦除,导致系统卡死。
所以 根据以上的步骤 将自己的flash分成这三部分
每次开机都回去启动boot 然后根据你的需求,让用户发送不同的关键字去跳转程序或者经过多少秒延时没有接收到对应的关键字,那就默认允许旧程序等等,这些方式很多看你自己的需求与选择。
根据上面的步骤 你可以创建2个APP程序。只需要去修改IROM1的起始地址和大小和中断向量表。
如APP1是0X08010000 ,size是0x30000
WRITE_REG(SCB->VTOR, 0x8010000); 这行代码后面的地址需要完全和APP的起始地址相同
再创建另一个APP2
它的地址就可以设置为0X08040000,size0x30000
WRITE_REG(SCB->VTOR, 0x8040000); 这行代码后面的地址需要完全和APP的起始地址相同
然后在BOOT里进行判断
这段代码是BOOT通过串口接收关键词去跳转不同的APP
需要注意的是创建一个新APP就需要创建一个函数指针(iapfun )和偏移地址(appxaddr)
橙色是APP1函数指针和偏移地址,红色是APP2
如果你需要更多的程序 就可以根据这个流程去分配flash 然后创建更多的APP
typedef void (*iapfun)(void);
iapfun jump2app;
uint32_t appxaddr =0X8010000;
iapfun jump_app2;
uint32_t app2addr =0X8040000;
void App_Led_BlueTask()
{
while(1)
{
HAL_UART_Transmit(&huart2,"这是BOOT\n",8,20);
tx_thread_sleep(1000);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_2);
jump2app = (iapfun) *(volatile uint32_t *)(appxaddr+4);
jump_app2= (iapfun) *(volatile uint32_t *)(app2addr+4);
if(Message_ID.Message[0]=='0'&&Message_ID.Message[1]=='A')
{
jump2app();
}
else if(Message_ID.Message[0]=='0'&&Message_ID.Message[1]=='B')
{
jump_app2();
}
}
}