STM32 IAP 在线升级详解
- _IOuint32_t*)(ApplicationAddress+4);
- 43. Jump_To_Application=(pFunction)JumpAddress;
- 44.
- 45. //初始化用户程序的堆栈指针
- 46. __set_MSP(*(__IOuint32_t*)ApplicationAddress);
- 47. Jump_To_Application();
- 48. }
- 49. else
- 50. {
- 51. SerialPutString("nouserProgram\r\n\n");
- 52. }
- 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?
- pFunctiona1,a2,a3;
- voidfun(void)
- {
- ......
- }
- 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的理解: (下面这篇文章写的非常好,有木
STM32IAP在线升 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)