21-STM32物聯網開發WIFI(ESP8266)+GPRS(Air202)系統方案升級篇(使用串口調試助手升級STM32程式,固定地址升級運行用戶程式),IAP詳解

  • 2019 年 10 月 7 日
  • 筆記

https://www.cnblogs.com/yangfengwu/p/11515717.html

源碼下載鏈接:

https://gitee.com/yang456/STM32_IAP_Learn.git

加入這一節呢主要是為了方便大家理解我寫的升級篇單片機的程式

這節寫的更詳細點哈,也寫給那些沒有做過升級的朋友看

有件事情哈!!!!

我不知道大家現在怎麼看我,我的資料有公開的,有售賣的,在有些人看來,我出售我寫的源碼就是不應該的,我就應該全部公開…

大家看沒看過當年魯豫採訪朴樹,其實儘管我和朴樹做著不一樣的事情,但是外界對我們內心的影響卻是如此的一致!

原影片:http://www.iqiyi.com/w_19ruzppxh9.html

給大家看一個片段

大家是否明白樸樹在表達什麼…

用自己的價值為自己創造金錢,只要不是違法犯罪和違反道德的事情,我認為掙多少錢都是應該的!

如果你所做的事情能夠幫到很多人,那麼這件事情就是好事情!

那些抨擊過他的人,都是一些沒有度過艱難困苦日子的腦殘,只知道過分的要求別人要怎樣怎樣!因為生活太安逸,只知道吃喝玩樂!無腦青年越來越多!

實際上我以前就說過,我的源碼到了一定的時候會全部公開!等到哪一天我這邊所有的事情都流轉起來了(包括人脈和金錢),我便會公開我的所有的源碼!人都是往好的地方去發展,都希望過輕鬆愉快的生活!我也想!

我現在出售的源碼是圍繞著項目開發來寫的,這些源碼是為了別人做項目時的參考(簡單來講就是直接幫助別人賺錢)!但是這些源碼也都是對我所公開的基礎知識源碼的整合和優化!

如果你沒有這個能力去整合和優化我公開的源碼,而你又不買我的,你也別說我這那!我不是聖人,但是我一直是個老好人!

前一段時間裡我就覺察到有些人開始說我了,所以沒有多久我就公開了我的基礎篇

我有時候也會想:憑什麼大家把我忘掉了!

我也在擔心:大家會不會感覺我不是那個我了!

也是因為這,我才發了那個說說 https://user.qzone.qq.com/946029359/main

像我這樣的人,世間還有多少人!

不過說起來,我還有很多要公開的基礎教程沒有寫完呢!無論如何我也會做完我想做的!

吃完飯回來接著寫.

演示步驟: (如果編譯出現錯誤,看下面詳細介紹)

打開串口調試助手 

下載bootloader程式  我用stlink下載哈,方便

選擇程式文件

首先需要發送一條指令

updata start

然後發送程式文件

說明接收並運行了咱寫的APP程式.

IAP詳細說明:

所謂單片機的升級實質上就是把手動用軟體下載程式,改為咱人為通過某種方式寫到Flash

我這篇文章就多嘮叨會!

打開下面的程式

如果編譯出錯,可能是這裡

我這裡是讓軟體幫忙生成bin文件

我寫的是

E:MDK5ARMARMCCbinfromelf.exe  –bin -o  .ProgectProgect.bin  .outputProgect.axf

E:MDK5ARMARMCCbinfromelf.exe  –bin -o   這是命令,意思是讓軟體生成bin文件

前面這個路徑和自己安裝軟體的路徑有關,下面是我的路徑

.ProgectProgect.bin   就是生成的bin文件名字是 Progect.bin  ,路徑是工程目錄的 Progect文件夾裡面(如果沒有則會自動建個文件夾)

所謂工程目錄

.outputProgect.axf   當前工程目錄的output文件夾裡面的Progect.axf文件

.axf這個文件也是由軟體生成的,這個文件裡面有咱要的bin文件數據,當然還有一些調試資訊

我設置的是生成的文件名字是Progect.axf

我自己設置的 讓文件生成到output文件夾

其實整理下就是

E:MDK5ARMARMCCbinfromelf.exe  –bin -o  .ProgectProgect.bin  .outputProgect.axf

