iap 應用跳轉代碼詳解

一.關於跳轉部分的代碼的理解(轉)app

 

這裏重點說一下幾句經典且很是重要的代碼:函數

第一句: if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)   //判斷棧定地址值是否在0x2000 0000 - 0x 2000 2000之間ui

怎麼理解呢? (1),在程序裏#define ApplicationAddress    0x8003000 ,*(__IO uint32_t*)ApplicationAddress)  即取0x8003000開始到0x8003003 的4個字節的值, 由於咱們的應用程序APP中設置把 中斷向量表 放置在0x08003000 開始的位置;而中斷向量表裏第一個放的就是棧頂地址的值spa

也就是說,這句話即經過判斷棧頂地址值是否正確(是否在0x2000 0000 - 0x 2000 2000之間) 來判斷是否應用程序已經下載了,由於應用程序的啓動文件剛開始就去初始化化棧空間,若是棧頂值對了,說應用程已經下載了啓動文件的初始化也執行了;.net

 

第二句:    JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);   [  common.c文件第18行定義了:  pFunction   Jump_To_Application;]
                      
debug

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;  就是給整型定義一個別名 acode

 void (*pFunction)(void);   是聲明一個函數指針,加上一個typedef 以後  pFunction只不過是類型 void (*)(void) 的一個別名;例如:blog

 

[cpp] view plaincopy索引

  1. pFunction   a1,a2,a3;  
  2.   
  3. void  fun(void)  
  4. {  
  5.     ......  
  6. }  
  7.   
  8. 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              ;這個不解釋,說了是跳轉

正點原子代碼裏是這麼實現的:

//appxaddr:用戶代碼起始地址.
void iap_load_app(u32 appxaddr)
{
    if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)//檢查棧頂地址是否合法.
    { 
         jump2app=(iapfun)*(vu32*)(appxaddr+4);//用戶代碼區第二個字爲程序開始地址(復位地址)
         MSR_MSP(*(vu32*)appxaddr);//初始化APP堆棧指針(用戶代碼區的第一個字用於存放棧頂地址)
         jump2app();  //跳轉到APP.
     }
}
相關文章
相關標籤/搜索