关于STM32的IAP与APP互相跳转

关于STM32的IAP与APP互相跳转

之前做了一个不带系统的IAP与APP互相跳转,在网上找了资料后,很顺畅就完成了,后来在IAR集成开发环境下,IAP无系统,APP用UCOS系统做互相跳转出现了很多问题。现将IAP学习过程和实际遇到问题总结一下。

首先说一下什么是IAP。IAP(In Application Programming)即在应用编程,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。通常实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信方式(如USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。

以上内容摘自原子的开发指南。说的通俗一点,要做IAP功能(也可以说成是远程升级功能),需要有两段程序一个是IAP程序(也可以称为BootLoader),另一个是APP程序(主应用程序)。通过USB、串口、CAN等通讯方式向STM32发送要升级的程序文件数据(按自定的协议),IAP程序中将接收到的数据写到APP程序的地址实现将APP程序的升级。这是大致的流程。

此文档只做互相跳转的总结不包含接收数据、FLASH写入等操作。

说到IAP升级不得不说两个图(图片引自原子的开发指南)

第一个是正常运行时的流程图

clip_image002

  STM32的FLASH地址起始于0x08000000,程序文件就从此地址开始写入。此外STM32内部通过“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动,而“中断向量表”的起始地址是0x08000004,当中断来临,STM32的内部硬件机制亦会自动将PC指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。

根据上图分析启动和运行过程,

① STM32在复位后,先从0X08000004地址取出复位中断向量的地址,并跳转到复位中断服务程序,

② 在复位中断服务程序执行完之后,会跳转到的main函数(如使用KEIL MDK调试时一下载进程序,会发现需要运行几次下一步才会跳转到main函数的位置)

③ main函数一般都是超循环体(while(1)死循环),在main函数执行过程中,如果收到中断请求(发生重中断),此时STM32强制将PC指针指回中断向量表处

④ 根据中断源进入相应的中断服务程序,

⑤ 在执行完中断服务程序以后,程序再次返回main函数执行。

第二个是加入IAP功能后的流程图

clip_image004

根据上图分析加入IAP后的起动和运行过程

① STM32复位后,还是从0X08000004地址取出复位中断向量的地址,并跳转到复位中断服务程序,在运行完复位中断服务程序之后跳转到IAP的main函数,如将IAP看作是一个APP的话,那么此部分和正常起动是一样的,此步相当于正常运行的①和②。

② 在执行完IAP以后(如需要将新的APP代码写入STM32的FLASH或没有更新直接跳转。APP的复位中断向量起始地址为0X08000004+N+M),跳转至APP的复位向量表

③ 取出APP的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至APP的main函数

④ 同样main函数为一个超循环,并且注意到此时STM32的FLASH,在不同位置上,共有两个中断向量表。在main函数执行过程中,如果CPU得到一个中断请求,PC指针仍强制跳转到地址0X08000004中断向量表处,而不是APP程序的中断向量表。

⑤ 程序再根据我们设置的中断向量表偏移量,跳转到对应中断源的APP中断服务程序中,

⑥ 在执行完中断服务程序后,程序返回main函数继续运行。

注意:IAP和APP跳转过程中,是通过PC指针定位进行跳转,所有的寄存器都保持原有状态,跳转过程中并不是做了复位。

下面是IAP和APP互相跳转程序

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

IAP 跳转到 APP 之间跳转函数

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

void IAP_APP_Jump (void)

{

INT32U SpInitVal; //要跳转到程序的SP初值.

INT32U JumpAddr; //要跳转到程序的地址.即,要跳转到程序的入口

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

RCC_DeInit(); //关闭外设

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

SpInitVal = *(INT32U *)IAP_ADDR;//IAP_ADDR IAP的栈顶地址(0x08000000)

//跳转到APP时 APP_ADDR AAP的栈顶地址(如:0x08003800)

JumpAddr = *(INT32U *)( IAP_ADDR + 4); //设置复位中断向量(如上面流程分析)

__set_MSP(SpInitVal); //设置SP.,堆栈栈顶地址

pFun = (void (*)(void))JumpAddr; //生成跳转函数.将复位中断向量地址做为函数指针

(*pFun) (); //执行函数,实现跳转.不再返回.

}

在IAP和APP中都需要进行中断向量表的设置,如正常程序中设置一样。

再介绍一下在集成开发环境下APP程序起始地址设置

Keil MDK环境下点击Options for TargetàTarget选项卡

clip_image006

clip_image008

clip_image010

在IAP和APP均为无系统时,上面程序能够很好实现互相跳转。但在IAP无系统,而APP使用UCOS系统时出现了较多问题(IAR环境)。如下一一记录各种问题的解决过程。

1、在程序正常设置APP的程序和向量表时后,在IAP直接调用跳转APP时,程序没有正常跳转到APP中,跳入未区域,具体情况现已回忆不清。但分析是因为跳转后没有找到中断向量表,从而没有正常进入APP的main()函数。

clip_image012

但在BSP_Init()函数中确实有对复位中断向量进行了设置。

NVIC_SetVectorTable(NVIC_VectTab_FLASH,(APP1_ADDR+4));

说明一下,这里将中断向量表设置为 (APP1_ADDR+4)(偏移4个字节即为复位中断向量),而有的程序中设置为APP1_ADDR。实际上两种设置是一样的,在

NVIC_SetVectorTable()函数中执行下句

SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); 所以可以看出是否偏移4字节是一样的。

