iap_over,上位机侦测到最后一包数据也是128个的时候补充发送该命令,下位机将缓存写入并退出
//最后一包有128个数据但是最终没有2048个数据 //收到这个指令检测receiveDataCur和addrCur的值, //完成最后的写入 void iap_over_s(void) { //这个时候,依然在串口下载模式 if(receiveDataCur != 0) { STMFLASH_Write(addrCur,iapbuf,receiveDataCur);//将最后的一些内容字节写进去. //printf("write addr%x,length %d",addrCur,receiveDataCur); addrCur = FLASH_APP1_ADDR; receiveDataCur = 0; //同时,也要退出下载模式 receiveMode = 0; } printf("ok\r\n"); }
这是iap的核心代码,接下来我们在main函数中检测app固化标志,如果标志位设置,那么跳转到app
if(STMFLASH_ReadHalfWord(APP_CONFIG_ADDR) == 0x5555) { //直接跳转到APP iap_jump_app_s(); }
到这里基本上就完成了iap的工作,可是想想,还需要设置一个地方,我们要在target中设置使用的flash空间,不能超范围,如下
如果需要flash下载的话还需要设置jlink的flash下载设置如下.
这样可以直接使用jlink将代码下载到单片机中,而且不会影响原先的app程序,注意,要选择erase sector used,不能全部擦除flash
桥斗麻袋,我们忘了一件事情,假设我们设置了app标志,那及时app能跳转到iap中,iap岂不是马上会跳转回app,永远不能等待下载?
解决办法就是我们在app中app跳转到iap的指令中将app固化标志清除掉,在app代码中添加一条指令
Iap,其响应方法为
__asm void MSR_MSP(u32 addr) { MSR MSP, r0 //set Main Stack value BX r14 }
void iap_jump(u32 iapxaddr) { if(((*(vu32*)iapxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.0x20000000是sram的起始地址,也是程序的栈顶地址 { printf("ok\r\n"); Delay_Ms(10); jump2iap=(iapfun)*(vu32*)(iapxaddr+4); //用户代码区第二个字为程序开始地址(复位地址) MSR_MSP(*(vu32*)iapxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) jump2iap(); //跳转到APP. } else { printf("iap programloss,please check\r\n"); } }
#define APP_CONFIG_ADDR 0X08001FFC //配置地址 #define APP_CONFIG_SET_VALUE 0X5555 //设置值 #define APP_CONFIG_CLEAR_VALUE 0XFFFF //清零值
void iap_Func(void) { Test_Write(APP_CONFIG_ADDR,APP_CONFIG_CLEAR_VALUE); iap_jump(FLASH_IAP_ADDR);//跳转到iap的复位向量地址 }
可以看到,我们先清除了app标志,然后在跳转到iap程序中,就不会影响到iap的流程了,同时app代码也还在单片机里面,另外,app工程里面也要设置两个东西
因为flash的起始地址为0x08000000,而我们用了之前2000的空间作为iap代码空间,那么,app代码的起始空间就变成了0x8002000,还有一个下载界面需要设置
红框部分也要修改. |