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