zoukankan      html  css  js  c++  java
  • 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_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大小的片子。。详细的大小设置,看自己的片子。。



  • 相关阅读:
    7
    go http请求库HttpRequest
    Golang设计模式
    深挖 go 之 for-range 排坑指南
    go在并发情况下使用map
    Redis知识点总结
    go 条件与循环结构
    数据分析的数据源
    go 生产者消费者模型与发布订阅模型
    go 文件与目录操作
  • 原文地址:https://www.cnblogs.com/llguanli/p/8443144.html
Copyright © 2011-2022 走看看