开发环境:Keil4
固件库开发
目标芯片:STM32F107VC
前言:
这里公司项目要求需要写一个带有网口bootlood根据新项目的硬件,也就是IAP(In Application Programming)。这样我们在实际项目中当我们需要更新硬件代码的时候就不需要把设备拆卸下来,只需要对着预留的网络接口配合上位机下载就可以了。这里当我遇到问题也看了很多网上网友写的帖子,让我受益匪浅。本人也始终相信分享是大家共同进步的强大动力。下面我会写出我在项目中遇到的问题,以及最终解决问题的办法。当你看到这篇帖子哪怕对你有一点点帮助也将是我继续分享下去的强大推动力。当然自己的知识水平也有限如果文中有哪些不对的地方,还望各位网友给予指正,感谢。
问题:
关于IAP具体实现这里在网上我们也能看到很多的帖子,当然官方也有范例这里我就不累述。这里切入重点,这里我发现自己的IAP可以成功的配合上位机实现代码的下载,但是通过打印调试发现代码进入到实际的应用层代码便出现重启又回到了bootlood开始的代码段。下面直接给出我们在做IAP的时候需要注意的点,这也是我自己的实际调试经验。
经验分享:
1.准确的内存分配(确保IAP)的代码段不会溢出到我们实际应用的代码段,以及正确的软件配置。
这里IAP代码段在0x8000000~0x8010000(根据自己实际IAP代码量来分配)
应用层代码Keil设置
代码中的实现设置
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x10000); (这里是应用层的实现配置 )
2.lAP看门狗
这里我们必须要注意的是我们在IAP代码中配置了看门狗,要么在关闭他,要么在应用代码工程中记得喂狗,不然到应用层代码段中会因为看门狗而且不断重启。
3.注意IAP代码段中的那些中断函数
这里我相信对于初次搞IAP的朋友不熟悉整个跳转和代码启动的过程最容易犯下的错误。这里我在调试过程中遇到的问题就在看门狗和IAP代码段的中断函数上。这里我们必须要有一个概念,虽然我们这里是两个工程代码,但是都是在同一块主控上运行,两者之间的关系不是分离的而是紧密相连的。这里简述一下我们在实现IAP代码跳转实现的流程,这里关于具体的实现细节我也在不断的学习。我们的工程代码是从main函数开始运行的,但是代码能成功跑到这里是靠启动文件(汇编)实现的跳转,其实在进入主函数之前已经完成了很多前期的主控制器的初始化,这里当然也包括时钟的初始化(默认下的情况)。这里当代码跳转到应用层代码的时候,代码层的最开始的四个字节分别是系统的复位向量接下来就是一些中断向量表的读取。这里我们在里面IAP实现代码中也可以当判断有误应用层代码是否需要跳转的判断就是靠这几个字节,在当我们跑完IAP代码的时候我们设置的一些中断向量表当我们跑到应用层代码的时候这些向量表依然保存着,如果这个时候我们应用层的代码没有这些中断向量表的函数,代码便找不到这个中断向量的地址而导致代码无法正常运行。
这里总结两点:
@1:当你在IAP中开启的中断函数,在进入应用层代码前关掉这些中断
@2:当你没有关闭IAP代码工程中的中断函数,在应用层代码也写出这些函数的中断函数。
if(((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) //判断应用层有无成功更新代码
{
SysTick-》CTRL &= ~(1《
TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE); //关闭定时器2的中断
IWDG_ReloadCounter(); //喂狗
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); //实际应用代码段的后4个字节
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
}