日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IAP实验笔记

發布時間:2023/12/16 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IAP实验笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ISP和IAP

ISP:在系統編程。通過芯片上已經固化好的bootloader,從串口將代碼寫入內部的flash。這塊bootloader位于系統存儲區,置位boot引腳來選擇系統存儲器為啟動區域。


IAP:在應用編程。用戶根據自己需要將flash分成兩個區域,一塊用作bootloader,一塊是我們正常運行的程序(app),而bootloader的作用和上面ISP的一樣,將app代碼引導至flash中。

IAP過程

stm32正常運行流程


從圖中可以看到,在0x08000000處存放著程序的中斷向量表,它由棧頂地址和各中斷的入口地址組成。在上電復位后,芯片會由硬件控制回到0x08000000處,先將0x08000000地址開始的4字節棧頂指針送給sp寄存器,然后將0x08000003地址開始存放的復位中斷的入口地址給程序計數器pc,從此開始程序跳轉到復位中斷服務函數。


跳轉到復位中斷后,它做的只有兩件事,一是系統時鐘初始化,二是跳轉到我們編寫的main函數

當我們進入到main函數時,程序會按照我們編寫的邏輯運行。當有中斷請求時,芯片會從中斷向量表中獲取相應的中斷服務函數入口地址,跳轉到相應的中斷程序。并且中斷向量表的位置是可以重定義的,它由SCB->VTOR寄存器控制。

有IAP的stm32運行流程


從圖中可以看到,與stm32正常運行流程相比,IAP相當于加入了一個bootloader,通過它將我們的app代碼引導至flash中。首先,和上面的流程一樣,復位后,芯片配置堆棧指針和pc指針,初始化系統時鐘,然后進入我們的main函數,main函數里面是我們編寫的bootlaoder程序,按照我們的需要引導app程序至flash或者跳轉到app程序。

int main(void) { uart_init(115200); //串口初始化為115200delay_init(); //延時初始化 LED_Init(); //初始化與LED連接的硬件接口KEY_Init(); //初始化按鍵while(1){if(KEY_Scan(KEY_CONT) == DOWNLOAD_PRES) //引導app至flash指定位置{iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,USART_RX_CNT);LED1 = 0;}else if(KEY_Scan(KEY_CONT) == EXECUTE_PRES) //跳轉到app{LED1 = 1;iap_load_app(FLASH_APP1_ADDR);}} }

(上面的代碼是一個簡單的bootloader的測試。通過按鍵控制,從串口接收app程序,并跳轉到app程序。我們可以根據自己需求編寫,功能都大同小異)
自此,bootloader部分暫時結束。程序會跳轉到我們的app。從圖中可以看到,它其實是又重復了一遍正常的運行流程,只不過相對于以前的0x08000000的起始地址有了一個偏移。值得注意的是,進入我們app的main函數之后,如果有中斷請求,我們需要它進入的是app的中斷,而不是bootloader的中斷,這時就需要對SCB->VTOR寄存器進行重設。

IAP代碼

這里主要是對正點原子提供的bootloader程序的部分代碼分析。

bootloader

bootloader主要包括兩個功能:引導app和跳轉到app。

引導app到flash這個功能的實現很簡單,利用的是flash的擦除和讀寫,在此不做贅述。

跳轉到app

//跳轉到應用程序段 //appxaddr:用戶代碼起始地址. void iap_load_app(u32 appxaddr) {jump2app=(iapfun)*(vu32*)(appxaddr+4); //用戶代碼區第二個字為程序開始地址(復位地址) MSR_MSP(*(vu32*)appxaddr); //初始化APP堆棧指針(用戶代碼區的第一個字用于存放棧頂地址)jump2app(); //跳轉到APP. }

(appxaddr是我們定義的app存放在flash中的地址,注意它不能和bootloader程序占用的空間沖突)

如前面分析所示,要跳轉到app程序執行,就是把app程序起始地址給程序計數器pc,同時初始化app的棧頂指針。變化是以前是硬件完成,現在由軟件完成。

首先是pc指針賦值工作。我們無法對程序計數器pc直接操作,所以我們使用空函數跳轉的辦法。我們獲取appxaddr+4的內容,得到復位中斷的入口地址,然后跳轉到它即可。這里的代碼先是取出了32位的函數地址,然后將其強制轉化成函數指針的類型賦給jump2app,最后執行jump2app這一空函數實現跳轉。

以下代碼是iapfun和jump2app的定義,涉及函數指針和typedef別名定義,可以參考這兩篇文章,很有學習價值:

typedef void (*iapfun)(void); //定義一個函數指針 iapfun jump2app;

typedef用法總結
函數指針和指針函數

接下來是初始化棧頂指針。

//設置棧頂地址 //addr:棧頂地址 __asm void MSR_MSP(u32 addr) {MSR MSP, r0 BX r14 }

這里使用的是兩條匯編指令。函數的參數會自動傳給寄存器r0,利用指令MSR將r0的值存儲到特殊寄存器sp中,實現棧頂指針的重設。之后執行BX指令,r14會保存執行函數前的pc值,這樣就跳轉到原始位置執行jump2app。

app

通過前面的分析,可以知道app程序要滿足兩個要求:

  • 起始地址偏移
  • 中斷向量表偏移

地址偏移的修改如下圖所示,根據bootloader的大小決定起始地址偏移量。比如我之前使用的bootloader是6k字節,那么我就可以把0x08001800后的空間留給app使用(在這里使用0x08010000為起始地址),之后再根據flash容量確定大小即可。

對比偏移后生成的二進制文件,就能發現其實是中斷向量表存放的中斷向量發生了一個整體偏移,對運行的代碼沒有影響。

起始地址偏移修改完后,在沒有中斷發生的情況下,程序是可以正常跑起來的;在有中斷請求時,芯片會根據中斷向量表起始地址(VTOR寄存器存儲)和中斷類型號找到對應中斷程序,因為中斷向量表起始地址還是默認的0x08000000,所以它進入的中斷還屬于bootloader。在這里修改中斷向量表起始地址,讓它定位到app。具體操作如下:

SCB->VTOR = FLASH_BASE|0X10000

到這里,app的部分就配置好了,接下來就該生成對應的二進制文件讓bootloader引導進flash。具體操作如下圖所示。

找到我們的MDK目錄下的fromelf程序,使用以下命令,讓它生成二進制文件。

D:\MDK\ARM\ARMCC\bin\fromelf.exe --bin -o xxx.bin xxx.axf

生成的二進制文件就是我們編譯完成后的最純粹的數據代碼,cpu按照這個代碼順序執行就能實現相應功能。至于為什么不使用十六進制文件,是因為他還有很多附加信息,比如數據存儲的起始地址,cpu執行過程中并不需要它們。具體可參考以下文章。
hex和bin的區別

總結

以上是生活随笔為你收集整理的IAP实验笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。