STM32IAP升级-----编写IAP升级遇到的问题总结

IAP的源码等资料我上传了 , 压缩包内有12个文件 ,  , http://download.csdn.net/detail/f907279313/7524849(要积分的辛苦收集的你们就给点积分吧)
还有另一篇博客总结的IAP:http://blog.csdn.net/super_demo/article/details/32133257
一,串口通信问题
1 , 串口通信两端的TTL电平要一致 , 看选用的芯片 , 要么都是3.3V要么都是5V 。。当两端电平不一致时通常是收不到数据的 。。当检测程序等都没有问题但是依然收不到数据时 , 考虑检测一下两端的电平是否一致 。。可用示波器查看收发数据时的电平


2 , 在写IAP是使用的官方的库函数 , 结果串口一直收不到正确的数据 。不管我发什么 , 收到的都是0x58或者0xF6 , 而且我发5个字节只能收到2个 。。确定自己的程序逻辑没问题 , 然后怀疑是使用的库函数有问题 。使用beyond compare挨着对照了一下以前写过的正确的程序 。。发现系统初始化时外部晶振没有改 。。在SystemInit();时就是为了/* 配置系统时钟为168M 使用外部8M晶体+PLL*/ 在函数内有一个宏定义#define PLL_M25. 。。。库函数默认的是25但是我们必须要使用8M的晶振 。。所以要把25改成8. 。。。。。。改完测试通过 。。。。。


3 , 在问题2的时候自己犯了个错误 。当时我把另一个程序的库文件都拷过来了替换了原来的库文件 , 结果直接进不了中断了 。有中断程序就死了 。。。如图所示
有中断时汇编显示就跳到了黄色的那句话 。然后程序就死了 。。其实进不了中断首先想到的是中断向量表的问题 。当时一着急没想到这个问题 。。复制过来的库文件是我写的IAP的APP程序 , 我把其中的中断向量表改了 , 我不是在main函数中改的 , 我是直接改的库函数中的偏移量 , 然后就把这个问题给忘了 , 导致找了半天终于意识到是中断向量表出了问题 。。。



4 , 串口一上电未初始化时就开始疯狂的发乱码 , 等初始化完成之后就不发了 。如图


解决方法:我是看的官方的例程 , 如果需要更新再初始化串口 , 如果不需要更新的话就不初始化串口 。所以把串口初始化部分写在了后面的判断中 。。。这样操作会出现上述问题 。把串口的初始化部分写到main函数的前端就不会出现这个问题了 。。至于具体为什么会这样的原因还没搞明白 。。。
经过询问大神们说不初始化的时候会有浮空电平 , 有时出现乱发一些数据也正常 。。。。


5 , 我在写iap升级的时候 , 使用的是一次性全部接收完70K的bin文件 , 再去升级 。。后期程序越写越多 , 最后编译完的bin文件大于了70K导致升级不能成功 。前面的$HEAD命令能接收 , 发完bin文件后$TAIL命令接收不到 。。。。。这是由于bin文件的大小超过了70k大小的buff后面的内容无法接收了 。。。。。。。。。。。。。正规的升级应该接收10k或者多少就编程一次 。。。。。。。。




二 , FLASH问题
1,flash的擦除
实际上是把flash的内容全部写1(擦除完再读的话读出来的全是0XFF) , flash的编程要按字(32位)或半字(16位)编程 , 当接收的数据是奇数位是要补上0 , 凑够半字来编程 。
2 , 写进flash跟读出来的不一样
注意编程flash时变量的存储接收等要用unsigned类型的 。存储接收的变量类型要一致 。以免造成越界问题 , 导致看到的数不一致


3 , flash做存储用时
当时写了个程序 , 用flash来存数据 , 然后再读出来 , 遇到的问题是设备不断电时可以完整的读出来 , 设备断电后读不出了 。要读多少个数我是把个数也存储在flash中的 。最终发现问题是程序中一个标志位的操作有问题 , 每次断电后再上电会自动把这个个数写为0 , 导致每次都读不出来数




【STM32IAP升级-----编写IAP升级遇到的问题总结】三 , 数组越界问题
1 , 嵌入式程序通常要求少占内存 , 通常变量能定义8位不定义16位 。。一定要注意变量的最大值 。(细心一点) 。。在越界问题上 , 吃亏了好几次了 。。。。
eg:① , 我定义了一个int16_t的变量来接收flash中的一个变量值0xABCD 。。结果很显然越界了 。。换成uint16_t即可
② , 定义了一个串口接收数据计数器uint16_t 的变量 , 要接收60k的APP程序 , 自认为足够用了 , 但是串口发送60K大小的文件发送的字节数大于了65535 ,  ,  , 又耽误了好久时间 。。。
谨记:要细心