经测试发现需要在调用OSStart()的前一句重新设置复位中断向量才能正确设置。

2、 经上一步修改后,IAP可以跳转到APP中,APP也能跳转到IAP中,但再重IAP就不能再跳回APP了。修改跳转函数

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

函数功能:跳转到IAP函数

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

void JumpToIAP(void)

{

INT32U IapSpInitVal;

INT32U IapJumpAddr;

void (*pIapFun)(void);

RCC_DeInit();

NVIC_DeInit();

__disable_irq(); //关中断()

// APP如跳转前关中断,跳转到IAP后,IAP初始化后要打开中断

IapSpInitVal = *(INT32U *)IAP_ADDR;

IapJumpAddr = *(INT32U *)(IAP_ADDR + 4);

__set_CONTROL(0);

//进入用户级线程模式 进入软中断后才可以回到特权级线程模式

//APP如使用系统如ucos必须要有此过程否则跳到IAP后,无法再次跳到APP

__set_MSP (IapSpInitVal);

pIapFun = (void (*)(void))IapJumpAddr;

(*pIapFun) ();

}

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

IAP 跳转到 APP 函数

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

void Jumpto_APP(void)

{

INT32U IapSpInitVal;

INT32U IapJumpAddr;

void (*pIapFun)(void);

RCC_DeInit();//关闭外设

NVIC_DeInit();

__disable_irq(); //关中断()如IAP关中断 APP如果没用UCOS系统,APP

//初始化后要开中断,用UCOS后,在起动任务后会开中断

IapSpInitVal = *(INT32U *)APP1_ADDR;

IapJumpAddr = *(INT32U *)(APP1_ADDR + 4);

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

{

__set_MSP (IapSpInitVal);

pIapFun = (void (*)(void))IapJumpAddr;

(*pIapFun) ();

}

}

如此调整后可以正常互相跳转。

3、 将IAP增加3秒延时后再执行跳转APP函数(使用定时器update中断(更新中断)定时),但一执行跳转就进入APP的HardFault_Handler()。

因为在IAP有初始化定时器并始能了中断,而在APP中没有初始化定时器和初始化定时器的中断向量表,所以在APP中定时器仍然工作,产生中断后没有相应中断向量表就起出现错误。(自己理解,总之不管什么原因这样操作是错误的。)在执行跳转APP函数前将定时器更新中断失能,并且将定时器失能可解决!

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

更能:关闭计时器

输入参数:num 定时器号

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

void CloseTim(u8 num)

{

u32 tim = 0;

tim = (APB1PERIPH_BASE + (num-2)*0x0400); //计算定时器地址

TIM_ITConfig((TIM_TypeDef*)tim,TIM_IT_Update,DISABLE);

TIM_Cmd((TIM_TypeDef*)tim, DISABLE);

}