用fromelf.exe裡面的–bin -o指令,把Progect.axf文件裡面的bin數據提取出來以後生成一個新的文件 Progect.bin

現在看bin文件  和  hex文件的區別

看沒看到hex比bin文件多了前面一部分,和後面一部分

大家下載單片機程式應該都知道是下載hex文件

但是大家了解整個的下載過程不

其實咱用軟體下載的時候首先單片機需要知道下載的這段程式下載到哪個地址上(把程式數據寫到哪個Flash地址)

所以hex文件的前面部分就是地址資訊,就是告訴晶片我後面的程式碼段存儲到哪個地址上

當然為了保險起見,數據需要加校驗,其實hex文件的最後一位就是校驗位

像51單片機,STM32的串口下載,下載的時候需要斷電上電,或者複位一下,其實咱的單片機裡面有一段程式(接收單片機程式,寫入Flash) 就是咱所說的bootloader

記不記得都是先點一下下載軟體的下載按鈕,然後再複位單片機

其實點一下下載軟體,下載軟體就一直串口輸出下載命令呢!單片機一啟動是先執行裡面內嵌的bootloader,bootloader一檢測到下載命令,就開始執行下載操作了,接收下載軟體過來的數據,然後寫到Flash裡面…..寫完了,有的單片機重啟下才運行,有的就直接運行了

好,現在說bin文件為啥去掉了前面的地址資訊

記住,咱自己更新的時候咱就規定好了程式的運行位置

注:大家應該知道0x08000000 和 0x8000000 是相等的

STM32默認一開始是從0x8000000開始運行的,程式默認也寫到這裡(注意這個是不可改變的)

但是呢咱可以手寫個程式碼把一個完整的程式文件寫到一個位置(假設寫到 0x8004000開始)

然後呢!調用STM32給的跳轉函數,填上跳轉地址(0x8004000),程式就跳轉到新地址運行了

我這幾程式碼呢!是這樣做的,第一部分程式碼(簡稱:bootloader),什麼也不配置,就是默認運行在 0x8000000地址

bootloader 程式碼主要做的就是串口接收程式文件(簡稱APP,注意是bin文件哈),然後把程式bin文件寫到指定的Flash地址,寫完之後,跳轉到這個地址執行

不過呢!APP程式碼除了上面說的是下載bin文件以外,還需要配置

我先說明 APP程式寫到哪個地址其實和bootloader程式有關

注意沒

咱的bootloader 程式需要佔用10KB的空間,也就是說

10KB = 10*1024 = 10240位元組 = 0x2800

那麼咱的APP程式一開始寫入的地址必須大於 0x8002800

如果寫入的地址佔用了bootloader的地址,那麼程式就崩了

我的bootloader 程式碼主要做的就是串口接收程式文件(簡稱APP,注意是bin文件哈),然後把程式bin文件寫到指定的Flash地址,寫完之後,跳轉到這個地址執行,你可不能讓這個程式碼崩….程式一開始就是執行bootloader,如果這個程式有問題了,整個就崩了…

現在看用戶程式的其它配置

假設我想讓APP個程式運行在0x8004000地址,那麼需要讓軟體生成可以運行在這個地址的bin文件才可以,所以

默認是0x8000000

還需要修改下SIZE,上面寫的是0x10000  也就是65536位元組 = 64KB  我用的單片機是C8T6哈,Flash就是64KB的

咱改為 0x8004000

0x4000 就是 16384位元組   其實整個FLASH還剩下  65536 – 16384 = 49152 位元組 也就是  0xC000

好,現在生成的程式就是可以運行在  0x8004000的程式了

但是呢還有個問題!

中斷問題!

咱可以在bootloader  MAP文件裡面看到

往下還有各種中斷

如果咱不在APP程式裡面做一下設置,那麼APP程式裡面的中斷其實會跳進 bootloader 裡面(假設bootloader 也使用了一樣的中斷)

這個我的影片會給大家演示

咱需要讓APP裡面生成自己單獨的一套中斷

所以呢咱需要設置下中斷向量偏移,一般都是咱的APP程式相對於Flash地址偏移了多少,咱就設置中斷向量偏移多少

SCB->VTOR = FLASH_BASE | 0x4000;

