說明
這節提供給用戶一份實現更新STM32的程序(兼容STM32f103全系列)
主要說明STM32是如何實現的升級程序.后面的章節都是在這節的基礎上進行優化.
該節源碼開源: https://gitee.com/yang456/STM32_IAP_Learn.git
測試
1.說明
BootLoader作為引導程序,負責把接收的程序文件寫入flash,然后加載執行.
STM32F10xTemplate 是用戶程序,這套程序采用串口升級進去.然后執行
2.下載BootLoader程序到單片機(自行下載)

4.打開串口調試助手
發送 updata start
單片機擦除flash以后返回 wait updata...
5.發送程序文件STM32F10xTemplate 用戶程序的 bin文件
用戶程序每隔1S打印 run user app
6.在用戶程序執行的時候再次發送
updata start
等待返回 wait updata... 可以再次發送程序文件,執行更新.
發送程序文件
用戶程序每隔1S打印 run user app
整體說明
首先用戶需要明白,無論是什么單片機實現更新程序,實質上就是把程序文件寫到單片機的存儲里面
然后調用單片機提供的函數運行而已!!
對於當前的STM32程序而言就是把程序文件從0x08004000這個位置開始,把程序文件寫到里面
然后把0x08004000這個地址給一個函數執行.
1.下載完BootLoader以后,當用戶發送 updata start
程序擦除用戶程序運行區的flash
2.當用戶發送程序文件時
把接收的程序從0x08004000這個位置開始,把程序文件寫到flash里面
3.當檢測到接收到用戶程序,打印下有沒有錯誤信息,然后重啟
4.一旦有了用戶程序,則加載用戶程序
5.在用戶程序里面,如果接收到updata start 則設置一個更新標志(存儲在flash里面)
6.BootLoader 判斷有更新標志以后,擦除用戶程序運行區的flash
然后就是如此循環
細節說明(bin文件)
1.什么是bin文件?
大家肯定知道hex文件
打開這節的hex文件和bin文件
(我使用的UltraEdit這個軟件)
注意看hex文件和bin文件的區別
咱們是直接把程序文件寫入了相應的地址里面.
2.如何制作bin文件
2.1 概述
在做升級之前,上面的flash存儲位置是事先規定好的
stm32的flash地址是從0x08000000開始,默認下載程序的時候都是把程序文件從0x08000000開始寫入
這節規定了從0x08000000地址到0x08004000這段flash留給BootLoader使用(16KB)
這個具體留多少要看BootLoader程序bin文件大小,后面有具體說明.
2.1 設置中斷偏移地址,程序文件從哪開始執行,就設置偏移多少.
SCB->VTOR = FLASH_BASE | 0x4000;
為什么需要設置中斷偏移?
記住一句話:BootLoader里面配置的程序,即使執行了用戶程序同樣有效!
記住另一句話:所有的中斷函數都有固定的地址入口!
假設BootLoader使用了某個中斷,用戶程序也使用了某個中斷,如果不設置這個偏移,
那么用戶程序和BootLoader就使用了同一個中斷函數!
2.2 設置該程序文件運行的地址,及其大小
0x8004000 0xB800
解釋:
想讓這個程序運行在某個地址上,必須在軟件上設置一下,然后生成的文件才可以運行在這個地址上.
0x8004000 :這節的程序就希望程序運行在這個地址上
0xB800 : 我使用的是64KB的flash,從0x08000000 到 0x08004000 (16KB) 用於存儲BootLoader程序
從 0x0800f800 到 0x0801000 (最后2KB) 用於存儲其它數據
用戶程序剩余 = 64KB - 16KB - 2KB = 46KB = 46*1024字節 = 47104字節 = 0xB800(16進制表示)
2.3讓軟件生成bin文件
.\Progect\user.bin 就是生成的bin文件名字是 user.bin ,路徑是工程目錄的 Progect文件夾里面(如果沒有則會自動建個文件夾)
所謂工程目錄
.\output\Progect.axf 當前工程目錄的output文件夾里面的Progect.axf文件
工程都會生成xxxx.axf文件,我的這個文件就生成在上面的目錄里面
點擊編譯便生成了 user.bin文件
如何分配flash
1.首先需要明確,BootLoader程序是燒寫到單片機里面永遠不變的!
寫完BootLoader程序以后,生成bin文件,看一下bin文件大小
BootLoader是10KB,那么可以規定12KB(高容量單片機是2KB作為一頁,用偶數可兼容全系列)
2.接下來是確定下存儲其它用戶數據所用flash大小
這個需要根據自己的項目自行規定大小,一般都是把數據放到最后的地址存儲
3.以上的確定下來之后,剩余中間部分就是作為用戶程序的了
為了便於修改,我做了以下程序
在BootLoader程序開始運行,會打印下當前的配置
程序具體怎么寫入的flash並運行
1.一開始得到了程序寫入的地址
2.接收到 updata start ;擦除用戶程序區; UpdataStartFlage = 1;
3.串口助手發送程序數據時,把程序數據寫入了環形隊列
關於環形隊列系列文章: https://mnifdv.cn/forum.php?mod=forumdisplay&fid=53
4.主函數取出數據拼接成16位數據以后寫入flash
從0x08004000開始寫入,地址每次累加2
注:STM32寫入flash每次需要寫16位數據
5.接收完數據,打印下相應的錯誤,重啟.
6.重啟以后,判斷了用戶地址里面有用戶程序,加載用戶程序
細節說明
1.環形隊列大小5字節
就是說,只使用了5字節就接收處理了全部的程序文件!
2.關於 if(((*(vu32*)(UpdateAddr+4))&0xFF000000)==0x08000000 && ((*(vu32*)UpdateAddr)&0x2FFE0000)==0x20000000)這句話是判斷程序文件
實際上就是判斷的程序文件的這兩個位置
>
前面的四位flash地址記錄的值 00 0E 00 20 是記錄的整個程序占用RAM空間的最高地址(STM32默認的)
STM32的RAM是從 20000000 開始
注意:STM32是小端模式,低位存在低位,高位存在高位
上面的 20 00 0E 00 就是說總共使用了 0E 00 (3584字節的RAM)
0x20000E00
((*(vu32*)UpdateAddr)&0x2FFE0000)==0x20000000
上面的判斷其實就是判斷了下是不是 20 00
后面的 08 00 6C 35
實際上這個存儲的是復位中斷入口的地址.(STM32默認的后面四位存儲的是復位中斷入口的地址)
當然再往后08 00 41 45 是不可屏蔽中斷函數的地址
再往后 08 00 41 47 是硬件錯誤中斷函數的地址
咱所有的程序都是存儲在flash里面的,復位中斷函數也不例外
其實是下面這個樣子
BootLoader和用戶程序的flash里面具體存儲的都是按照上面的圖示.
程序是存儲在flash里面的,flash的地址肯定是從 0x08000000 - XXXXXX,所以才會有了
((*(vu32*)(UpdateAddr+4))&0xFF000000)==0x08000000
主要判斷的是不是 最高位是不是08
3.一定要記住一件事情:
我上面說過一句話: BootLoader里面配置的程序,即使執行了用戶程序同樣有效!
仔細考慮這句話!
假設在BootLoader里面使用了中斷定時器,用戶程序里面沒有使用,跳轉到用戶程序以后定時器還在運行!
但是由於所有的變量全部重新分配,導致凡是定時器中斷里面的變量都沒有了!從而導致死機!
所以在跳轉用戶程序的時候關閉了BootLoader里面使用的中斷
如何下載用戶程序到單片機
方式1(使用軟件下載)
上面的例子是先下載BootLoader程序,然后把用戶程序升級進去
現在說一下在下載完BootLoader程序以后,如何把用戶程序下載進去運行
1.下載BootLoader程序到單片機
2.打開用戶程序,調整用戶程序的下載設置,只擦除使用的部分
3.然后點擊下載
4.下載成功以后將會看到正在運行用戶程序
方式2(合並Hex文件)
1.用記事本打開BootLoader程序的hex文件
2.用記事本打開用戶程序的hex文件
3.刪除用戶程序的hex數據的第一行和最后一行
4.最終用戶程序
5.復制修改后的用戶程序的hex數據(全部復制)
6.把復制的數據粘貼到BootLoader文件的下面的位置
7.粘貼后的樣子
8.然后把組合后的hex文件下載到單片機里面即可
結語
這節主要目的是讓用戶徹底了解單片機是如何更新的程序