关于IAP与APP互相跳转的实现

首先,在您动手做这个实验之前,先要弄清除咱俩的软硬件有什么不同:

1. 我的CPU是STM32F103ZET6,里面有512K的FLASH,您的CPU如果是其它类型,也不要紧,只是在程序里面,地址上限可能不一样。但是,个人觉得,最好能用256K以下的FLASH。

2. 我的外部存储介质是U盘,如果您的外部存储介质是SD卡,那也应该一样用,只是它们必须是FAT16,FAT32文件系统。如果您的板上没有外部存储介质,那也能做跳转实验,只是不能做加载APP实验。

3. 我的仿真器是JLINK7,如果您的仿真器是其它的,估计也没多大问题,只要您会用它就行了。什么?没有仿真器,那还是别做这个实验吧,出错了没法调试。

4. 我的开发环境是RVMDK 3。7,STM库是V2。03。使用其它开发环境的话,您要是能找到MDK中的设置对应到您那里怎么设置,估计也没问题。至于库嘛,您现在是用哪个就哪个吧,全部包在您的工程里,没问题的。

好了,开始啦。

先找个你以前调好的工程,当然,最好是非常可靠的,内容很精彩的,带液晶显示的,这样比较容易知道你后面有没有调好。这个工程还最好是在FLASH里面运行的,如果不是,要将它改回来。

至于什么开发文档,太麻烦了,不用看。我之前看了STM的IAP应用笔记AN2557,就觉得一个字“乱”,特别是心里还没谱的时候,更是越看越糊涂,这么大个工程,到最后对我有帮助的,就是一小段,就是如何擦除,如何编程那小段。当然,STM32的库还是非常有用的,如果不用库的话,学习、工作进度会慢很多。

说多啦,找好工程没有?找好工程咱就开工了。将这个工程复制两份,一份命名为IAP,一份命名为APP。

第一步:规划好你两个程序的存放位置。

IAP程序肯定是从0X08000000开始的,因为它是引导程序。将IAP程序放在0X08000000-0X0800FFFF的位置,给它64K空间,足够了。

APP程序从0X08010000-0X0807FFFF,给它448K空间。

如果您的CPU不同,那APP程序的空间小一点,也没问题。

第二步:制作你的APP程序。

1. 将程序定位在0X08010000开始的位置。

点魔术棒,打开目标选项设置。

选Target选项卡,IROM1改成从0X08010000开始,尺寸0X00070000;

Debug选项卡,Load Application at Startup打上勾,Run to main()打上勾;

Utilitiles选项卡,点settings按纽,弹出Flash download卡,Erase sectors打上勾,点你的编程算法,将底下的的起始地址改成0X08010000,尺寸0X00070000。

2. 制作一个RunInFlashOffset.ini文件。文件内容为:

SP = _RDWORD(0x08010000); // Setup Stack Pointer

PC = _RDWORD(0x08010004); // Setup Program Counter

目的是在用JLINK调试的时候,引导程序运行。

点魔术棒,打开目标选项设置。

选Debug选项卡,Initialization File:项,选择上面的RunInFlashOffset.ini。

3. 为了从IAP程序跳来运行APP的时候正常开始,初始化时要恢复RCC为复位状态,恢复NVIC为复位状态。

在你的RCC初始化部分,第一句加上:

RCC_DeInit();

在你的NVIC初始化部分,第一句加上:

NVIC_DeInit ();

4. 重定位中断表到0X08010000位置。

在上面NVIC_DeInit ();后面加上:

NVIC_SetVectorTable (NVIC_VectTab_FLASH, 0x00010000);

如果原来有其它的定位语句,将它删掉。

5. 编写跳转IAP函数:

/**************************************************************************************************

函数: 运行IAP程序.

输入: 无

返回: 无.不再返回.

说明: 由于APP是在IAP的基础上运行的,因此,IAP一定是有效的,这里不再作IAP有效性检查.

**************************************************************************************************/

#define IAP_ADDR 0X08000000

void IapProgramRun(void)

{

INT32U IapSpInitVal; //IAP程序的SP初值.

INT32U IapJumpAddr; //IAP程序的跳转地址.即,IAP程序的入口.

void (*pIapFun)(void); //定义一个函数指针.用于指向APP程序入口.

NVIC_DeInit (); //恢复NVIC为复位状态.使中断不再发生.

IapSpInitVal = *(INT32U *)IAP_ADDR; //取APP的SP初值.

IapJumpAddr = *(INT32U *)(IAP_ADDR + 4); //取程序入口.

__MSR_MSP (IapSpInitVal); //设置SP.

pIapFun = (void (*)(void))IapJumpAddr; //生成跳转函数.

(*pIapFun) (); //跳转.不再返回.

}

6. 编写在一定条件下跳转IAP的部分。比如按下某个键,就跳到IAP去。

完成上述几步后,编译调试,用JLINK调试,可以直接运行的,跟你原来的工程应该没区别。有问题的话,将它解决。

第三步:制作您的IAP程序。

1. 将程序定位在0X08000000开始的位置。如果您的程序本来就是在这个位置的,不用改了。