四 , 关于APP与IAP互跳之间的中断处理问题

跳转时中断问题还是一个比较棘手的问题 。。经常跳转之后无法进入中断 , 然后百度了一下 , 自己理解大概是 , 跳转时只是强制改变了PC指正的位置 , 但是里面的中断寄存器什么的都没有变 , 这样中断存在 , 但是中断函数什么的都没有了 , 造成程序死掉 。。我在写的过程中也遇到了问题 , 第一次从iap跳到app正常 , 但是从app跳回iap的时候由于残留的中断太多 , 在iap中程序死了 。我的处理方式是把app中的跳转命令换成了系统复位NVIC_SystemReset();(不同的固件库可能函数名不同)其他的处理理的方式据我所知还有有①跳转之前复位或者关闭所有打开的中断②跳转后在初始化时加入RCC_DeInit(); ,  , NVIC_DeInit();等让中断恢复默认值 。。具体可参考下面这篇文章http://dzdesigned80.blog.163.com/blog/static/203259238201272425313152/总之要注意中断寄存器的复位 。也可以直接软件复位管他什么中断寄存器残留的.从iap跳到app前可以用USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);来关闭串口接收中断 。从app跳转回iap可以用软件复位 。




五 , 总结一下在IAP升级中APP程序的中断向量表的偏移


1.关于APP程序的中断向量表地址偏移(三种方法 , stm32F2与F4系列通用 。三种方法本质一样只是看到网上的各种例程的表现形式不一样)
①直接操作寄存器
在APP程序的main函数的开头设置中断向量表偏移
SCB->VTOR = FLASH_BASE | 0x10000;

其中0x10000是偏移量 。。也就是前面的IAP程序所占用的空间大小 , 要是你的main函数中有SystemInit();的话要在SystemInit();之后添加 。
因为SystemInit();中有中断向量表的偏移操作
在void SystemInit (void)系统初始化函数中有初始化中断向量表的语句
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* 使用内部SRAM启动设置这一句. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* 使用内部FLASH启动设置这句*/
#endif
可以直接修改VECT_TAB_OFFSE的值 , 这个值代表偏移量 。不建议这么改 , 不建议修改库文件 , 应为后面其他程序用的话经常忘了这里动过中断向量表 , 导致中断不能正常运行(我就因为这个浪费了快一天时间 , 串口就是进不了中断)
其中
#define FLASH_BASE ((uint32_t)0x08000000) /*! #define SRAM_BASE ((uint32_t)0x20000000) /*!< SRAM baseaddress in the alias region */
对应keil设置中的(这是一般程序默认的 , IAP升级中APP程序的这个地方还得根据中断偏移量改)






② 使用库函数设置偏移量
在库文件中有专门的一个函数
在APP程序初始化时调用函数NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x10000);
其中/* Vector Table Base----------------------------------*/
#define NVIC_VectTab_RAM ((u32)0x20000000)
#define NVIC_VectTab_FLASH ((u32)0x08000000)

/***********************************************************************
Function Name : NVIC_SetVectorTable
* Description : Sets the vector table location andOffset.
* Input : - NVIC_VectTab: specifies if thevector table is in RAM or
* FLASH memory.
**********************************************************************/
void NVIC_SetVectorTable(u32NVIC_VectTab, u32 Offset)
{
/* Check the parameters */
assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
assert_param(IS_NVIC_OFFSET(Offset));
SCB->VTOR = NVIC_VectTab " (Offset & (u32)0x1FFFFF80);
}


③修改库文件(不建议使用)
直接修改固件库里面的数值 。在void SystemInit(void)下的
/* Configure the Vector Table location add offsetaddress ------------------*/
#ifdefVECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;/* Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;/* Internal FLASH */
#endif
直接修改
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
This valuemust be a multiple of 0x200. */

#define VECT_TAB_OFFSET 0x10000 /*!< Vector Table base offsetfield.
This valuemust be a multiple of 0x200. */


2.关于IAP程序与APP程序keil中的设置
Stm32的flash都是从0x8000000开始的 , 结束地址看片子的flash大小
Stm32的sram都是从0x2000000开始的 , 结束地址看片子的sram大小

    推荐阅读