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_M 25.。
。
。
库函数默认的是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,导致每次都读不出来数
三。数组越界问题
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) /*!<FLASH base address in the alias region */
#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大小
IAP程序基本默认就可以,跟普通程序一样
在APP程序中须要设置一下偏移量
默认的条件下,图中IROM1的起始地址(Start)一般为0X08000000,大小(Size)为0X100000。即从0X08000000開始的1M空间为我们的程序存储(由于我们的STM32F4的FLASH大小是1M)。而图中,我们设置起始地址(Start)为0X08010000,即偏移量为0X10000(64K字节)。因而。留给APP用的FLASH空间(Size)仅仅有0X100000-0X10000=0XF0000(960K字节)大小了。设置好Start和Szie,就完毕APP程序的起始地址设置。
这里的64K字节。须要大家依据Bootloader程序大小进行选择,比方我们本章的Bootloader程序为22K左右,理论上我们仅仅须要确保APP起始地址在Bootloader之后,并且偏移量为0X200的倍数就可以(相关知识,请參考:http://www.openedv.com/posts/list/392.htm)。这里我们选择64K(0X10000)字节,留了一些余量。方便Bootloader以后的升级改动。
注意:设置的起始地址要与程序中设置的中断向量表的偏移量相应起来(假设给IAP程序64k的空间则APPkeil中起始地址为0x8010000相应的程序中中断向量偏移0x10000)我用的1M flash大小的片子。。详细的大小设置,看自己的片子。。