点魔术棒,打开目标选项设置。

选Target选项卡,IROM1改成从0X08000000开始,尺寸0X00010000;

Debug选项卡,Load Application at Startup打上勾,Run to main()打上勾;

Utilitiles选项卡,点settings按纽,弹出Flash download卡,Erase sectors打上勾,点你的编程算法,将底下的的起始地址改成0X08000000,尺寸0X00010000。

2. 为了从APP程序跳回来运行IAP的时候正常开始,初始化时要恢复RCC为复位状态,恢复NVIC为复位状态。

在你的RCC初始化部分,第一句加上:

RCC_DeInit();

在你的NVIC初始化部分,第一句加上:

NVIC_DeInit ();

3. 重定位中断表到0X08000000位置。

在上面NVIC_DeInit ();后面加上:

NVIC_SetVectorTable (NVIC_VectTab_FLASH, 0x0);

如果原来有其它的定位语句,将它删掉。

4. 编写在一定条件下跳转APP的部分。比如按下某个键,就跳到APP去。

5. 编写跳转APP函数:

#define APP_ADDR 0X08010000

OP_RESULT AppProgramRun(void)

{

INT32U AppSpInitVal; //App程序的SP初值.

INT32U AppJumpAddr; //APP程序的跳转地址.即,APP程序的入口.

void (*pAppFun)(void); //定义一个函数指针.用于指向APP程序入口.

AppSpInitVal = *(INT32U *)APP_ADDR; //取APP的SP初值.

if (AppSpInitVal & 0XFFFF 0000 != 0X20 00 00 00) //APP未写入.不能跳.

{

FaceEnterDialog (&OpFailDialog);

return OP_FAIL;

}

AppJumpAddr = *(INT32U *)(APP_ADDR + 4); //取程序入口.

if ((AppJumpAddr & 0X FF F8 00 00) != 0X 08 00 00 00) //APP无效.不能跳.

{

FaceEnterDialog (&OpFailDialog);

return OP_FAIL;

}

NVIC_DeInit (); //恢复NVIC为复位状态.使中断不再发生.

__MSR_MSP (AppSpInitVal); //设置SP.

pAppFun = (void (*)(void))AppJumpAddr; //生成跳转函数.

(*pAppFun) (); //跳转.不再返回.

return OP_SUCCESS;

}

完成上述几步后,编译调试,OK。

第四步:双程序调试:

1. 用仿真器运行IAP程序,然后按下按键,转到APP去。如果你正常转到APP,说明成功。不能的话,用仿真器跟一下,把问题解决。

2. 用仿真器运行APP程序,然后按下按键,转到IAP去。如果你正常转到IAP,说明成功。不能的话,用仿真器跟一下,把问题解决。

3. 用仿真器运行IAP程序,然后按下按键,转到APP。

在APP中又按下按键,转回IAP。如此反复。

可以在IAP第一句设个断点,每次转回来的时候,都应该会停在那里的。

注意:在跳到另一个程序中运行的时候,要停止不能直接点“停止调试按纽”,就是那个放大镜一样的按纽,否则MDK立马出错退出。要停止的话,要先打开反汇编观察窗口,然后按下“停止”按纽,就是左上角红圆圈里一把叉那个,

再按下“停止调试按纽”。

第五步:在IAP中加载APP。

如果你的板子上没有USB,或都SD卡,这后面的就做不了了。

1. 改IAP程序,加上加载APP程序功能。就是按下某个键时,从U盘读取APP程序,并把它写到FLASH中。这个参考附件。

2. 在APP程序中,选择输出HEX文件。目前来说,HEX文件是比较方便处理的文件。

点魔术棒,打开目标选项设置。

选Output选项卡,Create HEX File打上勾。

编译,生成HEX文件。

3. 把APP。HEX拷到U盘中,然后用IAP程序加载。

第六步:让IAP区分是复位运行,还是从APP转过来运行的。

打开你的启动文件(我这里是stm32f10x_vector.s),看一下它里面栈空间是多大,堆空间是多大。在IAP程序主函数第一句设个断点,记下此时的SP值,一般这个值比 栈+堆+全局变量还要大一些。在这个值+8之上的内部RAM空间,是程序用不上的。所以可以让APP程序在RAM空间的顶端设置一个标志,然I后让AP程序去根据这个标志来区别复位运行、从APP转过来的运行。

区分IAP的运行方式有一个特殊的用途,那就是从APP程序中,跳转IAP程序,来更新APP程序。这是真正的在线升级。

最后,我总结一下,要做IAP和APP间的互相跳转,要注间以下几点:

1. APP程序是放在FLASH的中间位置运行的,所以在编译、下载、调试时,都要指定它的入口(本例是0X08010000)。具体实现就是在魔术棒中的设置。

2. 程序可以是从另外一个程序转来的,而另外一个程序的RCC,NVIC设置不可知,所以必须在初始化时,恢复RCC,NVIC为复位状态,并且设置正确的NVIC向量表。

3. 在要跳到别的程序之前,要恢复NVIC为复位状态,防止在跳转过程中出现中断。