這樣的話,所有的APP裡面分配的中斷函數地址最起碼是在0x8004000地址的基礎上的

其實現在APP程式就準備好了,

不過大家百度STM32  IAP,有很多人在bootloader裡面這樣寫

if(((*(vu32*)(UpdateAddrCopy+4))&0xFF000000)==0x08000000 && ((*(vu32*)UpdateAddrCopy)&0x2FFE0000)==0x20000000)

這就是對接收bin數據的(看的bootloader的bin數據)  

這兩個位置進行判斷

前面的四位是說明咱的整個程式佔用的RAM空間最高地址   注意:STM32是小端模式,低位存在低位,高位存在高位

所以上面的是  0x20000978

大家應該知道咱的全局變數和局部變數都是存在RAM裡面的

咱的STM32 RAM的首地址是0x20000000  我的後面是0x5000  = 20480位元組  = 20KB  (20480/1024)

咱可以看一下那個MAP

其實咱知道咱用的RAM空間是 0x20005000  

其實在細緻一點就是判斷高16位是不是 0x2000  然後低16位是不是小於0x5000

而程式中只是  ((*(vu32*)UpdateAddrCopy)&0x2FFE0000)==0x20000000

然後還有個 ((*(vu32*)(UpdateAddrCopy+4))&0xFF000000)==0x08000000

大家看MAP文件

bootloader 的MAP文件為例

0x08001F35

實際上這個Flash地址裡面存儲的是複位中斷入口地址,得到這個地址以後執行複位中斷服務程式

複位中斷入口地址是0x08001F35

這個數據存在了 Flash的 0x08000004 (1F35)  和 0x08000006 (0800)  地址裡面  

注意:所有的中斷入口地址都存在了Flash裡面,咱定義的函數的入口地址也是在Flash裡面

咱編譯的時候,軟體就給中斷函數和咱寫的普通函數分配空間 (從0x08000XXX)開始分,注意不是從0x08000000開始哈,具體前面的空間具體給誰我也不知道,但是呢!看上面就知道第一個32位(0x08000000 – 0x08000003),存儲的是堆棧棧頂地址(整個程式佔用的RAM空間最高地址)

第二個32位(0x08000004 – 0x08000007) 存儲的是複位中斷入口地址

可以看下MAP,這是分配的地址

分完以後函數的首地址就有了

然後再把這些地址存到Flash裡面,從0x08000000開始存

不過Cortex-M3內核規定,Flash起始地址必須存放堆頂指針,而第二個地址則必須存放複位中斷入口向量地址

其它的我就不知道按照什麼規則存了

當然後面的

不可屏蔽中斷,就是說系統出現了不可挽回的錯誤的時候會進去這個中斷

還有

硬體錯誤中斷,像數組越界,記憶體溢出等等都會進去

然後,發現後面基本上都是各種中斷函數…如果大家想判斷的更準確的話,就多判斷幾個08

其實各種中斷函數的地址都存在了Flash裡面,由於一開始是初始化各種中斷,所以才出現這麼多08

接收完程式就可以跳轉了

其實呢跳轉是固定形式,上面有注釋

所有涉及到的主要的IAP知識點就說完了

現在說下我的源碼思路

我為了方便我修改用戶程式軟體上的配置

我設置的bootloader使用了16K,實際上我的bootloader只用了10K

其實只要記憶體充足,自己願意定義多少就定義多少,前提看APP程式佔用多少空間,只要預留的夠APP使用就可以

總共 64K  去掉 16K  還有 48K…足夠用

然後我再主函數裡面列印了一下

其實就對應用戶程式

這樣方便一點

bootloader函數接收到 updata start以後先擦除APP程式所用的Flash地址空間

然後咱發bin數據的時候

環形隊列: https://www.cnblogs.com/yangfengwu/p/6822984.html

環形隊列實際上就是用一些函數操作數組,可以一邊往裡面存數據,一邊取數據

我就是用5位元組大小的數組,來接收的APP程式(21K),然後寫入Flash

由於讀環形隊列然後寫入其實挺快的,有時候串口接收數據的速度趕不上,所以

其實就是類似於空閑中斷,10ms的時間內串口都沒有接收到數據,就認為接收到一條完整的數據

其實用戶程式也就是上面說的那些配置

大家有不明白的再問吧.