微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > STM32 IAP 在线升级详解

STM32 IAP 在线升级详解

时间:11-09 来源:互联网 点击:
  1. _IOuint32_t*)(ApplicationAddress+4);
  2. 43. Jump_To_Application=(pFunction)JumpAddress;
  3. 44.
  4. 45. //初始化用户程序的堆栈指针
  5. 46. __set_MSP(*(__IOuint32_t*)ApplicationAddress);
  6. 47. Jump_To_Application();
  7. 48. }
  8. 49. else
  9. 50. {
  10. 51. SerialPutString("nouserProgram\r\n\n");
  11. 52. }
  12. 53. }

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

* @函数名称 main

* @函数说明 主函数

* @输入参数 无

* @输出参数 无

* @返回参数 无

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

int main(void)

{

//Flash 解锁

FLASH_Unlock();

//配置PA15管脚

KEY_Configuration() ;

//配置串口1

IAP_Init();

//PA15是否为低电平

if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15) == 0x00)

{

//执行IAP驱动程序更新Flash程序

SerialPutString("\r\n======================================================================");

SerialPutString("\r\n= (C) COPYRIGHT 2011 Lierda =");

SerialPutString("\r\n= =");

SerialPutString("\r\n= In-Application Programming Application (Version 1.0.0) =");

SerialPutString("\r\n= =");

SerialPutString("\r\n= By wuguoyan =");

SerialPutString("\r\n======================================================================");

SerialPutString("\r\n\r\n");

Main_Menu ();

}

//否则执行用户程序

else

{

//判断用处是否已经下载了用户程序,因为正常情况下此地址是栈地址

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

if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0 ) == 0x20)

{

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();

}

else

{

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

}

}

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

第一句: if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0 ) == 0x20) //判断栈定地址值是否在0x2 0 - 0x 2 2之间

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

也就是说,这句话即通过判断栈顶地址值是否正确(是否在0x2 0 - 0x 2 2之间) 来判断是否应用程序已经下载了,因为应用程序的启动文件刚开始就去初始化化栈空间,如果栈顶值对了,说应用程已经下载了启动文件的初始化也执行了;

第二句: 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 plaincopyprint?

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

pFunction a1,a2,a3;

void fun(void)

{

......

}

a1 = fun;

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

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

我们看一下启动文件startup_stm32f10x_md_vl。s 中的启动代码,更容易理解

移植后的IAP代码在我的资源(如果是stm32f100cb的芯片可以直接用):http://download.csdn.net/detail/yx_l128125/6475219

三、我们来简单看下启动文件中的启动代码,分析一下这更有利于我们对IAP的理解: (下面这篇文章写的非常好,有木

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top