最近,在研究F28035平臺(tái)下采用CAN總線的方式更新Flash的方法。取得了一些進(jìn)展,現(xiàn)介紹一下具體的實(shí)現(xiàn)思路。
這里所說的BootLoader并不是芯片自帶的Boot ROM,而是經(jīng)過Boot ROM引導(dǎo),通過Flash方式啟動(dòng)后,執(zhí)行C語言環(huán)境下的MCU程序,也稱為二次BootLoader。BootLoader需要配合PC端上位機(jī)使用,所以本文也涉及到了PC端上位機(jī)的開發(fā)。
下面的內(nèi)容從四個(gè)方面介紹:
1)BootLoader程序?qū)崿F(xiàn)的功能
2)F28035系列芯片的啟動(dòng)流程
3)MCU中BootLoader實(shí)現(xiàn)的方式
4)C#開發(fā)PC端上位機(jī)
硬件:
TI的C2000平臺(tái)下的F28035開發(fā)板(帶CAN2.0總線收發(fā)功能)
CAN盒:周立功USBCAN-2E-U
下載仿真器:XDS100V3
軟件:
CCS10.3.1
Visual Studio 2022
操作系統(tǒng):
WIN10 IoT 企業(yè)版 LTCS(21H2)
一、BootLoader實(shí)現(xiàn)的功能
將MCU中的程序代碼根據(jù)功能,可以劃分成兩個(gè)部分:
1)BootLoader(以下用BL代指)
2)Appilication(以下用app代指)
這兩部分代碼的關(guān)系如下圖所示:
如上圖,當(dāng)MCU上電后,通過復(fù)位向量的跳轉(zhuǎn),進(jìn)入Boot ROM,通過Boot ROM的引導(dǎo),選擇Flash方式啟動(dòng),然后執(zhí)行FlashA扇區(qū)中的BootLoader程序,BL通過CAN總線接收app的源代碼,并寫入到指定的MCU內(nèi)部Flash扇區(qū)(比如C-H扇區(qū)),然后對(duì)app代碼進(jìn)行校驗(yàn),確保接收的app源代碼正確后,通過復(fù)位看門狗,重新啟動(dòng)MCU。MCU重啟后,再經(jīng)過復(fù)位向量--BootROM--BL--app這樣的步驟,最終將MCU的軟硬件的資源交給app,app來完成用戶要求的功能。
Flash存儲(chǔ)區(qū)域經(jīng)過這樣劃分,保證了BL與app的隔離。app可以獨(dú)立于BL進(jìn)行開發(fā),只要在app的CMD文件中將FlashA扇區(qū)空閑出來,不用就行,并不需要更改其它的地址空間中的內(nèi)容。而且app也可以不用BL加載,直接通過TI官方的下載器,下載到MCU,app代碼也能正常工作,增加了BL使用的可選擇性。
至于CMD文件如何編寫、如何從BL跳到app的入口等等,這些技術(shù)細(xì)節(jié),會(huì)在后面詳細(xì)闡述。
總結(jié)一下BL寫入Flash的具體步驟:
1)先將BL編譯完成的.out文件通過下載器(如XDS100V3)下載到MCU中,成功后,MCU關(guān)電。
2)連接好CAN盒,啟動(dòng)C#編寫的上位機(jī)程序,選擇好對(duì)應(yīng)的要寫入MCU的app程序(.out)文件,此時(shí)上位機(jī)開始嘗試主動(dòng)與MCU通訊,通過CAN發(fā)送握手信號(hào)。
3)MCU上電,接收到上位機(jī)發(fā)送的握手信號(hào)后,上位機(jī)和MCU開始通訊,MCU接收完整的app代碼文件,并寫入Flash指定扇區(qū)。
4)app代碼校驗(yàn)成功后,MCU通過復(fù)位看門狗,使MCU重啟。
5)MCU重啟后,首先進(jìn)入BL,當(dāng)MCU在指定時(shí)間內(nèi)沒有接收到上位機(jī)發(fā)出的握手信號(hào)時(shí),BL會(huì)將程序指針指向app的入口地址。然后app程序開始執(zhí)行。
6)當(dāng)app沒有被成功寫入時(shí),則始終停留在BL程序中。
二、F28035的啟動(dòng)流程
理解MCU上電后的啟動(dòng)流程,對(duì)于開發(fā)BootLoader來說是非常重要的。對(duì)于C2000系列的MCU來說,啟動(dòng)流程基本一致,只是個(gè)別的跳轉(zhuǎn)地址不一致。這些不一樣的地方需要查找對(duì)應(yīng)型號(hào)的MCU手冊(cè)來確定。下面就以F28035芯片為例來說明:
F28035 MCU內(nèi)存映射如下:
可看到此表格的最下端(地址:0x3F FFC0至0x3F FFFF),是上電啟動(dòng)后CPU的中斷向量表(Vector)。當(dāng)MCU上電后,首先將程序指針,指向此區(qū)域的0x3F FFC0處。此過程是固化在MCU硬件中的,不可改變。在0x3F FFC0處只能放下兩個(gè)字節(jié)(16Bit)數(shù)據(jù),功能就是讓程序指針指向Boot ROM區(qū)域的InitBoot函數(shù)(0x3F F4B0)。下圖是Boot ROM區(qū)域的放大:
注意根據(jù)不同型號(hào)的MCU,InitBoot函數(shù)(0x3F F4B0)地址也是不同的,具體是多少要查找手冊(cè),幸運(yùn)的是這個(gè)跳轉(zhuǎn)也是硬件自動(dòng)完成的,不需要干預(yù)。
從上圖中,可以看到紅框中的區(qū)域就是Boot ROM了。這個(gè)區(qū)域是固化(只讀)在內(nèi)存中的,用戶不能寫入數(shù)據(jù)。從Boot ROM內(nèi)部的功能劃分來看,主要實(shí)現(xiàn)以下幾部分功能:
1)Boot ROM版本和Boot ROM校驗(yàn)
2)Flash API庫:我們需要的Flash擦除與寫入函數(shù)就在此庫中。
3)Boot引導(dǎo)函數(shù):包括InitBoot函數(shù)和其它的功能函數(shù)。
4)定點(diǎn)型的數(shù)學(xué)函數(shù):如sin、cos等。
5)定點(diǎn)型的數(shù)學(xué)表格。
最重要的就是2)和3)這兩項(xiàng)。
Flash API庫里包含著一些Flash相關(guān)的操作函數(shù),如擦除、寫入、數(shù)據(jù)校驗(yàn)等功能。在BL代碼中Flash操作需要的函數(shù)都在這里能夠找到。當(dāng)然,也可以在編譯BL代碼時(shí),從芯片外部引入TI官方提供的專門FlashAPI庫,但是這樣就增加了BL的代碼體積。最好就是用這個(gè)包含在Boot ROM中的FlashAPI。如果要用BootROM中的FlashAPI,需要將一個(gè)符號(hào)庫引入到BL的工程文件夾中。
當(dāng)程序指針指向InitBoot函數(shù),就開始依次執(zhí)行下面的功能:
上圖中SelectBootMode()函數(shù)做了簡化,具體技術(shù)細(xì)節(jié)請(qǐng)參見手冊(cè)。
_c_int00()在跳轉(zhuǎn)到程序入口之前完成了以下的工作
1) 定義系統(tǒng)棧.stack,并初始化棧指針,配置相關(guān)寄存器
2) 初始化全局變量(.cinit)
3) 若使用C++,還會(huì)完成全局對(duì)象構(gòu)造(.pinit)
4) 調(diào)用main函數(shù)運(yùn)行C程序
5) 當(dāng)main函數(shù)return時(shí),調(diào)用exit函數(shù)
注意:_c_int00()是在rts2800_ml.lib庫中。當(dāng)修改程序代碼后,再編譯時(shí),程序的入口地址就可能和上次的不一樣。到此,MCU就完成了從上電到C程序執(zhí)行的全過程。
BL與app各自編譯后的入口地址是不一樣的。
因?yàn)锽L的程序代碼先下載到MCU中,app的代碼通過BL的CAN總線,下載到MCU的Flash扇區(qū)里,所以程序指針先指向BL的_c_int00(),執(zhí)行BL的代碼,然后BL再將程序指針指向app的_c_int00(),建立app的C語言環(huán)境。即app的內(nèi)存分配方式會(huì)完全覆蓋BL的內(nèi)存分配方式,所以app和BL這兩個(gè)工程的CMD編寫中,除了各自代碼存放的Flash扇區(qū)要隔離開以外,象RAMM0、1和RAML0-3分配的方式可以完全不一樣,最終app的內(nèi)存分配也會(huì)覆蓋BL的內(nèi)存分配,所以app通過BL下載到指定Flash后能正常運(yùn)行,而此后BL代碼將不能再執(zhí)行,除非MCU重新上電或讓app將程序指針指向BL的入口地址。(待續(xù))