在用到STM32定时器的更新中断时,发现有些情形下只要开启定时器就立即进入一次中断。准确说,只要使能更新中断允许位就立即响应一次更新中断【当然前提是相关NVIC也已经配置好】。换言之,只要使能了相关定时器更新中断,不管你定时间隔多长甚至不在乎你是否启动了相关定时器,它都会立即进入一次定时器更新中断服务程序。这个问题比较容易忽视,有些情况下也无关紧要,但有些情况可能会给应用带来困扰。

解决办法是在使能定时器更新中断前先清除更新中断标志位。

在初始化定时器时使用如下代码:

TIM_ClearITPendingBit(TIM4,TIM_IT_Update);

TIM_ITConfig(TIM4,TIM_IT_Update, ENABLE);

TIM_Cmd(TIM4, ENABLE); //开启时钟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/243518.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

进程中的信号赋值与变量赋值

进程中的信号赋值与变量赋值 比较对象信号SIGNAL变量VARIABLE基本用法用于作为电路的信号连线用于作为进程中局部数据存储单元适用范围在整个结构体内的任何地方都能适用只能在所定义的进程中使用行为特性在进程的最后才对信号赋值,有延时立即赋值,无延时与Verilog对比信号赋…

不安和怀疑,美丽而又危险:看两位80后女艺术家的展览

“由喻红策划”是北京尤伦斯艺术中心“由……策划”系列展览计划之一。策展人喻红是中央美术学院油画工作室的教授,是目前最著名的新生代女艺术家之一。本次参展的是两位1984和1986年出生的北京女艺术家潘琳和苑瑗,展览名称——物非物。 展览突出了两位艺…

win32程序测试键盘钩子

// Test_Hook.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <Windows.h> #include <stdio.h> #include <stdarg.h> #include <ctype.h> #include <WinError.h>// Some global variables HINSTANCE g_Instance;…

SOA的未解之谜

虽然围绕着SOA有数以千计的出版物、提供商和分析师的吹嘘&#xff0c;以及SOA曾被宣布死亡然后又在SOA宣言中重生的事实&#xff0c;但是该话题周围仍然存在许多疑团。McKendrick在他最新的一篇博文对此进行了讨论。\u0026#xD;\nSOA与云计算之间的区别&#xff1f;David Linthi…

状态机设计技术

状态机设计技术 就理论而言,任何时序模型都可以归结为一个状态机。 状态机的优势 (1)高效的过程控制模型。 (2)容易利用现成的EDA工具进行优化设计。 (3)系统性稳定。 (4)高速性能。 (5)高可靠性能。 VHDL状态机的一般结构 从信号输出方式分,有Mealy和Moore型两…

Linux文件系统目录结构

进入Linux根目录&#xff08;即“/”&#xff0c;Linux文件系统的入口&#xff0c;也是处于最高一级的目录&#xff09;&#xff0c;运行“ls–l”命令&#xff0c;看到Linux包含以下目录。1./bin包含基本命令&#xff0c;如ls、cp、mkdir等&#xff0c;这个目录中的文件都是可…

藉上帝之旨,行时代之命的文学长征

——张炜长篇小说《你在高原》阅读笔记 阅读张炜的小说我从来没有过陌生感&#xff0c;这种感觉正如卡尔维诺对经典作品的比喻。他说&#xff1a;“一部经典作品是一本即使初读也好像是在重温的书。”我读张炜的作品就是这种感受&#xff0c;舒展的过程如同一场对往事前尘的追忆…

SSE指令集

SSE指令集的介绍网上一大堆, 这里贴一个用VS2008环境下的SSE测试程序, 分别用C代码, C内联汇编, C的SSE Intrinsics三种方式计算卷积的程序...这是一个win32控制台程序..... 程序下载地址 : http://download.csdn.net/detail/hemmingway/4598506 主文件的代码一览: // Test_SSE…

书评“世界杯”

