劉長勇,王宜懷,孫亞軍
(1.武夷學院 數(shù)學與計算機學院,福建 武夷山 354300;2.蘇州大學 計算機科學與技術學院, 江蘇 蘇州 215006;3.武夷學院 認知計算與智能信息處理福建省高校重點實驗室, 福建 武夷山 354300)
實時操作系統(tǒng)(real-time operating system,RTOS)的運用不僅能有效合理地利用現(xiàn)有的CPU資源,而且能簡化應用軟件的設計,縮短開發(fā)周期、降低開發(fā)費用[1],保證系統(tǒng)的可靠性和實時性。那么如何發(fā)揮RTOS作用和優(yōu)勢,采用何種技術實現(xiàn)RTOS在嵌入式系統(tǒng)中的駐留,實現(xiàn)RTOS與應用程序分開編譯,是有一定難度且值得研究的問題,可以采用嵌入式固件技術,將RTOS與應用程序進行物理隔離,固化在非易失存儲器(如Flash)中[2]。目前,在操作系統(tǒng)的應用及駐留等方面已有部分工作者做了一些基本的研究工作,如唐鵬程等[3]提出了一種基于IAP技術的STM32單片機在線固件升級方案;王運盛等[4]以VxWorks 653分區(qū)操作系統(tǒng)作為研究對象,采用統(tǒng)一建模語言來分析和說明分區(qū)的配置和啟動機制,為理解分區(qū)和駐留應用提供了參考;薛芳芳等[5]參考ARINC702A的分區(qū)要求,研究了FMS軟件的駐留規(guī)則,提出了分區(qū)設計和駐留方案,最后給出了測試方法;Wang H等[6]采用μC/OS-Ⅱ實時操作系統(tǒng),在ARM內核的處理器上開發(fā)了蛇狀機器人,并給出了步態(tài)規(guī)劃算法;常華利等[7]提出了一種基于MicroBlaze 軟核處理器的μC/OS-Ⅱ的移植方案;馬書紅[8]利用集成電路技術和密碼學原理,提出了一種將數(shù)學計算機系統(tǒng)固化于TPM安全芯片的方法。
mbedOS是專門為使用Arm微控制器的物聯(lián)網(wǎng)(IoT)設備而設計的開源操作系統(tǒng)[9],支持確定性、多線程、實時性等,廣泛應用于協(xié)議棧和IP網(wǎng)絡組件[10]、物聯(lián)網(wǎng)設備平臺[11]、通信技術和安全訪問服務機制[12]等方面。依據(jù)固件技術的設計原則,本文基于通用嵌入式計算機架構,在合理劃分Flash和RAM空間的基礎上,研究mbedOS駐留的關鍵技術,通過將mbedOS與應用程序分開編譯,達到快速編譯的目的。同時,也為用戶提供函數(shù)原型級的對外接口技術和調用方法,方便用戶對任務函數(shù)的使用,降低了開發(fā)門檻、節(jié)省了編譯時間、提高了寫入速度,從而提高應用程序的健壯性、實時性和可移植性,為學習和使用mbedOS提供了基礎,也為mbedOS的駐留提供了一種解決方案。
為了提升編程顆粒度、提高可移植性,借鑒通用計算機(general computer)的概念與做法,把基本輸入輸出系統(tǒng)(basic input and output system,BIOS)與用戶程序分離開來,實現(xiàn)徹底的工作分工,形成了通用嵌入式計算機(general embedded computer,GEC)[13]。GEC架構將嵌入式軟件系統(tǒng)分為BIOS工程程序(簡稱BIOS)和USER工程程序(簡稱USER)兩部分,BIOS先于USER固化于微控制器(microcontroller unit,MCU)內的非易失存儲器(如Flash)中,啟動時BIOS先運行,隨后轉向USER,最后由USER啟動mbedOS?;贕EC架構,將mbedOS駐留在BIOS中有以下優(yōu)勢:
(1)降低編程難度。由于工程分為了BIOS和USER,mbedOS駐留在BIOS中,成為了一個固件。因此,用戶只需關心USER的編程,不改變原有的編程模式,無需了解mbedOS調度機制,就可以調用mbedOS提供的對外接口函數(shù),從而降低了編程難度;
(2)節(jié)省編譯時間。由于mbedOS駐留在BIOS中,只需要編譯成功之后就可以作為一個固件提供給用戶長期使用,不占用用戶程序時間,而在USER中由于無mbedOS,只需編譯用戶程序即可,縮短了程序的編譯時間;
(3)簡化寫入方式。在原來不分BIOS和USER時,每次要使用SWD接口通過寫入器將程序燒錄到Flash中,若程序有變動,還需重新寫入。而在GEC架構中,只需在BIOS中通過寫入器將程序燒錄到Flash中,而USER則可以通過串口進行寫入和更新,甚至可以通過遠程的方式實現(xiàn)對USER的更新,簡化了程序的寫入方式。
基于GEC架構,程序雖然分為BIOS和USER,但最終程序代碼和各種變量數(shù)據(jù)都是放在同一個MCU的Flash和RAM中,要將mbedOS駐留到BIOS中,就必須對MCU的Flash和RAM空間進行合理的劃分,這樣才能確保代碼不重疊,變量使用不越界,從而保證mbedOS能得到正常運行,而且又不影響USER的執(zhí)行。
(1)Flash空間的劃分
MCU的Flash 空間一般分為中斷向量段、Flash配置段和程序代碼段,分別用于存放中斷向量、默認的Flash保護設定與加密屬性、程序代碼。在GEC架構下,F(xiàn)lash 空間采用分割獨享方式劃分為BIOS和USER兩部分,每部分都包含這3個段,其劃分如圖1所示,需要注意的是由于Flash是以扇區(qū)為單位進行擦除,在劃分空間時要以扇區(qū)為單位。BIOS負責MCU的啟動、提供各類構件、實現(xiàn)mbedOS的駐留以及生成函數(shù)原型級的對外接口函數(shù)表供USER使用;USER由用戶編寫,它可以調用BIOS提供的對外接口函數(shù),實現(xiàn)應用程序的功能需求。
圖1 分割獨享式Flash空間劃分
(2)RAM空間的劃分
MCU的RAM空間一般分為重定向段、data段、bss段、heap段和stack段,各段的作用見表1。??臻g的使用方向是從大地址向小地址方向進行的,??臻g的棧底位置應該設置為RAM最大地址+1處;而堆空間的使用方向是從小地址向大地址方向進行的。
表1 RAM中的各段作用
RAM空間的劃分也同樣分為BIOS和USER兩部分,前者包含重定向段、data段、bss段、heap段和stack段,后者包含data段、bss段、heap段和stack段。由于heap段和stack段都是用于存放臨時局部變量,可以重疊使用。因此,在RAM空間劃分上可以采用分割獨享和重疊共享兩種方式。分割獨享方式的優(yōu)勢在于BIOS和USER獨享自己的RAM空間,可以避免BIOS和USER運行時彼此間的數(shù)據(jù)重疊干擾,一般適用于RAM空間較大的情況。由于本文采用的KL36的RAM空間較小,因此采用重疊共享方式。
由于芯片上電啟動,運行完BIOS之后,程序會跳轉到USER執(zhí)行。此時,雖然BIOS完成了它的使命,但其RAM空間中的重定向段、data段、bss段和heap段仍要為USER服務,故需保留,而stack段的臨時變量不再被使用,無需保留。因此,可以充分利用這一特性,只需確保USER的RAM區(qū)域從BIOS的heap段之后開始,且BIOS的stack段的棧底地址與USER的stack段的棧底地址都指向RAM最大地址+1的位置,這樣可以將BIOS的stack段與USER的RAM空間共同使用同一段區(qū)域?;诖怂枷耄槍AM空間較小的情況,提出了采用重疊共享的方式來劃分RAM空間,如圖2所示,BIOS占用整個RAM空間,USER只占用BIOS的stack段這塊區(qū)域。
圖2 重疊共享式RAM空間劃分
通過對Flash和RAM空間的劃分,為mbedOS駐留在BIOS中提供了空間,但要發(fā)揮mbedOS的作用,還需將mbedOS的功能通過對外接口函數(shù)表的方式向USER提供服務。要達到這樣的目的,首先需要在BIOS中進行對外接口函數(shù)的定義、聲明、注冊,形成對外接口函數(shù)表;其次要在USER中獲取對外接口函數(shù)表的入口地址,并重定向對外接口函數(shù)名稱;最后在USER中實現(xiàn)對函數(shù)的調用,如圖3所示。
圖3 對外接口函數(shù)表的設計與實現(xiàn)
(1)對外接口函數(shù)的定義
對外接口函數(shù)不僅包含mbedOS的功能函數(shù),而且還可以包括各類構件函數(shù),其定義與一般函數(shù)的定義并無區(qū)別,主要包括函數(shù)名、函數(shù)的返回值類型、函數(shù)的參數(shù)、函數(shù)體等。
(2)對外接口函數(shù)的聲明
對外接口函數(shù)定義好之后,一般應在與之同名的.h頭文件中進行聲明,函數(shù)的聲明要給出函數(shù)名、函數(shù)的返回值類型、函數(shù)的參數(shù)以及函數(shù)的功能說明。
(3)對外接口函數(shù)的注冊
在對外接口函數(shù)定義和聲明之后,還要對函數(shù)進行注冊才能形成對外接口函數(shù)表。借鑒中斷向量表的定義做法,可以給所有的或部分的對外接口函數(shù)編號,并將函數(shù)名(即函數(shù)的入口地址)集中在一起按編號有序地放在一個統(tǒng)一的區(qū)域中,這個區(qū)域就稱為對外接口函數(shù)表。對外接口函數(shù)表常用數(shù)組(如BIOS_API)來存放,對外接口函數(shù)的編號與數(shù)組的下標元素一一對應,如0號對外接口函數(shù)對應BIOS_API[0],1號對外接口函數(shù)對應BIOS_API[1],依此類推。
(4)獲取對外接口函數(shù)表的入口地址
當BIOS的對外接口函數(shù)表形成之后,USER要使用它必須先獲得對外接口函數(shù)表的入口地址,也就是獲得存放對外接口函數(shù)表的數(shù)組首地址。為了與該數(shù)組的元素一一對應,在USER中一般也定義一個重定向表數(shù)組(如USER_API),這樣USER使用USER_API就相當于使用BIOS_API。也可以說,USER通過USER_API就可以訪問BIOS提供的對外接口函數(shù)。
(5)對外接口函數(shù)表的重定向
USER對對外接口函數(shù)表中函數(shù)的訪問是通過USER_API數(shù)組,如USER_API[1]訪問的是1號對外接口函數(shù)。但采用USER_API[i]這種形式對具體訪問的對外接口函數(shù)的類型、函數(shù)名、參數(shù)以及功能等不夠清晰明了。因此,類似中斷向量重定向的做法,也可以對對外接口函數(shù)進行重定向,即重新給USER_API[i]取另外一個用戶熟悉的函數(shù)名,這個函數(shù)名可以與對外接口函數(shù)名同名,也可以是不同名的,這樣就可以為用戶提供函數(shù)原型級的訪問方式,易于用戶記住和使用。如mbedOS中延時函數(shù)的名稱是wait,在重定向時可以取名為delay,表2列出了部分mbedOS對外接口函數(shù)。
表2 部分對外接口函數(shù)重定向
(6)函數(shù)調用
在對外接口函數(shù)表重定向之后,就可以利用重定向后的名字來調用對外接口函數(shù),如USER在調用delay函數(shù)時,實際上是指向了USER_API[3],而USER_API[3]對應BIOS_API[3],BIOS_API[3]存放的就是wait函數(shù)的入口地址,也就是USER通過delay達到調用wait的目的。
在GEC架構下,實現(xiàn)將mbedOS駐留在BIOS中,有以下幾個方面的關鍵點需要注意:
(1)合理分配Flash空間。由于Flash空間的劃分是以扇區(qū)為單位的,當Flash空間較小時,只須保留最基本的各類構件和mbedOS的最基本功能函數(shù)以滿足實際工程需要即可,確保BIOS的Flash空間不浪費;
(2)確保RAM空間不沖突。當RAM空間較小采用重疊共享方式劃分時,若BIOS使用new或malloc等動態(tài)內存申請函數(shù),此時申請的空間占用的是BIOS的heap段,當申請的內存過大,可能會出現(xiàn)heap段空間不夠而越界到USER的重定向段、data段、甚至bss段,造成USER無法正常運行;
(3)及時回收系統(tǒng)服務調用權。在GEC架構中,從芯片上電到最終用戶的任務執(zhí)行是先啟動BIOS,接著啟動USER,最后才啟動mbedOS。由于mbedOS的調度依賴于系統(tǒng)服務調用SVC、可掛起服務調用PendSV和系統(tǒng)時間嘀嗒SysTick等,而在啟動BIOS和USER時都會使用到SVC中斷,SysTick中斷也有可能會被作為定時器使用。因此,在啟動mbedOS前,必須及時將SVC、PendSV和SysTick的調用權回收,移交給mbedOS。
mbedOS的駐留測試工程在Kinetis Design Studio 3.0.0 IDE開發(fā)環(huán)境和金葫蘆AHL-A系列Cortex-M0+內核的KL36微控制器[14](即AHL-AN100VL型號開發(fā)板)上進行,分為BIOS和USER兩個工程,BIOS工程實現(xiàn)mbed-OS的駐留,先于USER固化到Flash中,USER工程實現(xiàn)應用功能。
KL36片內Flash大小為64 KB,分為64個扇區(qū),一般用來存放中斷向量(共有48個,占192字節(jié))、程序代碼、常數(shù)等;片內RAM為靜態(tài)隨機存儲器SRAM,大小為8 KB,一般用來存儲全局變量、靜態(tài)變量、臨時變量(堆棧空間)等。測試工程考慮到Flash和RAM空間較小,F(xiàn)lash空間采用圖1劃分方式,RAM采用圖2劃分方式。當mbedOS駐留后,F(xiàn)lash和RAM空間劃分情況見表3。
表3 KL36中BIOS和USER空間劃分
在GEC架構中,當mbedOS駐留在BIOS后,整個程序從上電啟動到最后由mbedOS實現(xiàn)對用戶任務的調度,需要經(jīng)歷BIOS啟動、USER啟動以及mbedOS啟動3個階段,其簡易啟動流程如圖4所示。
圖4 GEC架構下mbedOS的簡易啟動流程
首先,MCU上電開始BIOS的啟動,由硬件自動完成從Flash的0地址處取值對BIOS的堆棧指針初始化和啟動復位向量,接著進行系統(tǒng)時鐘初始化和各數(shù)據(jù)段的初始化,然后在main函數(shù)中調用projectJump跳轉到USER的執(zhí)行。
其次,從BIOS轉到USER的啟動,由用戶指令完成從Flash的0地址處取值對USER的堆棧指針初始化和啟動復位向量,接著進行各數(shù)據(jù)段的初始化,然后在USER的main函數(shù)調用mbedOS_start啟動mbedOS。
最后,從USER轉到mbedOS的啟動,包括設置mbed-OS的堆棧區(qū)、重定向中斷向量表、內核初始化、設置自啟動任務屬性、創(chuàng)建自啟動任務、啟動內核、調用自啟動任務的執(zhí)行函數(shù),然后由mbedOS完成對用戶任務的調度執(zhí)行。
USER工程的主要功能是創(chuàng)建兩個任務,實現(xiàn)每秒紅燈閃爍一次,藍燈任務每2 s切換亮暗一次,綠燈任務當收到藍燈任務的線程信號(34)時,切換綠燈亮暗。在USER 工程中,使用到了mbedOS提供的對外接口函數(shù)有延時、任務創(chuàng)建、任務啟動、信號設置和信號等待等函數(shù)。駐留測試工程的運行結果如圖5所示,從中可以看出mbedOS駐留成功,程序啟動流程正確,能準確調用mbedOS提供的對外接口函數(shù),任務在mbedOS調度下運行正常、程序執(zhí)行邏輯準確、實時性能得到滿足。
圖5 駐留測試工程的運行結果
為充分發(fā)揮實時操作系統(tǒng)mbedOS的強大功能和較高實時性的性能,本文結合固件技術的設計原則,深入剖析了GEC架構下mbedOS的駐留優(yōu)勢和關鍵技術,提出了分割獨享和重疊共享兩種方式來合理劃分Flash和RAM空間,詳細給出了對外接口函數(shù)設計與實現(xiàn),最后測試結果表明mbedOS駐留成功,F(xiàn)lash和RAM空間劃分合理,程序運行邏輯正確。同時,本文提出的對外接口函數(shù)重定向方法,使得用戶可以使用自己定義的函數(shù)名稱而不依賴于RTOS提供的函數(shù)名稱,提高了用戶程序的可移植性。后續(xù)將在不同MCU的可移植性和駐留等方面展開進一步的研究,文中的程序可在蘇州大學嵌入式學習社區(qū)(http://sumcu.suda.edu.cn)中下載查看。