作者:阿拉丁神丢
转自:http://blog.sina.com.cn/s/blog_6035432c0100xxzd.html
今天调试一个程序时,竟然一个局部变量莫名奇妙的乱变,最终因为Stack Size太小所致。原来400,改成800问题马上解决。

--------------------------------------------------------------------------------------------------
int main(void)
{
u8 ret;
SystemInit();
//Flash 解锁
FLASH_Unlock();
GPIO_Configuration();
//配置按键
KEY_Configuration() ;
//串口配置初始化
IAP_Init();
BootMenu:
//LED1ON;//亮
SerialPutString("\r\n==================================================================");
SerialPutString("\r\n* (C) COPYRIGHT 2011 *");
SerialPutString("\r\n* *");
SerialPutString("\r\n*STM32F10X In-Application Programming Application (V 2.1.3) *");
SerialPutString("\r\n* *");
SerialPutString("\r\n==================================================================");
SerialPutString("\r\n\r\n");
ret = SerialKeyPressedWithTimeOut(3);//等待串口输入按键
if (ret == 0x00)
{
//假如按键按下
//执行IAP驱动程序更新Flash程序
//LED1ON;不亮
Main_Menu ();
}
//否则执行用户程序
else
{
//判断用户是否已经下载程序,因为正常情况下此地址是栈地址。
//若没有这一句的话,即使没有下载程序也会进入而导致跑飞。
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();
goto BootMenu;
}
else
{
SerialPutString("\nno User Program, Go To Menu!\r\n\n");
goto BootMenu;
}
}
return 0;
}
解析:
=======================================
(ApplicationAddress + 4)是一个地址
(__IO uint32_t*) (ApplicationAddress + 4)把这个地址 转换为一个指针
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4)取地址里的内容作为JumpAddress
=======================================
因为CM3不同于ARM7等
并不是从入口地址开始指行第一条指令
而是从地址0x00取出MSP的初始值
再从地址0x04取出PC的初始值
然后从PC处开始执行第一条指令
=======================================
用户代码的首地址处放的是堆栈地址,首地址+4的地方放的是代码的复位地址,所以
1, JumpAddress = *(vu32*) (ApplicationAddress + 4);是把用户代码的复位地址赋值给JumpAddress。
2, __MSR_MSP(*(vu32*) ApplicationAddress); 是把用户代码的堆栈地址写入堆栈指针
3, Jump_To_Application()是把用户代码的复位地址付给PC指针
=======================================
if (((*(vu32*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
这句话的意思是把用户代码的首地址里面的数据拿出来,看看是不是以0x20000000开头。
前面说了用户代码的首地址放的是堆栈指针,而堆栈应该指向RAM,而RAM的首地址是0x20000000,所以这句话用来判断是不是已经有一个正确的堆栈指针地址写在了用户代码的首地址,进一步可以推测是不是有一个正确的用户代码写在了用户代码区,如果已经写入了,就可以跳过去运行,如果没有写入,就不跳过去。这是DEMO程序的判断逻辑,可以这样用,也可以不这样用。
这和你能不能跳转没有关系。