IAP升级功能编写初期的一些困惑与疑问---完成功能后的总结

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) 的一个别名;例如:

[cpp] view
plain
copy

  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 中的启动代码,更容易理解

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

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

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

网上很多人说跳转之后无法进入中断,然后百度了一下中断处理问题,反正没看明白,搞得自己也莫名的恐慌。。最后没搞明白,写完程序没处理中断问题,也照常运行自如(可能我的只是凑巧)我建议先不用管中断屏蔽的问题,先把逻辑写好,实际测试中再来处理中断问题,不要被中断问题吓到。处理的方式据我所知有①跳转之前关中断,避免跳转过程中受影响②跳转后在初始化时加入RCC_DeInit();,,NVIC_DeInit ();等让中断恢复默认值。。具体可参考下面这篇文章http://dzdesigned80.blog.163.com/blog/static/203259238201272425313152/

IAP升级功能编写初期的一些困惑与疑问---完成功能后的总结

时间: 2024-09-30 05:49:31

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

编写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..当两端电平不一致时通常是收不到数据的..当检测程序等都没有问题但是

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

刚接触ROS,学着写了第一个程序,怕以后忘记,就将其步骤记录下来.. 首先你必须保证你电脑已安装配置好ROS. 1.创建工作空间(workspace) 我们所创建功能包package,应该全部放到一个叫做工作空间(workspace)的目录中 .你可以把目录存储在你账号的任何位置例如,我所创建的工作空间的是路径/home,同时你可以用任何你喜欢的名字命名你的工作空间,我的工作空间名为 test,现在请使用标准的mkdir命令行去创建一个工作空间.我首先建立一个工作空间,名字为test, 此处创建

怎么写stm8的IAP升级的bootloader和app

因为之前写个stm32的IAP升级程序,所以我总结了做IAP升级的三个主要的难点: 1.如何设置中断向量,也就是说中断向量的重定向 2.如何配置程序的起始地址 3.如何从IAP跳转到APP程序 4.使用库函数要注意的地方(防止被坑) 说文章的时候我已经完成了一个最简单的IAP升级程序,可以通过串口接收bin文件写入到flash里面,然后再运行. 1.如何设置中断向量,也就是说中断向量的重定向 stm8不像stm32那样有个一寄存器管理着中断向量的地址,所以stm32的中断可以任意设置(符合要求的

Eclipse自动补全功能和自动生成作者、日期注释等功能设置

以前想实现添加代码作者信息的东西,但不知道怎样实现,今天终于在网上无意中找到解决办法了 Eclipse自动生成作者.日期注释等功能设置 在使用Eclipse 编写Java代码时,自动生成的注释信息都是按照预先设置好的格式生成的. 修改作者.日期注释格式:打开Windows->Preferences->Java->Code Style->Code Templates,点击右边窗口中的Comments,可以看到有很多选项,我们便可对此注释信息模板进行编辑. 如我们希望在一个Java文件

已知s.txt文件中有一个这样的字符串 请编写程序读取数据内容,把数据排序后写入 ss.txt文件

package cn.idcast5; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; /* * 需求:已知s.txt文件中有一个这样

Windows Azure 功能再扩充-SQL Database开始支持导入导出功能

本文将介绍 SQL Database 新增的导入导出功能,帮助您可以透过数据层应用程序把数据库导入到 SQL Database,或是将 SQL Database 导出至 Cloud Storage. [背景说明] 在 Facebook 上看到 Eric Shangkuan 分享 ScottGu 发表的文章,文中提到 Windows Azure Platform Management Portal 的再次扩充许多新功能,其中包含下列功能: Service Bus Management and Mo

为营造良好的论坛环境,应上线客户运营需要,短说OSX的敏感词功能正式上线了。 目前是敏感词功能第一

为营造良好的论坛环境,应上线客户运营需要,短说社区论坛系统的敏感词功能正式上线了. 目前是敏感词功能第一个版本,主要是替换,简单来说就是将相关敏感词在后台上传,用户在前后台进行发帖.更改昵称等行为时,若触发敏感词,则对该敏感词进行*替换. 短说社区论坛系统@凡科快图.png 下面详细介绍敏感词功能使用办法. 管理后台添加敏感词有两种方式,第一种是逐个添加,如下图. 管理后台-敏感词-敏感词列表-添加 添加完之后,就会出现在敏感词列表中,管理员可以对敏感词进行编辑和删除. 第二种是批量上传 管理后

IAP升级

一.原理 1.在正常情况下,程序运行路流程: 和STM32类似,STM8内部闪存(FLASH)地址起始于 0x8000(STM32是0x08000000),一般情况下,程序文件就从此地 址开始写入,通过一张"中断向量表" 来响应中断,程序启动后,将首先从"中断向量表"取出复位中断向量,执行复位中断程序完成启动,而这张"中断向量表"的起始地址是 0x8000(STM32是0x08000004),当中断来临,STM32 的内部硬件机 制亦会自动将 P

编写装饰器实现python请求错误重试功能

在做接口自动化测试的时候,总会遇到,因连接超时等错误导致,接口脚本失败. 官方给出的方法: max_retries=5 出错重试5次注意的是,这个只对DNS,连接错误进行重试. from requests.adapters import HTTPAdapter s = requests.Session() s.mount('http://',HTTPAdapter(max_retries=5)) s.mount('https://',HTTPAdapter(max_retries=5)) s.g