1. 程式人生 > >stm32實現簡易程式線上更新的原理簡述

stm32實現簡易程式線上更新的原理簡述

stm32要想更新程式,一般的做法就是用j-link或者串列埠下載。那可不可以實現不限通訊方式,實現線上更新呢?

為了實現線上更新的這個功能,我寫了一段簡易的類似BootLoader的程式。原理就是在應用程式執行之前新增一段程式碼,可以選擇一種通訊方式來接收新的應用編譯完成生成的bin檔案,然後固化到flash中,並跳轉到應用程式中執行相應程式碼。又在應用程式程式碼中給出了一個介面,在執行應用程式的時候也可以跳轉到一開始那段程式中再執行更新操作。這樣就可以實現線上更新了。

先來一張STM32Flash的地址匯流排圖
這裡寫圖片描述
可以看到,從0x8000000到0x807FFFF都是flash的儲存範圍。而我們把線上更新的程式放在flash開頭,以便在上電時就對其進行呼叫。

所以,我們要寫的這段更新程式,只需要實現一種通訊方式,接收新的應用程式,然後將其固化到flash中的另一段區域。所以這段程式往往佔用的記憶體空間不大。

在這裡,我們為其分配了一定大小的flash和RAM:這裡寫圖片描述

flash和RAM可以根據你實際的更新程式的大小和佔用資源來選定。

在更新程式內,你任選了一種通訊方式,接收到了應用程式的.bin檔案(.bin檔案可以由MDK在編譯應用程式的時候生成,具體如何做不做贅述)。然後呼叫flash寫操作,將接收到的快取在RAM裡的.bin檔案copy到您的flash中。這個動作非常簡單,只需要呼叫庫函式即可。

下一步就是要呼叫你的應用程式了。應用程式的main函式地址(也就是中斷向量表對應的復位操作)是儲存在MDK生成的.bin檔案中的第四到第八個位元組(因為地址是32bit的)中(前四個位元組儲存這棧頂指標)。所以我們定義一個函式的指標,然後給指標賦值,就可以呼叫了。來看程式碼:

typedef void (*myFunction)(void);

這裡定義的一個myFunction的無參無返回型別的函式指標。這條語句可能寫成typedef myFunction void (*)(void);會更好理解,但是我們還是要遵守C語言的語法。

然後我們定義一個函式型指標變數:

myFunction junpMyAPP;

在編寫我們的應用程式時,我們也可以在MDK中選擇程式的RAM和flash的起始地址和所用空間,只要別和我們之前的更新程式衝突就可以。假設我們給應用程式選定的起始地址為myAPP_ADDR,此時就可以對函式指標執行賦值操作:

junpMyAPP=(myFunction)*(volatile
unsigned int*)(myAPP_ADDR+4);

我們來分析一下這段程式碼。上邊已經提到過,應用程式的main函式地址是儲存在.bin檔案中的第四到第八個位元組中。所以(myAPP_ADDR+4)就是指向main函式存放地址的指標,所以我們用(volatile unsigned int*)表示它是一個32bit的指標,同時用volatile保證起不被編譯器優化。(volatile unsigned int*)前的*表示取此地址的值,也就是main函式的指標的值了,最後用(myFunction)把main函式指標的值強制轉換成先前定義的函式指標型別,就完成了對junpMyAPP函式指標的賦值操作。

接下來,只需要呼叫:junpMyAPP();就可以成功跳轉到我們的應用程式了。在應用程式裡,也可以使用此方法在適當的時候跳轉會我們的更新程式,實現線上更新。

由於本文只簡述了實現簡易線上更新的原理,所以忽略了很多細節,再加之本人水平有限,不足之處,請斧正,謝謝。