昨天晚上&#xff0c;手捧《哈扎尔词典》的米洛拉德帕维奇以1比0敲碎了君特格拉斯的《铁皮鼓》&#xff1b;斯拉沃热齐泽克拎着《伊拉克&#xff1a;借来的壶》2比2浇灭了贝侯赛因奥巴马的《我父亲的梦想》和他《无畏的希望》。 今天早上&#xff0c;0比0&#xff0c;史蒂文杰拉…

VHDL仿真流程

VHDL仿真流程 VHDL测试平台Test Bench的主要功能有4种 例化待验证的模块实体通过VHDL程序的行为描述,为待测模块实体提供激励信号收集待测模块实体的输出结果,必要时将该结果与预置的所期望的理想结果进行比较,并给出报告根据比较结果自动判断模块的内部功能结构是否正确简…

实现ftoa与itoa

/********************************************************************************************* Name : 浮点型转字符* Brief : none* Input : str:字符串指针 num:浮点数 n:精度* Output : none* Return : none***************************************************…

Apache Nuvem将带来更多的开源云?

只要你过去几年没被困在荒岛上出不来&#xff0c;你就不可能不知道人们在云上所花费的巨大心力。无论你是否相信云将成为软件的一个“根本转变”&#xff0c;毋庸置疑的是未来几年将是云的世界。虽然现在谈很多标准还为时尚早&#xff0c;但我们开始看到在安全/识别及基本架构等…

两个C++毫秒级定时器

Win32控制台测试程序如下, 其中完整的程序代码下载是: http://download.csdn.net/detail/hemmingway/4600235 // Test_Time.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include "Timer.h" #include "TimeCounter.h"#define N 1…

狼行天下:追寻狼迹内蒙生态行第二天(续1)

临近傍晚的乌力亚思太山谷。乱云中的敖包和写有藏经文的旗帜。 我搭的帐篷。别看很小&#xff0c;可以住两个人。 能够睡6个人的巨大的帐篷&#xff0c;需要几个人才可以搭建起来。 夕阳把草原染成了赤金色。 《时尚健康》的三条汉子裹挟了自己的美女。这片草地&#xff0c;这堆…

VHDL子程序

VHDL子程序 VHDL子程序(SUBPROGRAM)是一个VHDL程序模块,这个模块利用顺序语句来定义和完成算法,因此只能使用顺序语句。这一点与进程相似,所不同的是,子程序不能像进程那样可以从本结构体的并行语句或其他进程结构中直接读取信号值或者向信号赋值。 VHDL子程序与其他软件…

stm8因为固定中断向量表地址引发的一系列问题及其处理

转载&#xff1a;https://blog.csdn.net/chen244798611/article/details/51334489 因为之前写个stm32的IAP升级程序&#xff0c;所以我总结了做IAP升级的三个主要的难点&#xff1a; 1、如何设置中断向量&#xff0c;也就是说中断向量的重定向 2、如何配置程序的起始地址 3、…

《北京作家》2010年第2期,总第4期出版

《北京作家》2010年第2期&#xff0c;总第4期出版。 “名家新作”栏目推出的是著名作家张洁的最新短篇小说《一生太长了》&#xff0c;这篇小说最早发表于《人民文学》杂志社&#xff0c;是张洁非常特殊的小说之一。小说以狼为视角&#xff0c;叙述了狼在人类主宰的自然界的生存…

一种数据结构 跳表skiplist

跳表是平衡树的一种替代的数据结构&#xff0c;但是和红黑树不相同的是&#xff0c;跳表对于树的平衡的实现是基于一种随机化的算法的&#xff0c;这样也就是说跳表的插入和删除的工作是比较简单的。 下载地址 : http://download.csdn.net/detail/hemmingway/4625042 测试程…

《曙光与暮色》中的孤独与罪

《你在高原》第八卷《曙光与暮色》的两个主题值得关注。第一是孤独。小说的发展主要有三条线索&#xff1a;宁伽、曲涴、庄周&#xff0c;三条线索虽有内在关联&#xff0c;但都彼此孤立、隔离&#xff0c;甚至是彼此绝缘。小说中人与人之间的关系也是如此&#xff0c;出身、地…