|
目錄 1
1、如何使用內(nèi)部的Boot Loader。 2
2、通過USB DFU 方式下載程序 4
3、以串口方式升級(jí)程序 7
4、通過以太網(wǎng)接口升級(jí)程序 8
5、I2C 和SSI 方式下載程序 9
6、從應(yīng)用程序進(jìn)入Boot Loader 11
結(jié)語(yǔ) 13
附錄A 14
Boot Loader 是在用戶應(yīng)用程序開始運(yùn)行之前運(yùn)行的一段小程序。通過這段小程序,我們可以初始化硬件設(shè)備和軟件環(huán)境,從而將系統(tǒng)的軟硬件環(huán)境帶到一個(gè)合適的工作狀態(tài),以便執(zhí)行某些特定的功能。一般來說就是用來升級(jí)程序,引導(dǎo)程序或操作系統(tǒng)等。
LM3S 系列的芯片有些具有固化在內(nèi)部ROM 的Boot Loader,有些則沒有。根據(jù)芯片相應(yīng)的數(shù)據(jù)手冊(cè)可以很容易的確定這個(gè)問題。通過固化在ROM 中的Boot Loader,可以通過串口(UART0)、SSI(SSI0)、I2C(I2C0)、以太網(wǎng)將程序下載FLASH 中,而不需要使用JTAG 調(diào)試引腳。下面我們分類討論關(guān)于Boot Loader 的幾個(gè)問題。
1、如何使用內(nèi)部的Boot Loader。
對(duì)于有內(nèi)部Boot Loader 的芯片來說,可能會(huì)遇到如下的問題:
1、使用內(nèi)部的Boot Loader 有幾種接口可供升級(jí)。
2、如何使用內(nèi)部的Boot loader。
先回答第一個(gè)問題,關(guān)于這個(gè)問題前面提到了一句,內(nèi)部Boot Loader 支持串口(UART0)、SSI(SSI0)、I2C(I2C0)、以太網(wǎng)下載程序,但是并不支持USB DFU 和CAN 方式。
再回答第二個(gè)問題。
要想弄清楚如何使用內(nèi)部Boot Loader,我覺的有必要先說說內(nèi)部Boot Loader 是如何工作的。
我們知道,在MCU 復(fù)位后讀取0x0000 0000 地址處的數(shù)據(jù)設(shè)置堆棧,在讀取0x0000 0004 地址的數(shù)據(jù)設(shè)置PC 值,然后用戶程序開始執(zhí)行了。但是,其實(shí)在上電后任何復(fù)位內(nèi)核的復(fù)位操作中,MCU內(nèi)部還悄悄的執(zhí)行了一些其他的操作。具體來說就是:
1、先判斷ROM 控制寄存器(RMCTL)的BA 位(初始狀態(tài)為1)的值。如果為1,則將0x0100 0000( 內(nèi)部ROM 的地址)映射到0x0000 0000 地址,如果位0 則將Flash 映射到0x0000 0000 地址。
2、因?yàn)閺?fù)位后RMCTL 的BA 位為1,所以此時(shí)是將ROM 空間映射到0 地址,執(zhí)行ROM 啟動(dòng)序列。 而ROM 啟動(dòng)序列的第一步是將BA 位清零,將ROM 映射到0x0000 0000 地址處,將Flash 映射到0 地址出。
3、設(shè)置好ROM 和Flash 的映射關(guān)系后就開始讀取啟動(dòng)配置寄存器(BOOTCFG)的內(nèi)容,如果EN 位被置位,那么就判斷指定管腳的狀態(tài)與指定極性相比較。
4、如果指定的管腳與指定的極性相匹配則執(zhí)行ROM 中的Boot Loader。
5、如果管腳的狀態(tài)與極性不匹配,則檢查0x0000 0004 地址的內(nèi)容來判斷Flash 是否已經(jīng)被編程,如果該地址的數(shù)據(jù)是0xFFFF FFFF,則表明Flash 沒有被編程過,那么執(zhí)行ROM 中的Boot Loader。
6、如果0x0000 0004 地址的數(shù)據(jù)是有效的,則表明Flash 已經(jīng)被編程了,那么就從0x0000 0000 處讀取堆棧指針,從0x0000 0004 處讀取PC 值,開始執(zhí)行用戶程序。
看了上述啟動(dòng)序列以后我們明白了如下幾個(gè)問題:
1、當(dāng)給MCU 上電以后總是要執(zhí)行ROM 中的啟動(dòng)序列的。
2、ROM 的啟動(dòng)序列可以引導(dǎo)ROM 中的Boot Loader 的。
3、執(zhí)行內(nèi)部Boot Loader 是有兩個(gè)條件的,一個(gè)是檢測(cè)到了指定引腳上的指定電平狀態(tài),另一個(gè)是內(nèi)部Flash 沒有被編過程。
4、如果沒有設(shè)定BOOTCFG 寄存器來檢測(cè)指定引腳的電平,而Flash 已經(jīng)被編程了則內(nèi)部ROM 的Boot Loader 是不會(huì)再執(zhí)行了,除非用JTAG 等調(diào)試接口將芯片“解鎖”。
根據(jù)以上,我們要想讓內(nèi)部ROM 里的Boot Loader 總是執(zhí)行。那么最好的,可能也是唯一的方法就是給BOOTCFG 寄存器寫入特定的內(nèi)容來檢測(cè)某個(gè)引腳的電平極性。通過這個(gè)引腳的電平極性匹配關(guān)系來決定是否用內(nèi)部ROM 中的Boot Loader 來升級(jí)程序還是引導(dǎo)用戶程序。
好了,大政方針已經(jīng)確定,下面就是該討論如何付諸實(shí)施了。
稍微認(rèn)真看一下芯片的數(shù)據(jù)手冊(cè),就可以得出如下的方法來給BOOTCFG 編程。以LM3S9B96 芯片為例,第一步是將BOOTCFG 的地址寫入到FMA 寄存器,然后將對(duì)ROM 內(nèi)的Boot Loader 的配置 也就是要寫入BOOTCFG 的值寫入FMD 寄存器,最后給FMC 寄存器寫入相應(yīng)的密鑰(LM3S9B96 的密 鑰為0xA442)和確認(rèn)位。相應(yīng)的例程可能會(huì)是這個(gè)樣子的:
//write the BOOTCFG flash register to enable PA1 low to enable the ROM boot loader at power on
unsigned long regVal;
regVal = HWREG(0x400FE000 + 0x1D0); //BOOTCFG
if (regVal & 0x80000000) //committed yet?
{
HWREG(0x400FD000 + 0x000) = 0x75100000; //FMA=BOOTCFG "address"
HWREG(0x400FD000 + 0x004) = FLASH_BOOTCFG_PORT_A | FLASH_BOOTCFG_PIN_1 | FLASH_BOOTCFG_DBG1; //FMD=BOOTCFG
value (PB5 low/DBG enabled)
HWREG(0x400FD000 + 0x008) = 0xA4420008; //FMC=key+commit
SysCtlDelay(100 * SysCtlClockGet() / (3 * 1000));
}
在第一次給芯片寫程序的時(shí)候?qū)⑦@段代碼加到程序的開始部分,當(dāng)程序運(yùn)行的時(shí)候會(huì)首先開啟內(nèi)部的Boot Loader,這樣以后下載程序的時(shí)候就可以不需要調(diào)試接口來下載程序了,當(dāng)然相關(guān)的頭文件還是要包含進(jìn)來的。
下面對(duì)程序做一下簡(jiǎn)要的說明:
首先定義一個(gè)unsigned long 型的變量,然后讀取當(dāng)前BOOTCFG 寄存器的值,并判讀它的最高為是否為1,如果為1 則表明BOOTCFG 沒有被提交過,也就是說還沒有設(shè)定好每次都從內(nèi)部ROM 中的Boot Loader 啟動(dòng),那么就要對(duì)BOOTCFG 配置,否則就是已經(jīng)配置好了BOOTCFG,則不需要重新配置了。
對(duì)BOOTCFG 寄存器內(nèi)容提交的過程是這樣的,首先要將FMA 寄存器的值放入提交BOOTCFG 寄存器的地址,即0x7510 0000,有人可能會(huì)對(duì)0x7510 0000 這個(gè)地址有疑惑,為什么不是0x400FE1D0這個(gè)地址呢,根據(jù)數(shù)據(jù)手冊(cè)中內(nèi)部存儲(chǔ)器那一章的非易失性存儲(chǔ)器的編程那一句里所講,里面列出了一個(gè)表格,指出如果要提交BOOTCFG 寄存器,那么FMA 寄存器里的值應(yīng)該是0x7510 0000,而他的數(shù)據(jù)源則是FMD,也就是說把要寫入BOOTCFG 寄存器的值放到FMD 寄存器中。
If 語(yǔ)句的第二句就是配置FMD 的值的,采用了很直觀的方式配置,最后已經(jīng)就是寫入對(duì)BOOTCFG編程的密鑰和確認(rèn)信息了。
至此,對(duì)內(nèi)部Boot Loader 的配置已經(jīng)完成了,應(yīng)用的時(shí)候,首先給指定的管腳加上指定的電平極性,然后啟動(dòng)就會(huì)進(jìn)入Boot Loader,此時(shí)通過前面說過的串口連接電腦就可以用LM FlashProgrammer 來對(duì)MCU 進(jìn)行下載程序了。至于下載程序的方法和后面的要將的類似,如果不太明白的話可以參考后面的內(nèi)容。
有個(gè)問題需要單獨(dú)說明一下:當(dāng)使用ROM 中的Boot Loader 時(shí),系統(tǒng)時(shí)鐘使用的是內(nèi)部的振蕩器,它的頻率是16MHz(±1%)。之所以要提這個(gè)問題,是因?yàn)橐源蟹绞綗龑懗绦虻臅r(shí)候(包括UART,I2C,SSI)。它們通信都是要一定的速率的,如果超過了可能沒有辦法正確執(zhí)行。
使用UART 接口的時(shí)候,系統(tǒng)時(shí)鐘不能低于UART 速率的32 倍,換句話說也就是UART 的速率不能超過500K(16M / 32)。使用SSI 接口的時(shí)候系統(tǒng)時(shí)鐘不能低于SSI 的12 倍,也就是SSI 的速率不能超過1.3M(16M / 12)。I2C 稍微有點(diǎn)特殊,根據(jù)數(shù)據(jù)手冊(cè)上說,它可以運(yùn)行在100K 和400K 的速 率模式下,因此,它的最高速率是400K 。順便提一句,使用串行方式的時(shí)候一般都有類似主從的概念,Boot Loader 通常都運(yùn)行在從機(jī)模式下,I2C 在從機(jī)模式下使用的默認(rèn)地址是0x42。
2、通過USB DFU 方式下載程序
對(duì)于沒有內(nèi)部Boot Loader 的芯片來說,那么你用起來相對(duì)來說就不需要考慮那么多了,安安心心的把Boot Loader 下載到Flash 里運(yùn)行吧。
要說明的是內(nèi)部的Boot LoadeR 不支持USB DFU。要想使用USB DFU 的方式來升級(jí)程序不管內(nèi)部ROM 中有沒有Boot Loader 都得把他下載到Flash 中。
使用USB DFU 下載程序的方式如下:
首先打開boot_usb 目錄下面的工程文件。打開bl_config.h 這個(gè)文件,看清楚里面的配置,這里面的配置起著至關(guān)重要的決定。它的每一行都有很長(zhǎng)的英文解釋。要做的就是記住APP_START_ADDRESS 定義的值,它關(guān)系到將來應(yīng)用程序的下載地址的修改。然后把ENABLE_UPDATE_CHECK 的這個(gè)定義給使能,接著使能FORCED_UPDATE_PERIPH、 FORCED_UPDATE_PORT、FORCED_UPDATE_PIN、FORCED_UPDATE_POLARITY、FORCED_UPDATE_WPU這幾個(gè)的定義。這幾個(gè)定義分別定義了要檢查是否升級(jí)的引腳的端口模塊、端口、引腳序號(hào)、匹配電平類型和上下拉電阻。完成之后就可以編譯并下載程序到MCU 了。
完成以上步驟之后,用一根USB 線將開發(fā)板和電腦的USB 線相連,將bl_config.h 中設(shè)定的引腳給定升級(jí)所需要的電平,重啟開發(fā)板。如果之前沒有安裝過USB DUF 的驅(qū)動(dòng)那么需要先安裝USB DFU的驅(qū)動(dòng),該驅(qū)動(dòng)所在位置為“光盤目錄/tools/windows_drivers ”。安裝好驅(qū)動(dòng)之后在設(shè)備管理器中應(yīng)該能發(fā)現(xiàn)如圖1 所示的設(shè)備:
0.png (25.88 KB, 下載次數(shù): 77)
下載附件
2018-9-1 03:28 上傳
圖1 安裝好USB DFU 驅(qū)動(dòng)后出現(xiàn)的設(shè)備
當(dāng)發(fā)現(xiàn)該項(xiàng)不正常的是需要重新安裝驅(qū)動(dòng)確保驅(qū)動(dòng)正確安裝。安裝好驅(qū)動(dòng)之后打開LM Flash Programmer 軟件(這個(gè)軟件的安裝包在“關(guān)盤目錄/tools/LMFlashProgrammer”下面,也可以在TI或流明官網(wǎng)去下載),會(huì)在configuration 選項(xiàng)卡里的Interface 一欄的下拉菜單中找到USB DFU 這一項(xiàng),選擇該項(xiàng)之后Select Device 里面會(huì)出現(xiàn)一個(gè)設(shè)備,如圖2 所示:
0.jpg (21.93 KB, 下載次數(shù): 95)
下載附件
2018-9-1 03:28 上傳
圖2 LM Flash 中的USB DFU
如果后面沒有出現(xiàn)設(shè)備,可以重啟開發(fā)板并點(diǎn)Refresh 這個(gè)按鈕試試。如果能正確的走到這一步, 說明可以通過USB DFU 方式下載程序了。下載的方法是點(diǎn)LM 的第二個(gè)選項(xiàng)卡Program,在Select .binfile 中通過Browse 尋找要燒寫的.bin 文件。特別要注意的是Program Address Offset 后面的值,該值代表的是燒寫的程序的起始地址。前面我們已經(jīng)說過,還記得bl_config.h 中的APP_START_ADDRESS
這個(gè)定義嗎,它就是定義的用戶程序的起始地址,因此,此處一定要填寫bl_config.h 定義的這個(gè)值。 上面兩個(gè)是校驗(yàn)和編程完畢后重啟MCU,隨你怎么選擇,我是都選上了。相關(guān)圖片如圖3 所示:
0.jpg (15.14 KB, 下載次數(shù): 91)
下載附件
2018-9-1 03:29 上傳
圖3 USB DFU 燒寫程序的設(shè)置
設(shè)置完畢之后點(diǎn)擊Program 就開始對(duì)MCU 編程了。一般來說編程和校驗(yàn)是不會(huì)有問題的。最多的問題還是出在應(yīng)用程序中。在應(yīng)用程序中要修改它的起始地址,具體來說就是將連接問的首地址改為bl_config.h 中定義的地址,此處為0x1800。修改的方法如下:
1、KEIL RMDK 環(huán)境中
修改的方法是在需要修改的工程的Options 的Linker 選項(xiàng)卡中,去掉Use Memmory Layout…前面的復(fù)選框中的勾,然后點(diǎn)擊Scatter File 后面的Edit 來編輯該工程的分散加載文件。如圖4 所示:
0.jpg (21.71 KB, 下載次數(shù): 79)
下載附件
2018-9-1 03:29 上傳
圖4 修改分散加載文件
點(diǎn)擊Edit 之后在彈出的分散加載文件,一般是下面的樣子的,如圖5 所示:
0.jpg (20.9 KB, 下載次數(shù): 80)
下載附件
2018-9-1 03:29 上傳
將其中用紅色方框標(biāo)出來的兩個(gè)值都改為0x0000 1800,然后重新編譯即可生成USB DFU 下載或用其他(非內(nèi)部ROM 中的)Boot Loader 下載程序所需的bin 文件。
2、在IAR 環(huán)境中
IAR 的分散加載文件是以.icf 為后綴的文本文件,這個(gè)文件存放的位置一般在工程的根目錄下面,如果沒有的話,可以在工程上右擊選擇Options,然后再點(diǎn)擊Linker,就會(huì)出現(xiàn)icf 文件所在的地址了。如圖6 所示:
0.png (22.74 KB, 下載次數(shù): 91)
下載附件
2018-9-1 03:30 上傳
圖6 IAR 分散加載文件的地址
因?yàn)镮AR 只能用外部的記事本或其他的文本編輯器打開,所以這里點(diǎn)擊Edit 是沒有用的( 目前我的版本是這樣的),用記事本或其他文本編輯器打開這個(gè)文件之后修改Flash 定義的那條語(yǔ)句,如下圖所示:
0.jpg (7.68 KB, 下載次數(shù): 86)
下載附件
2018-9-1 03:30 上傳
圖7 IAR 要修改的地方
將紅色方框中的值修改為bl_config.h 中定義的值,比方說0x0000 1800。然后重新編譯即可下載到單片機(jī)了。
如果沒有使用內(nèi)部ROM 中的Boot Loader 則它在MCU 復(fù)位的時(shí)候首先執(zhí)行,判斷定義的管腳是 否符合相應(yīng)的電平,來確定是否需要給程序升級(jí)。如果是的話就會(huì)初始化USB 等外設(shè),然后等待電 腦往Flash 里下載程序,否則的話就直接引導(dǎo)應(yīng)用程序運(yùn)行。
3、以串口方式升級(jí)程序
無論是放在ROM 中還是Flash 的Boot Loader 都支持以串口的方式下載程序。在第一節(jié)里已經(jīng)明確的講了內(nèi)部ROM 中的Boot Loader 是如何運(yùn)行的。無論是執(zhí)行內(nèi)部ROM 中的Boot Loader 還是執(zhí)行Flash 中的Boot Loader 用串口來升級(jí)程序。它們執(zhí)行的原理都是差不多的,都是先檢查預(yù)先定義好的管腳電平(ROM 中的Boot Loader 也可能是檢查空片),然后確定是否需要升級(jí)應(yīng)用程序。當(dāng)檢測(cè)到了升級(jí)的條件就會(huì)設(shè)置串口及其他的外設(shè),然后等待電腦的串口發(fā)送命令或數(shù)據(jù)。
無論你的電腦上用的是自帶的串口還是用USB 轉(zhuǎn)的串口,只要有就可以用LM Flash Programmer下載應(yīng)用程序。首先打開LM Flash Programmer,在configuration 選項(xiàng)卡里的Interface 一欄里選擇Serial(UART),點(diǎn)擊后面的Device Manager 按鈕,在彈出的設(shè)備管理器里查看要使用的串口是哪一個(gè),比方說我用的是USB 轉(zhuǎn)的串口。如下圖所示:
0.png (7.9 KB, 下載次數(shù): 90)
下載附件
2018-9-1 03:36 上傳
圖8 我電腦上的串口
所以在端口配置的時(shí)候COM Port:應(yīng)該選擇COM1,波特率應(yīng)該選擇你芯片上實(shí)際配置串口的波特率,如果是Boot Loader 里面配置了自動(dòng)適應(yīng)波特率的話,則Disable Auto Band Support 前面的復(fù)選框應(yīng)該去掉。如果波特率是定死的話則應(yīng)該勾選該項(xiàng),然后再Band Rate:一項(xiàng)里選擇相應(yīng)的波特率。順便提一句,如果芯片是空片,而且BOOTCFG 寄存器沒有被修改過,此時(shí)的執(zhí)行內(nèi)部BootLoader 的時(shí)候波特率是自動(dòng)適應(yīng)的。至于最后一個(gè)Transfer Size 采用默認(rèn)的即可。例如我的串口配置情況是這樣的:
0.jpg (8.49 KB, 下載次數(shù): 93)
下載附件
2018-9-1 03:36 上傳
圖9 我的串口配置情況
配置好串口之后,就可以在Program 選項(xiàng)卡里選擇要下載的程序和要下載程序的地址了。如下圖所示:
0.jpg (12.61 KB, 下載次數(shù): 89)
下載附件
2018-9-1 03:37 上傳
圖10 下載程序界面
這個(gè)界面和之前的USB DFU 方式下載程序差不多,和后面要講的下載方式也類似。就不做過多介紹了,但是有一點(diǎn)要著重說明一下。那就是下載地址的問題。
通過ROM 或Flash 中下載程序的時(shí)候,這個(gè)下載地址是不一樣的。在ROM 中運(yùn)行Boot Loader的時(shí)候可以視為Flash 是空的,下載地址應(yīng)該是0x0(要是這個(gè)地址上你放了別的東西如boot_usb,此時(shí)就另當(dāng)別論了),如果用的是Flash 里的Boot Loader,因?yàn)槟愕腂oot Loader 已經(jīng)在0x0 這個(gè)地址上了,如果你不想把這個(gè)Boot Loader 覆蓋掉的話(更新Boot Loader 除外)那么你就應(yīng)該把這個(gè)地址設(shè)定為bl_config.h 中APP_START_ADDRESS 設(shè)定的程序起始地址:比如說0x1800。這個(gè)要根據(jù)實(shí)際情況靈活運(yùn)用,一般來說如果用ROM 中的Boot Loader 則該地址為0,如果是Flash里的Boot Loader則該地址為bl_config.h 中設(shè)定的值。
4、通過以太網(wǎng)接口升級(jí)程序
ROM 中的Boot Loader 也支持以太網(wǎng)接口的方式升級(jí)程序,當(dāng)然Flash 中的也支持。下面就來說一說如何通過網(wǎng)口來升級(jí)程序。
通過網(wǎng)口升級(jí)程序有兩個(gè)問題要說明一下:
1、地址問題:通過網(wǎng)口下載程序,應(yīng)用程序的地址根據(jù)是ROM 的中的Boot Loader 還是Flash中的Boot Loader 會(huì)有所區(qū)別。如果是ROM 中的Boot Loader,下載到Flash 的地址必須是從0 開始的,這個(gè)不能改變。因此編譯應(yīng)用程序的時(shí)候,SCT 或ICR 中的地址要設(shè)置為0。如果是用的Flash中的Boot Loader 則下載地址位bl_config.h 中APP_START_ADDRESS 定義的地址,一般是0x1800。
2、也是地址問題,不過和第一個(gè)的地址不是同一類型的地址,這個(gè)地址問題指的是芯片的MAC地址。我們知道,以太網(wǎng)通信有兩個(gè)重要的地址IP 地址和MAC 地址。MAC 地址指的就是網(wǎng)卡的物理地址。如果使用內(nèi)部ROM 中的Boot Loader 的話,這個(gè)MAC 地址是放在USER0/USER1 中的,它們的格式是U0B0-U0B1-U0B2-U1B0-U1B1-U1B2,這里的U0B0 指的是USER0 的7:0 位,也可以說是Byte 0,U0B1 指的是USER0 的15:8 位,也可以說是Byte 1,其他的依此類推。但是有一個(gè)重要的問題,就是如果沒有設(shè)置USER0/USER1 的時(shí)候,MAC 地址的默認(rèn)值為00-1a-b6-00-64-00,這個(gè)一定要記住。也就是說使用ROM 中的Boot Loader 下載程序的時(shí)候是不能把芯片MAC 地址設(shè)為 FF-FF-FF-FF-FF-FF 的。而如果使用的是Flash 中的Boot Loader 的話,則芯片的MAC 地址可以是全F, 也可以是bl_config.h 中指定的地址。
下面就來看看如何使用LM Flash Programmer 通過網(wǎng)口來下載程序:
首先,將電腦和開發(fā)板的網(wǎng)口連接,然后打開開發(fā)板電源。
接著打開LM Flash Programmer,在第一個(gè)選項(xiàng)卡configuration 里的Interface 里面選擇Ethernet,在下面的Ethernet Adapter 里面選擇和開發(fā)板相連的網(wǎng)口,然后在Client IP Address 里面填寫和該網(wǎng)卡的IP 地址在同一個(gè)網(wǎng)段內(nèi)的其他IP 地址,在Client MAC Address 里面填寫相應(yīng)的MAC 地址:如果用的是ROM 中的Boot Loader而且之前沒有對(duì)USER0/USER1修改過的話此處填寫芯片默認(rèn)的MAC地址00-1a-b6-00-64-00,否則填寫修改過的MAC 地址。如果用的是Flash 里的Boot Loader 而且在bl_config.h 中沒有設(shè)置MAC 地址,此處可填寫全F,格式同前面的格式。相關(guān)圖片請(qǐng)參考圖11.1和圖11.2。
0.jpg (32.13 KB, 下載次數(shù): 84)
下載附件
2018-9-1 03:37 上傳
在第二個(gè)選項(xiàng)卡Program 里選擇要下載的BIN 文件,我們注意到,這里的Options 是灰色的,下載程序的地址是無法修改的。在寫應(yīng)用程序的時(shí)候注意連接地址下載就沒有問題。當(dāng)使用以太網(wǎng)接口下載或升級(jí)程序的時(shí)候,LM Flash 會(huì)用到BOOTP 和TFTP 協(xié)議,它們和正常的以太網(wǎng)環(huán)境共存不會(huì)造成任何問題(當(dāng)然會(huì)占用一點(diǎn)點(diǎn)的帶寬),它們使用的都是標(biāo)準(zhǔn)的協(xié)議。BOOTP協(xié)議用來確定服務(wù)器端和客戶端的IP 地址,以及固件的映像名稱,它使用UDP/IP 數(shù)據(jù)包在服務(wù)器和客戶端通信。TFTP 也使用UDP/IP 數(shù)據(jù)包在服務(wù)器和客戶端通信,它將固件的映像傳遞給客戶端。這里的客戶端指的就是Boot Loader。
5、I2C 和SSI 方式下載程序
前面介紹了幾種通過LM Flash Programmer 下載程序的方法,這一節(jié)將要介紹的是通過I2C 和SPI接口來下載程序的方法。之所以要把他們列在一起來說是因?yàn)樗鼈冇羞@么幾個(gè)共同點(diǎn):
1、都是串行方式發(fā)生和接收數(shù)據(jù)
2、使用相同的串行協(xié)議(事實(shí)上,UART 使用的也是這樣的協(xié)議)
3、它們?cè)陔娔X上沒有相應(yīng)的接口,不能用LM Flash 來下載。只能通過一個(gè)芯片給另一個(gè)升級(jí)。
基于以上幾種原因,我把這兩個(gè)綜合起來將,只是大概講講它們通信的過程。通信就包括發(fā)送和接收數(shù)據(jù)包。
發(fā)送數(shù)據(jù)包的過程:
1、先發(fā)送要發(fā)送的包的大小,它的值時(shí)整個(gè)數(shù)據(jù)數(shù)據(jù)部分的長(zhǎng)度+2 個(gè)字節(jié)。
2、發(fā)送數(shù)據(jù)部分的校驗(yàn)和。
3、發(fā)送數(shù)據(jù)部分。
4、等待一個(gè)應(yīng)答信號(hào),確認(rèn)對(duì)方是否正確接收到了數(shù)據(jù)。
接收數(shù)據(jù)包的過程:
1、等待接收一個(gè)非零的數(shù)據(jù)。這非常重要,因?yàn)樵O(shè)備(從機(jī))會(huì)在發(fā)送和接收一個(gè)數(shù)據(jù)之間發(fā)送一個(gè)零字節(jié)。第一個(gè)接收到的字節(jié)表示將要接收的數(shù)據(jù)包的大小。
2、接收第二個(gè)字節(jié),該字節(jié)代表的是將要接收到的數(shù)據(jù)的校驗(yàn)和。
3、接收剩余的數(shù)據(jù),長(zhǎng)度為包的大小(即接收到的第一個(gè)字節(jié)) – 2 個(gè)字節(jié)。比方說第一個(gè)字節(jié)接收到的是3,那么實(shí)際上接收到的數(shù)據(jù)部分長(zhǎng)度為3-2=1。
4、計(jì)算接收到的數(shù)據(jù)部分的校驗(yàn)和,和接收到的校驗(yàn)(也就是第二個(gè)字節(jié))和是否相吻合,
5、如果校驗(yàn)和正確的話則返回(ACK)信號(hào),否則返回(NAK)信號(hào)。告訴主機(jī)是否正確的接收到了數(shù)據(jù)。
以上兩個(gè)過程大致描述了主機(jī)和從機(jī)是如何通信的,但是這個(gè)只是實(shí)際的數(shù)據(jù)包的通信過程, 事實(shí)上主機(jī)在給從機(jī)發(fā)送數(shù)據(jù)包之前都會(huì)先發(fā)送一個(gè)命令字節(jié)。命令字節(jié)及其代表的含義如下:
COMMAND_PING 該命令長(zhǎng)度是一個(gè)字節(jié),用來從Boot Loader 接收一個(gè)字節(jié),表明它
=0x20 們成功建立了通信。它的格式是這樣的:
unsigned char ucCommand[1];
ucCommand[0] = COMMAND_PING;
COMMAND_DOWNLOAD 該命令的長(zhǎng)度為9 個(gè)字節(jié),用來告訴Boot Loader要把數(shù)據(jù)放到哪里,
=0x21 共有多少數(shù)據(jù)。該命令共包含了兩個(gè)32 位的值,都是先發(fā)送MSB。
該命令同時(shí)還會(huì)擦除一段Flash 空間,因此會(huì)導(dǎo)致發(fā)送ACK/NAK 的
時(shí)間會(huì)延長(zhǎng),所以它的后面要跟一個(gè)COMMAND_GET_STATUS 命令,
確保命令成功執(zhí)行。
該命令的格式是這樣的:
unsigned char ucCommand[9];
ucCommand[0] = COMMAND_DOWNLOAD;
ucCommand[1] = Program Address [31 : 24];
ucCommand[2] = Program Address [23 : 16];
ucCommand[3] = Program Address [15 : 8];
ucCommand[4] = Program Address [7 : 0];
ucCommand[5] = Program Size [31 : 24];
ucCommand[6] = Program Size [23 : 16];
ucCommand[7] = Program Size [15 : 8];
ucCommand[8] = Program Size [7 : 0];
COMMAND_RUN 該命令告訴Boot Loader 轉(zhuǎn)到某一個(gè)地址開始執(zhí)行。該命令包含一個(gè)
=0x22 32 位的值,表示要轉(zhuǎn)到的地址,先發(fā)送MSB。
該命令的格式是這樣的:
unsigned char ucCommand[5];
ucCommand[0] = COMMAND_RUN;
ucCommand[1] = Run Address[31 : 24];
ucCommand[2] = Run Address[23 : 16];
ucCommand[3] = Run Address[15: 8];
ucCommand[4] = Run Address[7 : 0];
COMMAND_GET_STATUS 該命令返回最后一個(gè)命令執(zhí)行的狀態(tài),一般來說每發(fā)送一個(gè)命令都
=0x23 要跟隨這么一個(gè)命令確定上一個(gè)命令是否被正確執(zhí)行等。Boot
Loader 發(fā)送的相應(yīng)包含當(dāng)前狀態(tài)的一個(gè)字節(jié)的數(shù)據(jù)包。
它的格式是這樣的:
unsigned char ucCommand[1];
ucCommand[0] = COMMAND_GET_STATUS;
返回的狀態(tài)包括如下幾種:
COMMAND_RET_SUCCESS
COMMAND_RET_UNKNOWN_CMD
COMMAND_RET_INVALID_CMD
COMMAND_RET_INVALID_ADD
COMMAND_RET_FLASH_FALL
COMMAND_SEND_DATA 該命令跟隨在COMMAND_DOWNLOAD,如果數(shù)據(jù)很多也可以跟隨
=0x24 在另一個(gè)COMMAND_SEND_DATA 命令之后,如果連續(xù)發(fā)送數(shù)據(jù)則
數(shù)據(jù)的地址會(huì)遞增,并且續(xù)傳之前編程的位置。它每次最多傳輸252
個(gè)字。調(diào)用該命令之前應(yīng)該先調(diào)用COMMAND_GET_STATUS 命令,
以確保數(shù)據(jù)成功編入Flash 中。如果Boot Loader 返回了一個(gè)NAK 信
號(hào),則它不會(huì)增加當(dāng)前的地址,允許之前的數(shù)據(jù)重新發(fā)送。
他的格式大概是這樣的:
unsigned char ucCommand[9];
ucCommand[0] = COMMAND_SEND_DATA;
ucCommand[1] = Data[0];
ucCommand[2] = Data[1];
ucCommand[3] = Data[2];
ucCommand[4] = Data[3];
ucCommand[5] = Data[4];
ucCommand[6] = Data[5];
ucCommand[7] = Data[6];
ucCommand[8] = Data[7];
COMMAND_RESET 該命令告訴Boot Loader 復(fù)位。當(dāng)下載成功后需要重啟以執(zhí)行新的程
=0x25 序的時(shí)候發(fā)送該命令。當(dāng)然如果下載不成功想要重啟也是可以的。
總之,Boot Loader 接收到該命令后就會(huì)啟動(dòng)一個(gè)正常的啟動(dòng)序列。
從機(jī)在啟動(dòng)復(fù)位序列之前會(huì)向主機(jī)返回一個(gè)ACK 信號(hào)。表明命令正
確接收,將要進(jìn)入復(fù)位序列。
他的格式大概是這個(gè)樣子的:
unsigned char ucCommand[1];
ucCommand = COMMAND_RESET;
雖然我建議你沒事不要亂改上面定義的命令,但是如果你知道你想干什么的話,想要修改增加或刪除命令的話,它們?cè)赽oot_loader/bl_command.h 中,它們是Stellaris Peripheral Driver Library 的 一部分。
6、從應(yīng)用程序進(jìn)入Boot Loader
在應(yīng)用程序中你可以隨時(shí)調(diào)用一個(gè)函數(shù)進(jìn)入到Boot Loader,想想這個(gè)有多么誘人吧。你放說你的產(chǎn)品外面只有一個(gè)串口接出來,其他的都封裝起來了,但是你還想日后可能會(huì)給你的產(chǎn)品升級(jí)。 這個(gè)時(shí)候你可以通過給串口發(fā)送一個(gè)特定的命令使內(nèi)部的Boot Loader 通過這個(gè)串口來給你的產(chǎn)品升級(jí)程序。
要想使應(yīng)用程序能夠跳到Boot Loader 中執(zhí)行升級(jí)程序,它必須具備一個(gè)Boot Loader,無論是ROM 中固化的還是Flash 中的。最常見的就是通過USB、以太網(wǎng)和串口來升級(jí)程序,但是也可以通過I2C 和SSI 來升級(jí)程序。和前面講的一樣,ROM 中的Boot Loader 不支持USB 的方式。
先說說如何使應(yīng)用程序進(jìn)入Flash 中的Boot Loader 執(zhí)行程序。首先要將Boot Loader 燒如0 開始的Flash 空間,然后把應(yīng)用程序燒如到Boot Loader 的bl_config.h 中APP_START_ADDRESS 所定義的地址。這樣可以由Boot Loader 引導(dǎo)應(yīng)用程序。應(yīng)用程序中包含有跳轉(zhuǎn)到Boot Loader 的代碼,通過外部給它的特殊命令、屏幕操作、按鍵,,,隨你怎么操作,只要你能執(zhí)行到這個(gè)跳轉(zhuǎn)函數(shù)它就會(huì)跳到Boot Loader 中運(yùn)行。一個(gè)示例性的代碼可能會(huì)是這個(gè)樣子的:
- //*****************************************************************************
- //
- // Passes control to the bootloader and initiates a remote software update.
- //
- // This function passes control to the bootloader and initiates an update of
- // the main application firmware image via UART0, Ethernet or USB depending
- // upon the specific boot loader binary in use.
- //
- // \return Never returns.
- //
- //*****************************************************************************
- void
- JumpToBootLoader(void)
- {
- //
- // We must make sure we turn off SysTick and its interrupt before entering
- // the boot loader!
- //
- SysTickIntDisable();
- SysTickDisable();
- //
- // Disable all processor interrupts. Instead of disabling them
- // one at a time, a direct write to NVIC is done to disable all
- // peripheral interrupts.
- //
- HWREG(NVIC_DIS0) = 0xffffffff;
- HWREG(NVIC_DIS1) = 0xffffffff;
- //
- // Return control to the boot loader. This is a call to the SVC
- // handler in the boot loader.
- //
- (*((void (*)(void))(*(unsigned long *)0x2c)))();
- }
復(fù)制代碼
這段代碼是直接從TI 提供的例程里摘出來的。太多詳細(xì)代碼的分析不屬于本文的內(nèi)容,有興趣的可以自己去研究一下。根據(jù)其注釋可以很清楚的知道,進(jìn)入該函數(shù)后首先關(guān)閉systick 及其中斷, 然后關(guān)閉所有的中斷,最后跳到了Boot Loader 的SVC 中斷處理函數(shù)(注意,不是應(yīng)用程序的SVC 中 斷)中執(zhí)行了。再看看Boot Loader 的SVCall 中斷處理函數(shù)做了寫什么呢,在源代碼中分析,我們發(fā) 現(xiàn)是它引導(dǎo)了Boot Loader 的運(yùn)行,首先把Boot Loader 復(fù)制到SRAM 中,然后跳到SRAM 中初始化 bl_config.h 中所配置的硬件信息,然后就是等著LM Flash Programmer 來升級(jí)程序了。
如果芯片有內(nèi)置的Boot Loader 的話,應(yīng)用程序也可以執(zhí)行ROM 中的Boot Loader 來升級(jí)應(yīng)用程序。但是內(nèi)部ROM 中的Boot Loader 不支持USB。
和執(zhí)行Flash 中的Boot Loader 有所不同,具體來說表現(xiàn)在以下兩個(gè)方面:
1、鏈接時(shí)的起始地址不同。我們知道,F(xiàn)lash 中的Boot Loader 要占用一定的Flash 空間,所以應(yīng)用程序鏈接的起始地址是定義在bl_config.h 中的APP_START_ADDRESS 這個(gè)地址。而ROM 中的Boot Loader 不占用Flash 空間,這時(shí)候應(yīng)用程序是從0 地址開始的。
2、如何執(zhí)行Boot Loader 的問題。如果Boot Loader 在Flash 中,0x2C 代表的是Boot Loader 的中斷向量。如果Boot Loader 在ROM 中則0x2C 代表的是應(yīng)用程序的中斷向量。
應(yīng)用程序執(zhí)行ROM 中的Boot Loader,上述函數(shù)中最后一句是不對(duì)的,應(yīng)該修改為ROM 中執(zhí)行Boot Loader 的入口,也就是調(diào)用ROM_UpdateEthernet、ROM_UpdateI2C、ROM_UpdateSSI、ROM_UpdateUART 這幾個(gè)函數(shù),它們的定義在Rom.h 中。
有關(guān)應(yīng)用程序調(diào)用Boot Loader 有幾個(gè)問題,現(xiàn)在總結(jié)一下應(yīng)用程序調(diào)用Boot loader,包括前面可能講過的,也有沒講過的。
1、調(diào)用Flash 中的Boot Loader 注意修改程序的開始地址為Boot Loader bl_config.h 中的地址。
2、調(diào)用ROM 中的Boot Loader 注意修改程序的開始地址為0。
3、調(diào)用ROM_UpdateI2C、ROM_UpdateSSI、ROM_UpdateUART 和ROM_UpdateEthernet 不同。前三個(gè)函數(shù)沒有參數(shù),而以太網(wǎng)的應(yīng)該寫作ROM_UpdateEthernet(ROM_SysCtlClockGet());
4、應(yīng)用程序通過以太網(wǎng)升級(jí)的時(shí)候,必須在應(yīng)用程序里配置好網(wǎng)口,并且MAC 地址已經(jīng)被編程而且正在使用。(注:此時(shí)的MAC 地址可以全是F,只要IP 地址在同一網(wǎng)段內(nèi)即可)。
結(jié)語(yǔ)
好了,關(guān)于Boot Loader 的問題就介紹這么多了。不同的項(xiàng)目中可能用法也會(huì)有所不同,剛開始可能大家都是先看懂TI 的例程,然后慢慢修改,摸索出適合自己項(xiàng)目的Boot Loader,最后慢慢融會(huì)貫通,使用起來就能隨心所欲了。這個(gè)不是一篇文章看了就能全懂的。
|
-
-
BootLoader應(yīng)用說明.pdf
2018-8-31 23:22 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
577.56 KB, 下載次數(shù): 9, 下載積分: 黑幣 -5
Bootloader應(yīng)用說明
|