IAP的源代码等资料我上传了,压缩包内有12个文件,,http://download.csdn.net/detail/f907279313/7524849(要积分的辛苦收集的你们就给点积分吧)

还有还有一篇博客总结的IAP:http://blog.csdn.net/super_demo/article/details/32086541

一,网上下载的例程,跳转部分的代码有差异,尤其是用的汇编那句

eg:

①Jump_To_Application  = (pFunction)(*(vu32*) (IAPSTART + 4));

__MSR_MSP(*(vu32*) IAPSTART);

Jump_To_Application();

跟踪__MSR_MSP(一般这个函数都在库文件中有,跟踪不到就用搜索找)找到汇编函数为

__MSR_MSP 

 

    MSR MSP, r0 ; set Main Stack value

    BX r14

②//跳转到应用程序段

//appxaddr:用户代码起始地址.

void iap_load_app(u32 appxaddr)

{

if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)//检查栈顶地址是否合法.



jump2app=(iapfun)*(vu32*)(appxaddr+4);//用户代码区第二个字为程序開始地址(复位地址)

MSR_MSP(*(vu32*)appxaddr);//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)

jump2app();
//跳转到APP.

}

}

跟踪MSR_MSP找到函数为

//设置栈顶地址

//addr:栈顶地址

__asm void MSR_MSP(u32 addr) 

{

    MSR MSP, r0
//set Main Stack value

    BX r14

}

③  //推断用户是否已经下载程序,由于正常情况下此地址是栈地址。

        //若没有这一句的话,即使没有下载程序也会进入而导致跑飞。

        if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)

        {

            SerialPutString("Execute user Program\r\n\n");

            //跳转至用户代码

            JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);

            Jump_To_Application = (pFunction) JumpAddress;





            //初始化用户程序的堆栈指针

            __set_MSP(*(__IO uint32_t*) ApplicationAddress);

            Jump_To_Application();

        }

跟踪__set_MSP找到函数为

__ASM void __set_MSP(uint32_t mainStackPointer)

{

  msr msp, r0

  bx lr

}

总结以上发现都是操作ARM的R0跟R14(LR)寄存器。

另一种不太一样的,就是stm32F4的库函数中的跳转,例如以下所看到的

④ //測试用户app地址是不是在APPLICATION_ADDRESS位置。检測栈顶的地址,来检验app是否下载成功

    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)

    { 

    //APPLICATION_ADDRESS + 4相应的是app中断向量表的第二项,复位地址

    JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);

//把地址强转为函数指针

    Jump_To_Application = (pFunction) JumpAddress;

    //设置主函数栈指针

    __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);

//调用函数,实际失去app复位地址去运行复位操作

    Jump_To_Application();

    }

跟踪__set_MSP找到函数为

static __INLINE void __set_MSP(uint32_t topOfMainStack)

{

  register uint32_t __regMainStackPointer     __ASM("msp");

  __regMainStackPointer = topOfMainStack;

}

对于M4的这个库函数我也不太懂,感觉终于的操作应该跟其它的一样吧

二,关于跳转部分的代码的理解(转)

这里重点说一下几句经典且很重要的代码:

第一句: if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)   //推断栈定地址值是否在0x2000 0000 - 0x 2000 2000之间

怎么理解呢? (1),在程序里#define ApplicationAddress    0x8003000 ,*(__IO uint32_t*)ApplicationAddress)  即取0x8003000開始到0x8003003 的4个字节的值, 由于我们的应用程序APP中设置把 中断向量表 放置在0x08003000 開始的位置;而中断向量表里第一个放的就是栈顶地址的值

也就是说,这句话即通过推断栈顶地址值是否正确(是否在0x2000 0000 - 0x 2000 2000之间) 来推断是否应用程序已经下载了,由于应用程序的启动文件刚開始就去初始化化栈空间,假设栈顶值对了,说应用程已经下载了启动文件的初始化也运行了;

第二句:    JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);   [  common.c文件第18行定义了:  pFunction   Jump_To_Application;]

                      

ApplicationAddress + 4  即为0x0800 3004 ,里面放的是中断向量表的第二项“复位地址”  JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); 之后此时JumpAddress

第三句:    Jump_To_Application = (pFunction) JumpAddress;

 startup_stm32f10x_md_lv. 文件里别名  typedef  void
(*pFunction)(void);     这个看上去有点奇怪;正常第一个整型变量   typedef  int  a;  就是给整型定义一个别名 a