4. 如果IAP要判断是复位开始运行的,还是从APP跳转过来的,应该用程序启动部分不会被改变的内存、外存存储一个标志,用它来判定从哪跳来的。

【转】关于IAP与APP互相跳转的实现的更多相关文章

  1. 关于STM32的IAP与APP互相跳转

    关于STM32的IAP与APP互相跳转 之前做了一个不带系统的IAP与APP互相跳转,在网上找了资料后,很顺畅就完成了,后来在IAR集成开发环境下,IAP无系统,APP用UCOS系统做互相跳转出现了很 ...

  2. ios&h5混合开发项目仿app页面跳转优化

    前言:本人原本是ios开发工程师,但由于现今H5的兴起,行内刮起了一阵混合开发的风气,趁着这股劲,我也学了前端开发,不说研究的多深,但也能胜任日常的开发工作.长话短说,现今的混合开发应该还处于摸索阶段 ...

  3. H5调取APP或跳转至下载

    来源: 最近在配合移动端做几个详情页h5分享页面,需要调取App并跳转至app详情页, 如果没有安装App,需要判断引导至下载页面. 参考文档: https://juejin.im/post/5b7e ...

  4. 通过手机浏览器打开APP或者跳转到下载页面.md

    目录 通过手机浏览器打开APP或者跳转到下载页面 添加 schemes 网页设置 参考链接 通过手机浏览器打开APP或者跳转到下载页面 以下仅展示最简单的例子及关键代码 由于硬件条件有限,仅测试了 A ...

  5. ios两个app之间跳转,传值的实现

    两个APP之间的跳转是通过[[UIApplication sharedApplication] openURL:url]这种方式来实现的. 1.首先设置第一个APP的url地址 2.接着设置第二个AP ...

  6. Vue仿微信app页面跳转动画

    10:14:11独立开发者在开发移动端产品时,为了更高效,通常会使用Web技术来开发移动端项目,可以同时适配Android.iOS.H5,稍加改动还可适配微信小程序. 在使用Vue.js开发移动端页面 ...

  7. app使用微信支付成功后,点击返回到该app却跳到另外一个app去了

    刚接手了公司iOS的两个APP, 现在碰到了这样一个问题: 有一台iPhone在一个APP中使用了微信支付,支付成功后,点击返回到该APP,结果却跳到了另外一个APP去了. 这两个APP都是公司开发的 ...

  8. iOS App之间跳转

    1.先来看看效果,这里做了三个功能 从MyApp跳转到YourApp 从MyApp跳转到YourApp的指定页面 从YourApp使用跳转url的方式跳回MyApp 2.实现app之间的跳转需要注意两 ...

  9. 3D touch 静态、动态设置及进入APP的跳转方式

    申明Quick Action有两种方式:静态和动态 静态是在info.plist文件中申明,动态则是在代码中注册,系统支持两者同时存在. -系统限制每个app最多显示4个快捷图标,包括静态和动态 静态 ...

随机推荐

  1. React Native小知识点记录

    1>查看 RN 的所有历史版本: npm view react-native versions -json 2>查看 RN 的当前版本: npm view react-native ver ...

  2. 数位dp作业

    dp东西实在太多,昨天开了个树形dp入门,还没入呢,今天就要写数位dp,也不知道这种学习状态对不对啊? A - 不要62 题意: 输入n到m内,符合条件的数的个数.条件:不含62和4. 这里直接学习q ...

  3. 导入现有java工程

    1)错误:点击File-->open File 这样只能导入单个文件: 2)正确:File-->Import--> 然后下一步下一步即可.

  4. vue中如何编写可复用的组件?

    原文地址 Vue.js 是一套构建用户界面的渐进式框架.我们可以使用简单的 API 来实现响应式的数据绑定和组合的视图组件. 从维护视图到维护数据,Vue.js 让我们快速地开发应用.但随着业务代码日 ...

  5. Y2K Accounting Bug POJ2586

    Description Accounting for Computer Machinists (ACM) has sufferred from the Y2K bug and lost some vi ...

  6. PTA(Advanced Level)1025.PAT Ranking

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  7. JZOJ.1150【贪心算法】IQ

    欢迎转载,请附上原链接https://www.cnblogs.com/Code-Garden/p/11276741.html(也没人会看) 一道对我来说较难的贪心题 题目描述 根据世界某权威学会的一项 ...

  8. STL stack 常见用法详解

    <算法笔记>学习笔记 stack 常见用法详解 stack翻译为栈,是STL中实现的一个后进先出的容器.' 1.stack的定义 //要使用stack,应先添加头文件#include &l ...

  9. 老贾的幸福生活day3 之markdown常用语法简要

    1.markdown常用语法 标题 一级到六级 用#+空格实现 2.代码块 3个 `实现 python is a ...... 单行代码,用"``" 3.列表 有序列表 跟内容 数 ...

  10. python-day7(正式学习)

    目录 数字类型内置方法 整形内置方法(int) 常用操作+内置方法 是否可变 浮点型内置方法(float) 常用操作+内置方法 是否可变 字符串内置方法 常用操作+内置方法 是否可变 数字类型内置方法 ...