iap如何初始化_STM32F4-IAP学习笔记(一)
啰嗦兩句
花了斷斷續續兩天時間在STM32上面寫了一個IAP(In Application
Programing)Boot,期間多多少少還是遇到的了不少問題。現在就花點時間把這兩天寫的東西整理一下,就當是學習筆記吧。本人用的芯片是
STM32F4系列,1M的FLASH,192KB的SRAM。
正文
不得不提的啟動方式
STM32支持三種啟動方式
1. FLASH啟動
2. SRAM啟動
3. 系統存儲器啟動
這三種啟動順序決定了上電后第一條指令的位置。如果你選擇FLASH啟動,則上電復位后PC指針指向第一條指令位置——0x08000000,如果
你選擇SRAM啟動,則上電復位后PC指針指向第一條指令位置——0X20000000,若你選擇系統存儲器啟動,則上電復位后PC指針指向第一條指令位
置——0X1FFF0000。
為什么會這樣呢?接下來我們分析一下STM32F4的存儲區地址結構。
上圖摘自《Cortex-M3與M4權威指南》。從這里我們可以看出M4內核支持4GB的存儲空間,從0X00000000-0X1FFFFFFF
共512MB的空間是Code區,0x20000000-0x3FFFFFFF共512MB的空間是SRAM,其他的我們暫且不分析。我們再來看看
《STM32F4xx Reference manual 》中 關于F4系列的物理內存映射
從上面的物理內存映射圖我們可以看出:
0x08000000-0x080FFFFF: FLASH
0x1FFF0000-0x1FFF77FF: System memory
0x20000000-0x2001FFFF: SRAM
其中FLASH大小為1MB, SRAM大小為12KB, System memory大小為30KB。
在這里解釋三個問題:
《Cortex-M3&M4權威指南》中講到“系統上電復位后,從0x00000000處加載第一條指令…..”為什么上面提到的
三種啟動方式都是從非0x00000000加載第一條的呢?-這就是“地址映射”的作用了。我們通過boot0&1引腳的配置,可以選擇不同的啟
動方式,同時將flash或sram的基地址映射到啟動空間0x00000000處,這樣,加載的第一條指令位置便是我們相應的啟動方式對應的存儲設備的
地址了。
三種啟動方式有何區別?顯然,第一點不同就是地址空間不同,導致了三種啟動方式啟動時代碼加載空間隨之改變;此外System
memory是個真正的ROM,里面固化了廠家出廠時的BootLoader代碼,不可重寫。FLASH和SRAM則可自己重寫程序完成啟動,但是由于芯
片特性原因,兩者的用途也不一樣。FLASH就是我們常說的閃存,具有”掉電不失性”,燒寫代碼后,代碼不會因為掉電而丟失,下次上電啟動時仍然可以正常
啟動,為常見的啟動方式,但是缺點是運行速度較慢;SRAM是“靜態隨機存儲器”,具有“掉電易失性”,屬于RAM的一種,那么顯然我們不可能將代碼長保
存到SRAM中,因為下次上電后仍舊沒有代碼。這種啟動方式常用于程序調試,即上電后下載代碼,運行,進行調試,運行速度比FLASH快。
為什么FLASH不是RAM也可以運行程序?FLASH分為兩種,一種是Nor FLASH, 一種是Nand
FLASH。這兩者區別就不一一贅述,網上資料很多,在這里我們只需要明確:Nor FLASH 支持片內執行,Nand
FLASH不支持片內執行,而我們使用的STM32F4系列芯片內置的1MB的FLASH屬于Nor FLASH,所以便有從FLASH啟動這一說法。
解釋完這三個問題,我們便可以談談IAP了
關于IAP
IAP全稱為 In Application
Programing,即“應用內編程”,按照我個人的理解就是:我們通常下載到開發板上的程序其實是兩部分——BOOT+APP,
BOOT代碼負責必要的堆棧,中斷向量表等初始化,而APP才是我們真正需要的功能代碼,而STM32已經有.s啟動文件支持,所以我們無需關注BOOT
部分,只需完成相應的功能代碼即可,通常無論你代碼內有多少功能,但你下載的文件只有一個,即BOOT+APP,且只能通過特定的方式寫入到FLASH或
者SRAM內運行。而應用內編程,則打破了這個規則,原則上只要存儲空間無限大,我們就可以使用IAP可以下載到FLASH內部無限多個應用程序。
下面我簡單的畫一下兩者的運行機理:
應該不難看出,其實所謂的IAP,就是先寫一個APP作為偽BOOT,在系統初始化完成之后,引導系統加載真正的APP程序,使之運行,完成真正的
APP程序的功能。這樣我們就可以下載多個APP在不同空間內,只要讓引導程序做出相應的跳轉工作,便可以實現運行對應APP功能。
講到這里,我們先來思考下面四個問題:
偽BOOT完成了哪些工作?
APP程序是如何下載到開發板上去的,對空間有特殊要求嗎?
偽BOOT到APP之間的跳轉如何完成?
APP程序需要具有哪些功能?
下來我們就來分析分析
剛才已經提到過,偽BOOT其實就是我們平時寫的APP程序,為什么我要叫他偽BOOT呢?因為他并不是一個真正的BOOT程序,他也是一個BOOT+APP程序,只不過這個程序在IAP編程中完成的工作很像一個BOOT程序,所以我起了個名字叫做偽BOOT。
我們先來看看一般BOOT程序完成的工作:單片機上電復位之后,程序指針PC指向0x00000000(映射到FLASH的0x08000000或者SRAM的0x20000000處),這里存放的是用戶堆棧棧頂地址,獲取到棧頂指針后,程序指針向后偏移4個字節,指向0x00000004(映射到FLASH的0X80000004或者SRAM的0X20000004),這里存放的是系統中斷復位的指針,
然后程序跳轉到Reset_Handler執行SystemInit(系統復位)工作,在系統復位中系統關閉了中斷,初始化系統時鐘等等。然后跳轉到
__main進行堆棧初始化,最后跳轉到.C文件中的main函數中執行相應的功能。【這里只做概述,過兩天有時間了專門寫一篇關于STM32啟動流程分
析的文章^-^】。
我們可以看到,系統初始化部分是必須的,關鍵我們要修改的就是最后這一步跳轉,如和讓程序跳轉跳轉到我們編寫的APP代碼中而不是跳到偽BOOT中
的APP程序呢?其實這也是可以的,我們只需要將我們編寫的用戶APP程序中啟動代碼刪掉,其余代碼將偽BOOT中的用戶程序代碼覆蓋掉就可以,但這樣好
像失去了IAP的意義。IAP本來就是期望用戶“不拆機在線升級”。這樣搞豈不是更復雜了?
所以,更常見的做法是:偽BOOT完成系統初始化后,進入APP程序,此時利用APP實現兩個功能:
檢測是否需要升級某個用戶APP
跳轉到指定APP運行空間運行
我們可以依靠UART,USB,IIC等一切板上通信外設完成第一個功能。如果需要升級或更新某個APP,則通過某種通信方式將我們編譯好的bin
文件發送到單片機上,單片機偽BOOT中的程序接收這些數據并根據需要使用FLASH寫操作將這些代碼寫到指定的FLASH空間(這里我們只討論
FLASH)。當需要執行某個用戶APP程序時,可以在偽BOOT的主程序中修改程序指針PC,使系統跳轉到指定用戶APP程序所在的FLASH空間,然
后運行,就可以完成跳轉到相應的APP程序的功能。
道理很簡單。我們編寫偽BOOT程序使之有通信,FLASH讀寫,地址跳轉功能就可,在啟動啟動后,因為程序還運行在偽BOOT
里,我們依靠BOOT程序中的功能,檢測是否需要更新用戶APP,需要更新則進行數據通信,并將數據通過FLASH操作寫入FLASH,然后執行程序跳轉
指令,使系統跳轉到對應的APP程序空間,就可以執行對應的程序功能。
這里有幾個問題需要注意一下:
我們并沒有裁減掉用戶APPx中的boot代碼,所以某種程度來說,燒進FLASH中的至少是兩套或兩套以上的【boot+app】程序,只不過我們的偽BOOT是為了完成引導,其余的APP都是用戶功能程序罷了。
從問題1來看,既然每一個程序都是完整的,如果我們的偽BOOT通過串口接收到我們編譯好的完成工程的bin文件,并寫入到FLASH中
0x08004000之后,那么0x08004000這個地址里面存放的是什么東西?用戶APPx
main函數地址?錯!應該是用戶APPx程序的BOOT代碼的第一行,也就是程序代碼的用戶堆棧棧頂地址,那0x08004004理所當然就是APPx程序的BOOT代碼里的系統中斷復位指針。
從問題1和2我們可以推斷出,由偽BOOT引導后跳轉到用戶APP程序,系統又進行了一次復位操作,而且和偽BOOT是一模一樣的復位操作,但此時有個明顯的問題就是,我們的中斷向量表多
套,每套中斷向量表都對應的是自己APP的中斷入口,但是用戶程序執行時遇到中斷,跳轉會跳到哪里去呢?如果我們在用戶APP中不加以修改,中斷向量表的
偏移量仍舊是以0x08000000為基地址計算得到的,所以任何一個用戶APP都會跳轉到偽BOOT中的中斷向量,造成不可預料錯誤。但是幸好
STM32提供了中斷向量偏移寄存器,我們可以通過修改這個寄存器的值,將每個APP程序的中斷向量對應到自己所在空間的正確地址。完成中斷操作。
FLASH空間是在編譯鏈接后就確定的,所以在你下載程序之前,你的程序地址已經確定,這樣我們就需要在keil的配置文件中更改ROM的
地址,使APP程序可以燒寫到一個正確的FLASH空間,即不會破壞其他程序空間,又能被正確引導啟動,一般來講,偽BOOT文件大小越小越好,這樣可以
為APP程序節留下很多空間。而我個人建議將偽BOOT文件單獨放在第一扇區,即0x08000000-0x08003FFF【16KB】,因為程序中在
進行FLASH寫操作之前可能需要擦除,但往往擦除會擦除掉一整個扇區,如果對內存理解不到位或者程序編寫有誤,也會將偽BOOT擦除掉,使引導系統崩
潰。
我們的傳輸的APP程序一定經過keil編譯過的完整的工程形成的二進制——bin文件。因為我們是將文件數據直接發送到開發板上,不經過
特殊的解析,直接寫入到FLASH中,所以這就要求我們發送的文件一定是內存中最終存儲的二進制文件,而不是hex和axf文件。hex是十六進制文件,
我們打開可以看到一串ASCII碼,對應著地址信息和數據,而axf則包含著調試器調試信息,是通過JLINK或者STLINK解析后下載到開發板上的。
至于bin文件的生成,我們可以使用keil自帶的fromelf.exe工具。
而APP程序的功能絲毫沒有限制,和大家平時寫的一模一樣。這樣,就完成了整個IAP編程。
簡單總結一哈
IAP用途很大,比如無線下載,快速升級,遠程系統維護等等,這些都是IAP的具體應用,當然還有更多好玩的等你去發現。其實我學習IAP主要是想
玩玩無線下載,因為環境問題整天抱著電腦跑太累了,如果再改一改代碼,也可以實現BOOT-APPx之間的任意跳轉,可以讓下載和引導隨心所欲。不過今天
主要還是分享一下IAP編程的思想和一些細節問題,關于具體的編碼過程,后面有時間我會在下一篇文章里分享。
對啦,上面都是自己的理解,如果大家發現其中有什么講的不對的地方,歡迎指正,共同學習~
以上
總結
以上是生活随笔為你收集整理的iap如何初始化_STM32F4-IAP学习笔记(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 异步RFC 的使用
- 下一篇: 5G消息RCS富媒体通信与传统短信相比有