当前位置:首页 > 公众号精选 > 漫长当下

既然你想了解这方面的内容,便默认你已经知道为什么需要IAP程序,IAP程序有哪些好处,下面进入正题。

首先整个工程分为两个小工程,也就是所说的IAP和APP,IAP程序负责完成APP程序的接收和固化,APP程序负责完成想要实现的功能,图1是从前面提到的网站内下载的一份文档中截取的。

图1

从图1可以看到芯片的flash被分成了四个区域(当然实际上并不止这些),从下往上看,flash起始地址放的是向量表和IAP程序,接着放的是向量表和APP程序,平时我们都是一个程序然后下载到flash起始地址,这个地址是已经设计好的,芯片执行完内部出厂程序后,就会跳转到这个地址执行用户写的程序,所以IAP程序一定是下载到这个地址。

来看下IAP程序实现跳转到APP程序的关键代码,其中每行都已经详细注释,就不再进行讲解:

#define APPLICATION_ADDRESS (uint32_t)0x08004000
typedef  void (*pFunction)(void);

pFunction JumpToApplication;
uint32_t JumpAddress;

/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
/*
* 检测栈顶指针是否落在合法的区域,这里因为芯片RAM大小为128K,所以合法地址是:
* 0x20000000-0x2001ffff,0x2FFE0000值需要根据自己芯片的实际RAM大小进行调整
*/

if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
    /* Jump to user application */
    /*
    * APPLICATION_ADDRESS地址为APP程序存放的地址,+4是因为向量表中复位向量
    * 的位置排在第二,程序跳转后是先执行复位
    */

    JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
    /*
    * 将跳转地址强制转换成函数类型
    */

    JumpToApplication = (pFunction) JumpAddress;
    /* Initialize user application's Stack Pointer */
    /*
    * 设置栈顶指针,栈顶指针排在向量表第一
    */

    __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
    /*
    * 将前面转换后的地址当成函数进行调用,便跳转到了APP程序
    * 其原理就好比你知道你有个函数下载在flash的哪个地址,你
    * 可以直接使用这个地址去调用那个函数
    */

    JumpToApplication();
}

现在IAP程序就已经大功告成了,只是有一些需要注意的点,如果你的IAP程序还有一些其它功能,比如使用了某些外设并且开启了中断,在跳转之前一定记得先关闭这些中断,否则的话偶尔可能出现跳转失败的情况。

下面看下APP程序需要完成哪些操作,以Keil MDK为例,首先需要修改程序在ROM中的起始地址,这个起始地址必须和你IAP程序中的跳转地址(APPLICATION_ADDRESS)一致(注意这里我没有修改,你应该根据你的设置改为正确的地址),否则IAP程序跳转到这里后发现没有程序可以执行,那么直接就挂掉了,具体修改步骤见图2。

图2

第一步完成了,我们打开system_stm32f1xx.c(这里如果是其它系列只是stm32f后面的数字不一样)文件,修改图3中的值即可,这一步操作是为了重定向向量表,以便告知中断控制器不要到之前的向量表(也就是IAP那一份)中去找了,要在新指定的地方去找,不然程序产生中断后没响应。

图3

至此一个完成的IAP加APP工程就完成了,将两个程序下载到芯片flash中,就可以实现从IAP程序跳转到APP了,因为要下载两个hex文件到芯片中,前面的文章(STM32HEX合并及一键烧写)就可以起到作用了,帮助你一键下载多个hex。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