宋書龍,葛 露
(中國西南電子技術(shù)研究所,成都 610036)
嵌入式設(shè)備在實際使用中可能會遇到各種軟件問題和用戶需求的變化,這就需要對軟件進行升級以提供更好的功能和性能,尤其是交付到外場的設(shè)備,需要拆卸設(shè)備鏈接仿真器進行軟件升級,對于大型復(fù)雜的設(shè)備,甚至需要多名專業(yè)人員到現(xiàn)場,就會導(dǎo)致軟件升級過程比較繁瑣,增加了維護成本。軟件維護人員對嵌入式終端設(shè)備的軟件進行維護升級,常用的方法是拆卸設(shè)備,使用仿真器工具進行燒寫,而采用在線更新軟件的方式,可以解決不拆設(shè)備和掛載仿真器燒寫的問題。國外的公司PHILIPS的P89C51RX2xx系列單片機同時支持兩種功能在系統(tǒng)中編程和在應(yīng)用中編程,PHILIPS為了使在線更新技術(shù)得以推廣,還在單片機上提供了免費的BOOT固件,使在線燒寫功能實現(xiàn)更簡單,意法半導(dǎo)體公司的PSD系列微控制器的片內(nèi)Flash大容量存儲器,也同時支持在系統(tǒng)中編程和在應(yīng)用中編程。國內(nèi)的華大半導(dǎo)體有限公司HC32L136系列32位微控制器支持在線APP更新,在芯片上電復(fù)位的狀態(tài)下,BOOT0腳為高電平時,芯片會進入在線編程模式,通過上位機可以進行在線編程。兆易創(chuàng)新科技集團股份有限公司的GD32系列片上FLASH高達3 072 K字節(jié)用于存儲指令或數(shù)據(jù),支持從系統(tǒng)存儲器啟動,在應(yīng)用編程則可由用戶在應(yīng)用中實現(xiàn)。本文采用GD32F450系列ARMCortex-M4內(nèi)核的32位通用微控制器(MCU,microcontroller unit),處理器主頻高達200 MHz,控制器內(nèi)部集成了一個以太網(wǎng)外設(shè),支持100 Mbps數(shù)據(jù)傳輸速率,借助以太網(wǎng)外設(shè),GD32F450控制器可以通過ETH外設(shè)按照IEEE 802.3-2002和IEEE 1588-2008標準發(fā)送和接收數(shù)據(jù)包。文獻[1-5]同類的研究大都是采用串口、CAN等總線在線燒寫,本設(shè)計是利用在應(yīng)用編程技術(shù)進行免拆設(shè)備,在外場通過網(wǎng)絡(luò)在線快速升級GD32國產(chǎn)微控制器固件。
通過仿真器燒寫有兩種接口:一種是JTAG模式,另一種是SWD模式,JTAG(Joint Test Action Group)國際標準測試協(xié)議被廣泛應(yīng)用于各種基于嵌入式系統(tǒng)的開發(fā)、測試和編程任務(wù)中。它提供了一種通用接口,可以方便地訪問芯片內(nèi)部電路和功能,可以實現(xiàn)與目標設(shè)備的通信,讀取和寫入芯片內(nèi)部寄存器或存儲器中的內(nèi)容,以及監(jiān)控和控制芯片的狀態(tài),JTAG接口通常由TMS、TCK、TDI和TDO共4條線組成,TMS用于控制時序和模式選擇,TCK線則提供定時脈沖,TDI和TDO分別用于輸入和輸出數(shù)據(jù)。SWD(Serial Wire Debug)一種和JTAG不同的模式,使用的協(xié)議與JTAG也不一樣,SWD只需要4個引腳,結(jié)構(gòu)簡單,需要的硬件接口為:GND、RST、SWDIO和SWDCLK,分別為地線、復(fù)位、數(shù)據(jù)線及時鐘,調(diào)試階段的終端模塊大都使用仿真器仿真調(diào)試和燒寫,除了仿真器可以燒寫以外,還有一些通過總線方式在線燒寫[6-8]。
在嵌入式技術(shù)中,在線編程方式主要有兩種:IAP(在應(yīng)用中編程)和ISP(在系統(tǒng)中編程)。
ISP(In-system Programming)在系統(tǒng)中編程,用于嵌入式系統(tǒng)或芯片程序的更新和燒錄,跟傳統(tǒng)的更新和燒錄方式相比,ISP允許直接通過系統(tǒng)的通信接口如SPI、I2C、UART等對芯片內(nèi)部進行編程操作,無需拆卸芯片,在系統(tǒng)上對程序進行更新、配置或修改,使用專門的編程器連接到目標設(shè)備進行編程操作,只要留出上位機的通信口,使用上位機軟件就可以實現(xiàn)對芯片內(nèi)部存儲器的數(shù)據(jù)、配置文件、參數(shù)設(shè)置等進行修改,由于ISP技術(shù)可以對芯片內(nèi)部直接訪問,在系統(tǒng)編程中,需要確保編程操作的準確性和安全性,避免意外寫入錯誤的代碼而損壞目標設(shè)備[9]。
IAP(In-application Programming)在應(yīng)用中編程,它與ISP相似,但ISP通常涉及到整個系統(tǒng)的編程,而IAP是在特定應(yīng)用程序中對固件進行更新,目標設(shè)備開機上電,直接運行應(yīng)用程序完成固件更新,而無需重新啟動目標設(shè)備,需要把目標設(shè)備上的存儲器劃分為3個獨立的區(qū)域:一個區(qū)域作為引導(dǎo)程序,一個區(qū)域用于更新程序,最后一個區(qū)域用于存儲新固件的升級文件,通過對程序存儲器的指定段進行讀和寫操作,從而實現(xiàn)對目標設(shè)備上的程序的更新和燒錄[10]。
在線燒寫系統(tǒng)主要由3部分組成:上位機軟件、手持控制器和終端設(shè)備,上位機軟件主要通過網(wǎng)絡(luò)把數(shù)據(jù)發(fā)送給手持控制器,手持控制器把數(shù)據(jù)發(fā)送給終端設(shè)備,終端設(shè)備功能是運行點亮流水燈,系統(tǒng)如圖1所示。
圖1 系統(tǒng)框圖
1)上位機軟件通過網(wǎng)絡(luò),把編譯鏈接生成最終的BIN格式文件發(fā)送給手持控制器。
2)終端設(shè)備上電時候,會進入BOOT引導(dǎo)區(qū),此時如果手持控制器沒有給終端設(shè)備發(fā)送“啟動燒寫”指令,BOOT引導(dǎo)區(qū)的程序等待10 s以后,自動跳轉(zhuǎn)到APP運行區(qū)執(zhí)行;此時如果手持控制器給終端設(shè)備發(fā)送“啟動燒寫”指令,BOOT引導(dǎo)區(qū)的程序收到正確的指令會跳轉(zhuǎn)到UPDATE升級區(qū),手持控制器發(fā)送需要待燒寫的BIN文件給終端設(shè)備,由UPDATE升級區(qū)運行的程序把收到的數(shù)據(jù)燒寫到指定Flash分區(qū)上,燒寫完成后自動跳轉(zhuǎn)到APP運行區(qū)執(zhí)行。
3)終端設(shè)備程序在APP運行區(qū)運行,手持控制器可以給終端設(shè)備發(fā)送復(fù)位命令,此時終端設(shè)備程序會進入BOOT引導(dǎo)區(qū)運行[11-12]。
2.2.1 上位機模塊設(shè)計
如圖2所示,上位機軟件基于PC機開發(fā)設(shè)計,讀取本次編譯的BIN格式文件,通過網(wǎng)絡(luò)發(fā)送給手持控制器,網(wǎng)絡(luò)收發(fā)數(shù)據(jù)使用UDP協(xié)議,每次傳輸數(shù)據(jù)的大小1 024字節(jié),數(shù)據(jù)傳輸完成會給手持控制器發(fā)送傳輸完成標志。
圖2 上位機模塊圖
2.2.2 手持控制器模塊設(shè)計
手持控制器的片上Flash不需要分區(qū),程序運行于片上Flash的開始區(qū)域0x08000000,收到數(shù)據(jù)存儲在片外Flash上,外掛的Flash存儲容量512 MB。
手持控制器由自檢、數(shù)據(jù)讀取、啟動燒寫及數(shù)據(jù)注入等命令組成,手持控制器發(fā)送自檢命令給終端設(shè)備模塊,終端設(shè)備模塊收到命令將自檢結(jié)果發(fā)送給手持控制器,如果手持控制器未收到自檢數(shù)據(jù),會重傳自檢命令給終端設(shè)備,重傳3次以后仍未收到數(shù)據(jù)或收到數(shù)據(jù)異常,都會顯示自檢超時,只有收到正確的自檢數(shù)據(jù),會把自檢結(jié)果信息顯示,通過自檢命令判斷手持控制器與終端設(shè)備網(wǎng)絡(luò)鏈接是否正常[13-14]。
如圖3所示,手持控制器會主動發(fā)送數(shù)據(jù)讀取命令給上位機軟件,接收到上位機軟件發(fā)送的數(shù)據(jù)會寫入到外掛的片外Flash進行存儲,當(dāng)手持控制器會發(fā)送數(shù)據(jù)注入命令給終端設(shè)備模塊時,會從外掛的片外Flash中讀取數(shù)據(jù),發(fā)送給終端設(shè)備模塊。
圖3 手持控制器模塊圖
2.2.3 終端設(shè)備模塊設(shè)計
終端設(shè)備模塊的程序分區(qū)運行,防止在更新程序時候失敗,導(dǎo)致應(yīng)用程序無法執(zhí)行,終端設(shè)備模塊分為3個區(qū)加載程序,分別是BOOT區(qū)、UPDATE區(qū)和APP應(yīng)用區(qū),如圖4所示。
圖4 終端設(shè)備模塊圖
1)BOOT區(qū):終端模塊設(shè)備開機上電BOOT區(qū)的程序先加載運行,根據(jù)接收到的網(wǎng)絡(luò)命令進行程序跳轉(zhuǎn)。
2)UPDATE區(qū):固件程序更新區(qū),主要是更新程序,下載完成新固件后,自動跳轉(zhuǎn)到APP應(yīng)用區(qū)運行。
3)APP應(yīng)用區(qū):主要用來實現(xiàn)所需要的業(yè)務(wù)的程序。
終端設(shè)備模塊開機上電時候,程序會在BOOT區(qū)運行,首先會初始化網(wǎng)絡(luò),此時手持控制器發(fā)送“啟動燒寫”命令,終端設(shè)備模塊BOOT區(qū)的程序就會跳轉(zhuǎn)到UPDATE區(qū)域去運行,手持控制器發(fā)送 “數(shù)據(jù)注入”命令,會把待燒寫文件通過網(wǎng)絡(luò)發(fā)送給終端設(shè)備模塊,終端設(shè)備模塊收到正確數(shù)據(jù)后會把數(shù)據(jù)寫入到片上Flash,數(shù)據(jù)寫入完成后,終端設(shè)備模塊的程序會跳轉(zhuǎn)到APP運行區(qū)去運行,就會看到流水燈點亮,此時手持控制器發(fā)送復(fù)位命令,終端設(shè)備模塊就會進行軟件復(fù)位,程序會從BOOT區(qū)重新運行,APP程序為用戶功能代碼,執(zhí)行用戶功能操作。
GD32F450ZI上使用了兩片閃存,前1 024 kB容量在第0片閃存中,后續(xù)的容量在第1片閃存中,主存儲閃存總共容量為3 072 kB,包含8個16 kB的扇區(qū)、2個64 kB的扇區(qū)、14個128 kB的扇區(qū)、4個256 kB的扇區(qū)[15]。主存儲閃存的每個扇區(qū)都可以單獨擦除,支持32位整字或16位半字、字節(jié)編程,4 kB頁擦除,扇區(qū)擦除和整片擦除操作,Bank0的總大小為1 024 kB,閃存的地址范圍為0x08000000-0x080FFFFF。根據(jù)固件在線升級的需要,將其劃分為 3個作用不同的區(qū)域,具體劃分如表1所示。
表1 終端設(shè)備Flash地址區(qū)域劃分
終端設(shè)備模塊在系統(tǒng)上電后或復(fù)位后立即進入 BOOT引導(dǎo)區(qū)執(zhí)行,即系統(tǒng)上電或復(fù)位后,軟件從地址為0x8000000處執(zhí)行,因此在MDK上需設(shè)置BOOT引導(dǎo)區(qū)片上Flash 起始地址為 0x08000000,BOOT引導(dǎo)區(qū)生成的BIN文件大小為52 kB設(shè)置分區(qū)大小為192 kB,同樣原理,UPDATE升級區(qū)生成的BIN文件大小100 kB,因此在MDK上需要設(shè)置UPDATE升級區(qū)片上Flash 起始地址為 0x08030000,APP運行區(qū)生成的BIN文件大小150 kB,在MDK上需要設(shè)置APP運行區(qū)片上Flash 起始地址為 0x08060000,BOOT引導(dǎo)區(qū)、UPDATE升級區(qū)和 APP 運行區(qū)的存儲區(qū)域相互獨立,只存在簡單的跳轉(zhuǎn)關(guān)系[16]。
終端模塊BOOT引導(dǎo)區(qū)的程序必須通過仿真器燒入,運行于片上Flash的開始區(qū)域0x08000000,UPDATE升級區(qū)的程序也必須通過仿真器燒入,運行于片上Flash的開始區(qū)域0x08030000,APP運行區(qū)的程序可以通過手持控制器燒入,運行于片上Flash的開始區(qū)域0x08060000,以后需要更新終端模塊的程序,只需要更新手持控制器存儲內(nèi)容,無需通過仿真器進行更新,即使在燒寫的過程中突然掉電,只會導(dǎo)致APP運行區(qū)的程序會破壞,BOOT引導(dǎo)區(qū)和UPDATE燒寫區(qū)的程序仍然可以正確運行。
ARM結(jié)構(gòu)CM4手冊規(guī)定芯片復(fù)位時要從0x0000 0000地址開始取出中斷向量,GD32的片上Flash在MDK里被設(shè)置為起始地址0x0800 0000,因為啟動模式?jīng)Q定了向量表的位置,GD32有3種啟動模式:
1)片上Flash存儲器。當(dāng)選擇從片上Flash啟動模式后,使用JTAG或SWD模式燒寫程序,一般會將程序下載到設(shè)備內(nèi)置的片上Flash存儲器中的0x0800 0000地址處,設(shè)備重啟直接從這個地址啟動程序,片上Flash的0x0800 0000地址被映射到0地址處,這個時候CM4既可以在0地址處訪問中斷向量表,也可以在0x0800 0000地址處訪問中斷向量表,而代碼存放在地址0x0800 0000。GD32通過做了一個啟動映射,NVIC中有一個寄存器,稱為向量表偏移量寄存器,在文件GD32f4xx_misc.c通過修改該寄存器的值就能重新定位向量表,向量表在地址空間中的位置是通過重定位寄存器設(shè)置的值來指出向量表的地址。在復(fù)位后,該寄存器的值為0[17]。
2)系統(tǒng)存儲器啟動。從系統(tǒng)存儲器啟動,通過設(shè)置引導(dǎo)引腳BOOT1=0 BOOT0=1,芯片能夠從特定區(qū)域的固化程序開始執(zhí)行,特定區(qū)域的內(nèi)存地址從0x1FFFF000開始,存放了廠家預(yù)置的程序,也稱為ISP程序,通常是只讀的,在出廠后,這個區(qū)域的數(shù)據(jù)不可以被修改或擦除,因此被認為是ROM區(qū)域。它存放著芯片出廠時預(yù)置的固化程序,主要用于初始化系統(tǒng)和提供下載功能,我們可以使用廠商提供的ISP程序,通過串口總線將用戶的應(yīng)用程序下載到芯片的Flash存儲器中,下載完成后,為了使芯片能夠正常啟動運行已下載的程序,需要將BOOT0引腳和BOOT1引腳都重新設(shè)置為低電平。這種方式的好處是在不使用仿真器的情況下,直接通過串口進行程序更新和調(diào)試[18]。
3)片上SRAM啟動。從片上SRAM啟動時,確保程序正確執(zhí)行,需要在應(yīng)用程序的初始化代碼中重新設(shè)置向量表的位置,從特定的起始地址0x2000 0000進行訪問,與前面提到的系統(tǒng)存儲器啟動不同,SRAM無法永久存儲程序,且在掉電后數(shù)據(jù)將丟失,如果需要長期保存的數(shù)據(jù),必須采取其他方式進行存儲,以防止掉電導(dǎo)致數(shù)據(jù)丟失,因此這種啟動模式主要用于程序的調(diào)試和臨時存儲數(shù)據(jù)[19]。
在許多GD32系列芯片上,存在兩個引腳BOOT0和BOOT1,它們在芯片復(fù)位時的電平狀態(tài)決定了芯片復(fù)位后從哪個區(qū)域開始執(zhí)行程序。多數(shù)正常啟動情況下BOOT0和BOOT1引腳都被拉低,電平都為0時,芯片從片上Flash存儲器的起始地址處開始執(zhí)行程序。當(dāng)芯片從系統(tǒng)存儲器啟動時候,BOOT0引腳被設(shè)置為高電平,才允許外部串口下載新的程序到芯片的Flash存儲器中,下載完成后,將BOOT0引腳重新設(shè)置為低電平,以便芯片正常啟動已下載的程序,而BOOT1引腳通常保持為低電平。當(dāng)芯片從SRAM啟動,BOOT0和BOOT1兩個引腳都需要拉高。啟動模式如表2所示。
表2 啟動模式
通過設(shè)置BOOT1和BOOT0兩個引腳的電平狀態(tài),就可以靈活切換芯片的啟動模式,本文啟動模式設(shè)計為BOOT1=0和BOOT0=0從片上Flash存儲器啟動,如圖5所示。
圖5 啟動模式原理圖
DP83848是一種由德州儀器(Texas Instruments)公司生產(chǎn)的集成以太網(wǎng)控制芯片,用于實現(xiàn)100 Mbit/s單路物理層以太網(wǎng)的收發(fā)功能,支持100 M的以太網(wǎng)通信,集成度高,具有低功耗等性能,同時支持MII(媒體獨立接口)與RMII(簡化的媒體獨立接口)兩種與物理層(PHY)通訊的標準接口,實現(xiàn)以太網(wǎng)數(shù)據(jù)幀的發(fā)送與接收,遵守IEEE 802.3-2002標準和IEEE 1588-2008標準,還集成了串行管理接口(SMI,serial management interface),專門用于訪問PHY芯片寄存器[20-21],SMI接口包括MDC和MDIO兩條信號線,MDIO是用來讀寫PHY的寄存器,以獲取PHY的狀態(tài),MDC為MDIO提供時鐘。SMI接口可以支持最多32個PHY,但在任意時刻只能訪問一個PHY的一個寄存器。
本文采用RMII接口模式,需要7根線通信,MII模式需要16根通信線,RMII模式在功能上與MII是相同的,在保持物理層器件現(xiàn)有特性的前提下減少了PHY芯片引腳數(shù)量,RMII接口模式主要包括以下引腳:參考時鐘、發(fā)送使能、接收使能、發(fā)送數(shù)據(jù)及接收數(shù)據(jù)等。PHY芯片原理如圖6所示。
圖6 PHY芯片原理圖
ETH_50M:在RMII模式下使用,提供給PHY芯片的50 MHz參考時鐘,這個外部時鐘非常重要,需要穩(wěn)定、高精度,讓系統(tǒng)各個組件時序同步。
MCU_PHY_TXEN:數(shù)據(jù)發(fā)送使能,高電平有效。在整個數(shù)據(jù)發(fā)送過程保存有效電平,表示MAC層正在將要傳輸?shù)臄?shù)據(jù)放到MCU_PHY_TXD0和MCU_PHY_TXD1上。
MCU_PHY_TXD0:發(fā)送數(shù)據(jù),MCU_PHY_TXEN有效后,作為發(fā)送端。
MCU_PHY_TXD1:在RMII模式下只有2位,只有在MCU_PHY_TXEN 有效數(shù)據(jù)線才有效。
MCU_PHY_CRS_DV:數(shù)據(jù)接收使能,用于數(shù)據(jù)接收。對于RMII 模式,這個MCU_PHY_CRS_DV引腳有效,則認為在MCU_PHY_RXD0和MCU_PHY_RXD1上的數(shù)據(jù)是有效的。
MCU_PHY_RXD0:接收數(shù)據(jù),與ETH_50M時鐘同步,在MCU_PHY_CRS_DV有效后的每個時鐘周期里,MCU_PHY_RXD0和MCU_PHY_RXD1接收PHY芯片的兩位數(shù)據(jù)。
MCU_PHY_RXD1:接收數(shù)據(jù),MCU_PHY_CRS_DV有效后,作為接收端。
MCU_PHY_MDC:為MCU_PHY_MDIO提供時鐘,最高頻率為2.5 MHz的時鐘信號,在空閑狀態(tài)下該引腳保持為低電平狀態(tài)。
MCU_PHY_MDIO:用于與PHY之間的數(shù)據(jù)傳輸,與MCU_PHY_MDC時鐘線配合,接收和發(fā)送數(shù)據(jù)。
網(wǎng)絡(luò)變壓器原理如圖7所示。在PHY芯片與RJ45網(wǎng)絡(luò)插座之間還需要一個網(wǎng)絡(luò)變壓器,PHY芯片工作時送出的上行數(shù)據(jù)信號從網(wǎng)絡(luò)變壓器的 Pin1和Pin3進入,再由Pin16和Pin14輸出,經(jīng)RJ45水晶頭連接網(wǎng)線發(fā)送出去,外部設(shè)備送來的下行數(shù)據(jù)信號經(jīng)網(wǎng)線和RJ45水晶頭,由Pin9和Pin11進入網(wǎng)絡(luò)變壓器,再由Pin6和Pin8輸出,送到PHY芯片的收發(fā)器上。
圖7 網(wǎng)絡(luò)變壓器原理圖
理論上來說,可以不接網(wǎng)絡(luò)變壓器,從PHY芯片出來信號直接連到RJ45上,也是能正常工作的,但傳輸距離就會受到限制,因為PHY芯片驅(qū)動器的功率有限,當(dāng)網(wǎng)線較長時,到接收端RJ45上的信號會逐漸衰減,導(dǎo)致工作異常,添加網(wǎng)絡(luò)變壓器后,通過變壓器輸出信號顯著提高,傳輸距離進一步增加。增加網(wǎng)絡(luò)變壓器相當(dāng)于將PHY芯片與RJ45線路隔離,減少PHY芯片受到各種干擾,輸出信號更加穩(wěn)定,還可以確保不同型號PHY芯片信號正常傳輸,增強整個網(wǎng)絡(luò)的兼容性。
上位機軟件通過網(wǎng)絡(luò)與手持控制器進行數(shù)據(jù)通信,手持控制器是固件更新操作的發(fā)起端,手持控制器發(fā)送數(shù)據(jù)讀取命令給上位機,上位機把編譯生成的BIN文件發(fā)送手持控制器存儲。其具體實現(xiàn)流程如下:
1)上位機軟件初始化,讀取本地更新BIN文件,如果收到手持控制器發(fā)送的數(shù)據(jù)讀取命令后,會把文件大小通過網(wǎng)絡(luò)發(fā)送給手持控制器,手持控制器接收到正確的文件大小后擦除本地片外Flash;
2)上位機根據(jù)讀取數(shù)據(jù)幀長度判斷是否需要拆幀發(fā)送,數(shù)據(jù)超過1 024字節(jié)需要進行拆分為若干幀,沒有超過1 024字節(jié)的數(shù)據(jù)直接發(fā)送,上位機發(fā)送的每幀數(shù)據(jù)1 024字節(jié),發(fā)送完成都要等待手持控制器回復(fù),否則對該幀數(shù)據(jù)進行重傳3次,重傳3次仍沒有收到表示傳輸失?。?/p>
3)上位機下發(fā)的每幀數(shù)據(jù)都收到了手持控制器回復(fù),當(dāng)傳輸完最后一幀數(shù)據(jù),手持控制器會顯示數(shù)據(jù)讀取成功,如果傳輸過程中出現(xiàn)異常,手持控制器會顯示數(shù)據(jù)讀取超時。
手持控制器操作按鍵選擇相應(yīng)功能執(zhí)行,跟設(shè)備進行命令式交互,通過以太網(wǎng)接口與終端設(shè)備模塊通信,交互信息顯示在屏上顯示,手持控制器起到了中轉(zhuǎn)數(shù)據(jù)的作用,手持控制器設(shè)計流程如圖8所示。
圖8 手持控制器設(shè)計流程
手持控制器交互具體實現(xiàn)流程如下:
1)上電初始化手持控制器,主要包括顯示模塊、按鍵模塊、網(wǎng)絡(luò)傳輸模塊、Flash模塊等;
2)初始化完成進入主菜單,通過查詢判斷按鍵是否被按下,如果按下就會發(fā)送對應(yīng)的命令給終端設(shè)備模塊,終端設(shè)備模塊收到命令回復(fù)確認消息,超過設(shè)置的時間未收到數(shù)據(jù),則顯示超時;
3)如果按下數(shù)據(jù)注入命令,就會讀取存儲在片外Flash中的數(shù)據(jù),通過網(wǎng)絡(luò)發(fā)送給終端設(shè)備模塊,發(fā)送完成后顯示發(fā)送成功;如果按下數(shù)據(jù)讀取命令,就會接收上位機軟件發(fā)送的數(shù)據(jù),并將數(shù)據(jù)存儲到片外Flash,接收完成后顯示接收成功;
4)如果按下自檢命令,就會通過網(wǎng)絡(luò)發(fā)送給終端設(shè)備模塊,終端設(shè)備模塊收到自檢命令就會把自檢結(jié)果回傳給手持控制器。
終端設(shè)備模塊的設(shè)計需要創(chuàng)建3個工程,分別是BOOT工程、 UPDATE工程和APP點亮流水燈工程,如圖9所示,終端模塊上電運行BOOT區(qū)程序,等待手持控制器發(fā)送升級命令,10 s沒有升級收到命令,程序跳轉(zhuǎn)到APP區(qū)運行。如果終端設(shè)備模塊上電以后,手持控制器發(fā)送升級命令,程序跳轉(zhuǎn)到UPDATE區(qū)運行,將收到的數(shù)據(jù)寫入到0x8060000開始的地址,數(shù)據(jù)全部燒寫完成后,程序會跳轉(zhuǎn)到APP區(qū)運行。
圖9 終端模塊的圖
4.3.1 BOOT啟動區(qū)的軟件設(shè)計
終端模塊上電復(fù)位后在0x0800 0000地址處訪問中斷向量表,如果收到手持控制器升級命令,跳轉(zhuǎn)到UPDATE區(qū),10 s沒有收到手持控制器命令,跳轉(zhuǎn)到APP區(qū),下面程序是收到升級命令從BOOT區(qū)跳轉(zhuǎn)到UPDATE區(qū)。
define FLASH_UPDATE_ADDR 0x08003000 /*UPDATE區(qū)中斷向量表*/
void iap_jump_to_update(void)
{
if (((*(__IO uint32_t*)FLASH_UPDATE_ADDR) &0x2FFE0000 ) 0x20000000) /*檢查棧頂?shù)刂肥欠窈戏?*/
{
__disable_irq();/*屏蔽所有中斷,否則可能導(dǎo)致跳轉(zhuǎn)的失敗*/
JumpAddress = *(__IO uint32_t*) (FLASH_UPDATE_ADDR + 4); /*設(shè)置UPDATE區(qū)堆棧首地址即跳轉(zhuǎn)到新的程序的起始地址 */
Jump_To_Update = (pFunction) JumpAddress; /*將跳轉(zhuǎn)到達UPDATE區(qū)程序的首地址賦值給一個函數(shù)指針*/
__set_MSP(*(__IO uint32_t*) FLASH_UPDATE_ADDR); /*初始化堆棧指針*/
Jump_To_Update (); /*函數(shù)指針完成跳轉(zhuǎn)*/
}
}
4.3.2 UPDATE燒寫區(qū)的軟件設(shè)計
UPDATE區(qū)的程序能夠運行,需要在程序中再次被映射中斷向量表,根據(jù)表1終端設(shè)備模塊片上Flash地址區(qū)域劃分,UPDATE區(qū)中斷向量表被映射到0x0803 0000,修改中斷向量表函數(shù)使用nvic_vector_table_set(NVIC_VECTTAB_FLASH,0x30000),UPDATE區(qū)程序存儲更改為0x0803 0000,如圖10所示。
圖10 UPDATE區(qū)程序存儲位置
手持控制器負責(zé)將上位機軟件下發(fā)的數(shù)據(jù)幀內(nèi)容通過網(wǎng)絡(luò)總線轉(zhuǎn)發(fā)到對應(yīng)的終端設(shè)備模塊,UPDATE區(qū)的程序按照表3數(shù)據(jù)幀消息內(nèi)容進行解析,每幀前8個字節(jié)分別表示幀頭、長度和幀序號,后面接著1 024字節(jié)真實BIN文件數(shù)據(jù),為避免傳輸出錯會進行CRC校驗,終端設(shè)備模塊收到每幀數(shù)據(jù)都正確,就會寫入到片上Flash存儲。
表3 數(shù)據(jù)幀消息內(nèi)容
下面程序是UPDATE區(qū)核心程序,主要功能是燒寫B(tài)IN文件到片上Flash中,燒寫完成程序會自動跳轉(zhuǎn)到APP區(qū)。
define FLASH_APP2_ADDR (0x08060000) /* APP區(qū)起始地址*/
define READ_LEN (1024) /*一幀固件數(shù)據(jù)大小*/
void Write_MCU_To_Flash(void)/*把固件數(shù)據(jù)寫到flash*/
{
uint32_t data_buff[512]={0};
if(JTAG_flag 1)
{
g_cn = 0;/*計數(shù)清0*/
}
else if(JTAG_flag 2)/*收到一幀數(shù)據(jù)1024字節(jié)*/
{
memcpy(data_buff,g_UdpRxBuf+8,READ_LEN);
fmc_write_32bit_data(FLASH_APP2_ADDR+g_cn,READ_LEN/4, data_buff); /*寫入片上FLASH*/
g_cn+=READ_LEN;
}
else if(JTAG_flag 3) /*收到最后一幀數(shù)據(jù)不足1024字節(jié)*/
{
memcpy(data_buff,g_UdpRxBuf+8,data_len);
fmc_write_32bit_data(FLASH_APP2_ADDR+g_cn,data_len/4, data_buff); /*寫入片上FLASH*/
g_cn = g_cn + data_len;
}
}
4.3.3 APP運行區(qū)的軟件設(shè)計
1)同樣原理APP區(qū)的程序能夠運行,根據(jù)表1終端設(shè)備模塊片上Flash地址區(qū)域劃分,APP區(qū)中斷向量表被映射到0x08060000,修改中斷向量表映射位置nvic_vector_table_set(NVIC_VECTTAB_FLASH,0x60000)。
2)默認情況下MDK編譯鏈接是不會生成 BIN 文件,需要配置工程選項,在 MDK的“Options For Target->Users”中加入fromelf 指令,編譯生成BIN格式文件如圖11所示,KARMARMCCinfromelf.exe --bin-output=@L.bin !L。原始數(shù)據(jù)如圖12所示,其中BIN 文件是最直接的代碼映像,它記錄的內(nèi)容就是要存儲到片上FLASH 的二進制數(shù)據(jù),在片上FLASH 中燒寫的內(nèi)容與BIN文件內(nèi)容完全相同[22]。
圖11 配置工程
圖12 BIN文件的原始數(shù)據(jù)
3)程序在UPDATE區(qū)運行時候,才能更新固件,在APP區(qū)運行無法更新,此時,手持控制器給終端設(shè)備模塊發(fā)送復(fù)位命令,通過NVIC_SystemReset()函數(shù)執(zhí)行軟件復(fù)位。軟件復(fù)位后程序就會重新從BOOT區(qū)運行,手持控制器給終端設(shè)備模塊發(fā)送燒寫命令,終端設(shè)備模塊程序跳轉(zhuǎn)到UPDATE區(qū)運行,固件更新完成后會自動運行新的應(yīng)用程序。
本文是把生成固件通過上位機發(fā)送給手持控制器,通過手持控制器,對終端設(shè)備模塊的應(yīng)用程序進行燒寫,通過實驗對固件升級過程進行模擬測試驗證,并對終端設(shè)備模塊的環(huán)境實驗進行測試驗證,最后對實驗結(jié)果進行分析和總結(jié)。
1)按照3.3節(jié)完成終端設(shè)備模塊設(shè)計,把片上Flash全部擦除,BOOT區(qū)的可執(zhí)行程序和UPDATE區(qū)的可執(zhí)行程序通過仿真器燒錄到片上Flash,將APP應(yīng)用程序生成的BIN文件,通過上位機軟件發(fā)送到手持控制器;
2)終端設(shè)備模塊上電復(fù)位,通過手持控制器把APP應(yīng)用程序生成的BIN文件燒寫到片上Flash指定地址,通過讀取0x0806 0000地址數(shù)據(jù)與BIN源文件比對,如果兩者一樣,說明燒寫到片上Flash成功,BIN源文件的部分數(shù)據(jù)如圖12所示,片上Flash部分數(shù)據(jù)如圖13所示;
圖13 片上Flash讀出來的數(shù)據(jù)
3)燒寫完成后,手持控制器會顯示燒寫完成,觀察終端設(shè)備模塊上的流水燈會閃爍,表明此次升級成功。有多種情況會造成固件升級失敗,比如升級過程中網(wǎng)絡(luò)斷開、突然斷電都會導(dǎo)致終端設(shè)備模塊燒寫失敗,此時終端模塊上電復(fù)位會無法工作,流水燈無法點亮。由于本設(shè)計分為BOOT區(qū)、UPDATE區(qū)和APP區(qū),異常造成固件升級失敗,只是APP區(qū)的程序無法正常運行,斷電后終端設(shè)備模塊重新上電燒寫,仍可以將固件寫入APP區(qū)完成升級。
通過手持控制器燒寫完成的終端設(shè)備模塊放到溫箱進行環(huán)境實驗測試,分別在高溫正52 ℃、低溫負55 ℃和常溫正30 ℃進行功能驗證,觀察流水燈是否點亮,在此范圍溫度上電斷電各30次,測試記錄如圖14所示,流水燈全部點亮。
圖14 環(huán)境實驗圖
通過上述實驗表明,在-55~52 ℃流水燈都點亮,固件都能正常工作,上下電各30次全部點亮,成功率均達到了100%,實驗結(jié)果與預(yù)期一致,通過在線燒寫固件方法,可以讓終端設(shè)備模塊程序正確運行,方案是穩(wěn)定可靠的。
本文是通過免拆終端模塊及無須掛載仿真器對其在線燒寫,并對其功能進行驗證,通過實驗測試驗證流水燈都能正常工作,說明此方案可行性,達到了預(yù)期的目的,基于GD32芯片網(wǎng)絡(luò)在線燒寫固件技術(shù)可靠,為外場升級免拆設(shè)備提供依據(jù),在企業(yè)的實際生產(chǎn)和維護過程中使用在線燒寫技術(shù),可以降低設(shè)備維護人力成本,大大地提高了企業(yè)經(jīng)濟效益。