void (*pFunction)(void);   是声明一个函数指针,加上一个typedef 之后  pFunction仅仅只是是类型 void (*)(void) 的一个别名;比如:

  1. pFunction   a1,a2,a3;
  2. void  fun(void)
  3. {
  4. ......
  5. }
  6. a1 = fun;

所以,Jump_To_Application = (pFunction) JumpAddress;  此时Jump_To_Application指向了复位函数所在的地址;

第四 、五句: __set_MSP(*(__IO uint32_t*) ApplicationAddress);      \\设置主函数栈指针

               Jump_To_Application();                         \\运行复位函数

Jump_To_Application()是把用户代码的复位地址付给PC指针,我看到Jump_To_Application()这句代码debug的时候相应的汇编代码是

LDR
r0,[pc,#12] ;相对PC的数据载入,去函数指针的地址

LDR r0,[r0,#00] ;R0做索引,无偏移,数据装载到R0,这个内容就是函数指针指向的内容,也就是函数的地址了,用户程序的起始地址;

BLX r0              ;这个不解释,说了是跳转

我们看一下启动文件startup_stm32f10x_md_vl.s 中的启动代码,更easy理解

三,关于跳转时是否能不用按键,用软件标志位以及APP与IAP之间的互跳

全然能够不用按键,能够模拟一个按键信号,或者用软件的一个标志位来推断是否更新。。我设计的在flash中中存储一个值,当APP执行中须要更新时串口发来更新命令,然后在flash中存一个值之后跳到IAP部分,来读取flash中存储的那个值,假设是须要更新则更新,假设不是须要跟新标志位就直接跳转到APP部分。。。这样也不用反复上电,断电。

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

跳转时中断问题还是一个比較棘手的问题。。常常跳转之后无法进入中断,然后百度了一下,自己理解大概是,跳转时仅仅是强制改变了PC指正的位置,可是里面的中断寄存器什么的都没有变,这样中断存在,可是中断函数什么的都没有了,造成程序死掉。。我在写的过程中也遇到了问题,第一次从iap跳到app正常,可是从app跳回iap的时候因为残留的中断太多,在iap中程序死了。我的处理方式是把app中的跳转命令换成了系统复位NVIC_SystemReset();(不同的固件库可能函数名不同)其它的处理理的方式据我所知还有有①跳转之前复位或者关闭全部打开的中断②跳转后在初始化时添�RCC_DeInit();,,NVIC_DeInit ();等让中断恢复默认值。。详细可參考以下这篇文章http://dzdesigned80.blog.163.com/blog/static/203259238201272425313152/

关于stm32的软件复位:

STM32软件复位(基于库文件V3.5) ,对于STM32来说软件复位有两种方式:

1)採用官方自带的软件库  

    在官方软件库的 core_cm3.h 文件中 直接提供了 系统复位的函数

static __INLINE void NVIC_SystemReset(void)



SCB->AIRCR  = (
(0x5FA << SCB_AIRCR_VECTKEY_Pos)    |

(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk)   |

SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */ 

  __DSB();                                                                                       /* Ensure completion of memory access */               

  while(1);                                                                                        /* wait until reset */



  可是不是直接调用这个函数就OK了?    在Cortex-M3权威指南中有这么一句话:     

这里有一个要注意的问题:从SYSRESETREQ 被置为有效,到复位发生器运行复位命令,  往往会有一个延时。在此延时期间,处理器仍然能够响应中断请求。但我们的本意往往是要  让此次运行到此为止,不要再做不论什么其他事情了。所以,最好在发出复位请求前,先把  FAULTMASK 置位。  



  所以最好在将FAULTMASK 置位才万无一失。    相同官方 core_cm3.h 文件中也直接提供了该函数  

  static __INLINE void __set_FAULTMASK(uint32_t faultMask)

{

register uint32_t __regFaultMask       __ASM("faultmask");

__regFaultMask = (faultMask & 1);



  把上面这两个函数写在一起就能够实现软件复位了~~

void SoftReset(void)



__set_FAULTMASK(1);      // 关闭全部中端

NVIC_SystemReset();// 复位



 /*------

IAP升级功能编写初期的一些困惑与疑问---完毕功能后的总结的更多相关文章

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

    IAP的源代码等资料我上传了,压缩包内有12个文件.,http://download.csdn.net/detail/f907279313/7524849(要积分的辛苦收集的你们就给点积分吧) 还有还 ...

  2. STM32 Bootloader基于ymodem传输协议串口IAP升级详解

    硬件:stm32f103cbt6 软件:STM32F10x_StdPeriph_Lib_V3.5.0 文章目录 1 预备知识 2 Bootloader 2.1 启动流程 2.2 校验跳转地址是否有效 ...

  3. (转)-编写第一个ROS(创建工作空间workspace和功能包package)

    原文网址:http://www.cnblogs.com/liuamin/p/5704281.html 刚接触ROS,学着写了第一个程序,怕以后忘记,就将其步骤记录下来.. 首先你必须保证你电脑已安装配 ...

  4. 编写第一个ROS(创建工作空间workspace和功能包package)

    刚接触ROS,学着写了第一个程序,怕以后忘记,就将其步骤记录下来.. 首先你必须保证你电脑已安装配置好ROS. 1.创建工作空间(workspace) 我们所创建功能包package,应该全部放到一个 ...

  5. sql server编写简洁四则运算表达式脚本实现计算批次功能(C#等其它编程语言也能直接用此通用表达式)

    问题: 在数据库编程开发中,有时会遇到数据量比较大的情况,如果直接大批量进行添加数据.修改数据.删除数据,就会是比较大的事务,事务日志也比较大,耗时久的话会对正常操作造成一定的阻塞.虽不至于达到删库跑 ...

  6. STM32 IAP 升级官方资料汇总

    整理了一下SMT32标准外设库进行IAP升级的官方demo: 标准库版本 STM32F10xxx in-application programming using the USART (AN2557) ...

  7. 在用easyui中做CRUD功能时,当删除一行或多行数据后再点击修改会提示你选中了多行,如何解决这个bug了?

    在用easyui中做CRUD功能时,当删除一行或多行数据后再点击修改会提示你选中了多行,如何解决这个bug了? 在删除成功后,加上这句话就可以了:$("#dg").datagrid ...

  8. 微信小程序仿朋友圈功能开发(发布、点赞、评论等功能)

    微信小程序仿朋友圈功能开发(发布.点赞.评论等功能) 1.项目分析 项目整体分为三个部分 发布 展示 详情页 graph LR 朋友圈发布 --内容发布--> 内容展示 内容展示 --点击展示卡 ...

  9. STM32 IAP 升级功能

    IAP In Application Programming 可通过USB,CAN,UART,I2C,SPI等接口实现 IAP流程 Bootloader程序:接收升级程序,更新到flash指定地址:跳 ...

随机推荐

  1. Rails 撤销操作

    即使再小心,在开发 Rails 应用程序过程中仍然可能犯错.幸运的是,Rails 提供了一些工具能够帮助你进行复原. 举例来说,一个常见的情况是,你想更改控制器的名字,这时你就要撤销生成的代码.生成控 ...

  2. 【原创翻译】The Case for the Reduced Instruction Set Computer

    RISC机的例子 David A. Patterson 加州大学伯克利分校计算机科学系 David R. Ditzel 贝尔实验室计算科学研究中心 介绍 计算机体系结构最主要的目标之一就是设计比之前产 ...

  3. 【DataStructure In Python】Python实现各种排序算法

    使用Python实现直接插入排序.希尔排序.简单选择排序.冒泡排序.快速排序.归并排序.基数排序. #! /usr/bin/env python # DataStructure Sort # Inse ...

  4. Android开发UI之自定义动画

    自定义动画,需要新建一个类,继承Animation类. 重写applyTransformation()方法和initialize()方法. applyTransformation(float inte ...

  5. WPF——控件之间的绑定

    一.启动窗口 二.控件绑定(注意看光标的位置,一个是单向绑定,一个是双向绑定) 注意看单向绑定与双向绑定的绑定方法:

  6. Java之 AtomicInteger

    AtomicInteger,一个提供原子操作的Integer的类.在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字.而AtomicIn ...

  7. 嵌入式开发软件环境:uboot、kernel、rootfs、data布局分析

    uboot+linux的整体方案 开发板的datasheet中都有详细的地址空间的划分,其中比较重要的两块是:DDR地址空间和Flash地址空间.DDR空间是系统和应用的运行空间,一般由linux系统 ...

  8. Servlet3.0学习总结(四)——使用注解标注监听器(Listener)

    Servlet3.0提供@WebListener注解将一个实现了特定监听器接口的类定义为监听器,这样我们在web应用中使用监听器时,也不再需要在web.xml文件中配置监听器的相关描述信息了. 下面我 ...

  9. 超大型 LED 显示屏

    http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11574&courseid=0 题目 E. 超大型 L ...

  10. 【JS】Beginner1:Making Stuff Happen

    1.JS(JavaScript) is for interactivity 2.How does JS relate to HTML&CSS? script tag script elemen ...