蔣建武, 王宜懷
(1. 蘇州大學(xué)計算機(jī)科學(xué)與技術(shù)學(xué)院, 江蘇 蘇州 215006;2. 泰州職業(yè)技術(shù)學(xué)院信息工程學(xué)院, 江蘇 泰州 225300)
?
MQX操作系統(tǒng)啟動流程剖析
蔣建武1, 2, 王宜懷1
(1. 蘇州大學(xué)計算機(jī)科學(xué)與技術(shù)學(xué)院, 江蘇 蘇州215006;2. 泰州職業(yè)技術(shù)學(xué)院信息工程學(xué)院, 江蘇 泰州225300)
摘要:針對嵌入式操作系統(tǒng)啟動流程中的內(nèi)核數(shù)據(jù)區(qū)的結(jié)構(gòu)及其初始化, MQX運行所需系統(tǒng)中斷和時鐘滴答的初始設(shè)置, 系統(tǒng)初始化任務(wù)及其空閑任務(wù)的創(chuàng)建與啟動等問題. 提出了實際應(yīng)用中冷熱復(fù)位區(qū)別啟動、 系統(tǒng)滴答時鐘調(diào)整等問題的操作系統(tǒng)內(nèi)核級解決方法. 結(jié)果表明該方法提升了帶MQX操作系統(tǒng)的應(yīng)用項目的實時性、 穩(wěn)定性、 魯棒性等性能.
關(guān)鍵詞:MQX嵌入式操作系統(tǒng); 啟動流程; 內(nèi)核數(shù)據(jù)區(qū); 時鐘滴答
0引言
MQX(message queue eXecutive)操作系統(tǒng)是一款免費、 開源、 有技術(shù)支持的嵌入式實時操作系統(tǒng)(RTOS), 主要面向工業(yè)控制、 醫(yī)療電子、 家用電器等應(yīng)用開發(fā)領(lǐng)域, 目前基于MQX的產(chǎn)品已達(dá)數(shù)百萬. 從1989年至今, MQX已經(jīng)走過了二十多年的發(fā)展歷程, 飛思卡爾于2009年收購MQX, 組織專門團(tuán)隊升級維護(hù), 并提供免費技術(shù)支持, 至2014年2月推出最新版本4.1.0[1].
與通用PC操作系統(tǒng)下的工程項目開發(fā)相比, 嵌入式操作系統(tǒng)環(huán)境下的開發(fā)對系統(tǒng)的實時性、 穩(wěn)定性、 啟動時間等方面要求更加嚴(yán)格, 由于資源的有限性, 對于資源消耗, 代碼執(zhí)行效率等方面要求也更高. 嵌入式操作系統(tǒng)中對于內(nèi)存、 外設(shè)、 任務(wù)調(diào)度策略等內(nèi)容均在啟動過程中配置, 清晰理解嵌入式操作系統(tǒng)的啟動執(zhí)行流程可幫助開發(fā)人員設(shè)計出更加穩(wěn)定高效的嵌入式應(yīng)用系統(tǒng). 陳鵬[2]在Linux操作系統(tǒng)下提出了基于狀態(tài)保持恢復(fù)的快速啟動方法, 溫圣軍[3]立足于系統(tǒng)安全性提出了重構(gòu)嵌入式系統(tǒng)安全啟動流程設(shè)計, 鄧國榮[4]在分析傳統(tǒng)基于AIS和串口引導(dǎo)啟動的基礎(chǔ)上, 提出了基于NORFlash實現(xiàn)OMAPL138雙核系統(tǒng)二次引導(dǎo)自舉啟動的方法. 羅蕾[5]研究發(fā)現(xiàn), 通過對操作系統(tǒng)啟動流程的分析改進(jìn), 可以切實地提升系統(tǒng)的啟動時間、 執(zhí)行效率、 安全特性等各方面性能.
目前, 在文獻(xiàn)中多為針對Linux、 Android等嵌入式操作系統(tǒng)的啟動研究[6], 并無剖析MQX的啟動流程的相關(guān)資料. 對此將在CodeWarrior v10.5嵌入式軟件集成開發(fā)平臺下, 以SD-FSL-K60-C評估板作為硬件平臺, 利用蘇州大學(xué)飛思卡爾嵌入式系統(tǒng)實驗中心(http://sumcu.suda.edu.cn/)發(fā)布的有無操作系統(tǒng)相統(tǒng)一的AMQXFW工程框架對MQX操作系統(tǒng)啟動流程進(jìn)行研究. 剖析其從芯片上電, 經(jīng)主程序Main, 最終進(jìn)入操作調(diào)度的啟動全過程. 分析了實現(xiàn)機(jī)理, 給出了執(zhí)行流程并對關(guān)鍵代碼進(jìn)行了分析.
1AMQXFW工程框架啟動流程
AMQXFW工程框架啟動過程分為芯片啟動和MQX系統(tǒng)啟動兩部分[7], 如圖1. 芯片啟動過程包括存儲映射區(qū)域解析、 中斷向量表解析、 引導(dǎo)啟動boot、 程序啟動startup和主程序啟動main, 這部分內(nèi)容與操作系統(tǒng)無關(guān), 進(jìn)入main主函數(shù)中后調(diào)用_mqx()函數(shù)將系統(tǒng)控制權(quán)交給MQX操作系統(tǒng).
在ARM Cortex-M4處理器架構(gòu)中, 芯片上電后自動執(zhí)行物理地址0x00000000h處指令, 查詢位于芯片內(nèi)部的存儲映射區(qū)域. 從中斷向量表中獲取其中第一個表項作為系統(tǒng)棧的棧首指針賦給MSP(main stack pointer, 主棧指針), 獲取其中的第二個表項作為系統(tǒng)啟動函數(shù)的地址賦給PC(program counter, 程序計數(shù)器)[8-9]. 在AMQXFW工程框架中, 由_boot函數(shù)執(zhí)行啟動, 執(zhí)行關(guān)中斷、 切換堆棧等過程. 然后轉(zhuǎn)入執(zhí)行_thumb_startup函數(shù), 進(jìn)入C語言函數(shù)部分, 完成禁用看門狗(wdog_disable)、 初始化內(nèi)存數(shù)據(jù)(_copy_rom_sections_to_ram)、 初始化系統(tǒng)時鐘(system clock setup)等操作[10]. 最后進(jìn)入main函數(shù)執(zhí)行, 調(diào)用MQX操作系統(tǒng)的入口函數(shù)_mqx()開始啟動MQX.
MQX進(jìn)入main函數(shù)之后, 調(diào)用MQX的入口函數(shù)開始啟動, 初始化后由任務(wù)調(diào)度機(jī)制控制系統(tǒng)執(zhí)行. MQX啟動過程完成操作系統(tǒng)運行所需的內(nèi)核數(shù)據(jù)區(qū)變量初始化、 中斷初始化、 外設(shè)初始化, 以及各種任務(wù)隊列的創(chuàng)建等工作.
2MQX操作系統(tǒng)內(nèi)核數(shù)據(jù)區(qū)
內(nèi)核數(shù)據(jù)區(qū)是用來表明MQX的狀態(tài)和動態(tài)變量的結(jié)構(gòu)體, 它的成員數(shù)不是固定的, 其中有些變量是根據(jù)配置決定是否編譯, 所以內(nèi)核數(shù)據(jù)區(qū)的大小不是固定的.
2.1內(nèi)核數(shù)據(jù)區(qū)的存儲位置
AMQX工程框架的鏈接文件intflash.ld對RAM進(jìn)行分配和部署. K60微控制器RAM共有128 KB, 地址范圍0x1FFF0000到0x2000FFFF, 如圖2所示. _KERNEL_DATA_END定義為0x2000FFF0, 預(yù)留了15個字節(jié), 防止內(nèi)存塊地址對齊時出現(xiàn)地址越界的發(fā)生. 從0x1FFF0000開始的一段區(qū)域用于存放從FLASH復(fù)制來的數(shù)據(jù), 系統(tǒng)啟動時startup.c文件會初始化這段數(shù)據(jù)區(qū), 該區(qū)包括中斷向量表、 .DATA和.BSS等數(shù)據(jù). 在采用段式內(nèi)存管理的架構(gòu)中, .BSS段通常是指用來存放程序中未初始化的全局變量的一塊內(nèi)存區(qū)域, .BSS段屬于靜態(tài)內(nèi)存分配; 而另一個.DATA段, 用來存放程序已初始化的全局變量; 而函數(shù)內(nèi)的局部變量都在棧上分配空間[11]. 在項目開發(fā)中加入冷熱復(fù)位處理時要注意跳過對.BSS段初始化為零的操作, 否則系統(tǒng)將因為全局變量的重新賦值而恢復(fù)不到復(fù)位前的狀態(tài).
2.2內(nèi)核數(shù)據(jù)區(qū)數(shù)據(jù)結(jié)構(gòu)kernel_data_struct
MQX初始化函數(shù)_mqx()的結(jié)構(gòu)體參數(shù)MQX_INITIALIZATION_STRUCT包含了初始化MQX的基本信息, 如處理器個數(shù)、 中斷堆棧大小等成員變量. BSP_DEFAULT_START_ OF_KERNEL_MEMORY代表了內(nèi)核所在內(nèi)存的起始地址, 具體數(shù)值在intflash.ld文件中定義, 這個起始地址就是內(nèi)核數(shù)據(jù)區(qū)kernel_data_struct的起始地址. 執(zhí)行_mqx()函數(shù)的過程中, 程序會對這塊內(nèi)存區(qū)域kernel_data_struct成員變量進(jìn)行賦值, 其主要成員變量如表1所示[12].
表1 kernel_data_struct結(jié)構(gòu)表
MQX_INITIALIZATION_STRUCT類型常量MQX_init_struct包含了啟動MQX所需的所有參數(shù)的預(yù)設(shè)值, 各成員的數(shù)值及含義如表2所示.
表2 MQX_init_struct結(jié)構(gòu)表
3MQX操作系統(tǒng)啟動流程源碼剖析
在main函數(shù)中, 將MQX初始化參數(shù)傳入_mqx函數(shù), 執(zhí)行_mqx函數(shù)啟動MQX系統(tǒng). MQX啟動過程如下: 初始化內(nèi)核數(shù)據(jù)區(qū), 初始化MQX運行所需系統(tǒng)模塊, 創(chuàng)建系統(tǒng)初始化任務(wù), 創(chuàng)建空閑任務(wù), 啟動任務(wù)調(diào)度器.
3.1初始化內(nèi)核數(shù)據(jù)區(qū)
內(nèi)核數(shù)據(jù)區(qū)是負(fù)責(zé)記錄MQX系統(tǒng)運行狀態(tài)及資源使用情況的存儲區(qū), 在開始正常工作之前, 要確保為內(nèi)核數(shù)據(jù)區(qū)指定合適的初始值.
1)創(chuàng)建內(nèi)核數(shù)據(jù)區(qū)訪問指針kernel_data.
//獲得內(nèi)核數(shù)據(jù)區(qū)的首地址, 執(zhí)行地址對齊后, 作為內(nèi)核數(shù)據(jù)區(qū)的訪問地址
kernel_data = (KERNEL_DATA_STRUCT_PTR)
_ALIGN_ADDR_TO_HIGHER_MEM(mqx_init->START_OF_KERNEL_MEMORY);
_SET_KERNEL_DATA(kernel_data);// 設(shè)置將內(nèi)核數(shù)據(jù)區(qū)的首地址指向全局變量區(qū)
內(nèi)核數(shù)據(jù)區(qū)空間在鏈接命令文件中的定義, 屬于BSP的內(nèi)容. 為了提高相對于BSP的獨立性, 此處創(chuàng)建了一個內(nèi)核數(shù)據(jù)區(qū)訪問指針, 并定義了訪問接口. 以后的程序中, 只要將kernel_data定義為“volatile KERNEL_DATA_STRUCT_PTR”類型, 再使用“_GET_KERNEL_DATA(kernel_data)”宏函數(shù), 即可訪問內(nèi)核數(shù)據(jù)區(qū).
2)填充內(nèi)核數(shù)據(jù)區(qū). 在MQX啟動過程中要將系統(tǒng)設(shè)定的初始信息填充到內(nèi)核數(shù)據(jù)區(qū). 操作流程包括操作系統(tǒng)版本號與廠商名稱賦值、 內(nèi)核數(shù)據(jù)區(qū)字段置0、 內(nèi)核數(shù)據(jù)區(qū)讀寫功能驗證、 MQX內(nèi)核數(shù)據(jù)區(qū)初始化數(shù)據(jù)賦值等, 詳細(xì)流程如圖3所示.
3)系統(tǒng)中斷棧初始化. 若使用中斷, 則需要為系統(tǒng)中斷棧分配存儲空間并在內(nèi)核數(shù)據(jù)區(qū)中登記. 當(dāng)產(chǎn)生嵌套中斷時, 系統(tǒng)將把嵌套中斷的上下文保存在中斷棧中. 高優(yōu)先級中斷服務(wù)例程執(zhí)行返回后, 從中斷棧中恢復(fù)低優(yōu)先級中斷上下文繼續(xù)執(zhí)行.
4)創(chuàng)建系統(tǒng)任務(wù)棧. 系統(tǒng)棧用于自動維護(hù)系統(tǒng)空閑任務(wù), 非用戶創(chuàng)建. 當(dāng)系統(tǒng)空閑任務(wù)被中斷阻塞時, 使用系統(tǒng)棧保存空閑任務(wù)的上下文. 系統(tǒng)棧指針鏈接在kernel_data->SYSTEM_TD上, 可由全局變量_mqx_system_stack操作控制.
5)創(chuàng)建就緒任務(wù)隊列數(shù)組與操作信號量. 就緒任務(wù)隊列數(shù)組是任務(wù)調(diào)度系統(tǒng)操縱的主要對象, 在系統(tǒng)初始化過程中, 根據(jù)任務(wù)模板列表中用戶定義的任務(wù)最低優(yōu)先級創(chuàng)建就緒隊列數(shù)目并根據(jù)優(yōu)先級排序. 在就緒任務(wù)隊列剛被創(chuàng)建時, 每個就緒任務(wù)隊列中僅包含一個隊列頭結(jié)構(gòu), 當(dāng)有任務(wù)進(jìn)入就緒態(tài)后, 該任務(wù)的描述符就掛載到相應(yīng)優(yōu)先級的就緒任務(wù)隊列上. 在內(nèi)核數(shù)據(jù)區(qū)中為創(chuàng)建和刪除任務(wù)創(chuàng)建一個輕量級信號量, 用以保證同步訪問能夠正確進(jìn)行.
3.2MQX運行所需系統(tǒng)模塊初始化
在系統(tǒng)啟動時通過_bsp_pre_init函數(shù)對硬件平臺進(jìn)行初始化, 主要內(nèi)容有:
1) 初始化MQX的中斷系統(tǒng). 為中斷系統(tǒng)分配動態(tài)中斷向量鏈接表頭節(jié)點, 初始化動態(tài)中斷向量表.
//初始化MQX的中斷管理系統(tǒng)
result = _psp_int_init(BSP_FIRST_INTERRUPT_VECTOR_USED, BSP_LAST_INTERRUPT_VECTOR_USED);
//設(shè)置硬件中斷向量表的存儲位置
(void)_int_set_vector_table(BSP_INTERRUPT_VECTOR_TABLE);
//將Systick設(shè)置為系統(tǒng)滴答定時器中斷向量
_time_set_timer_vector(BSP_TIMER_INTERRUPT_VECTOR);
//為定時器中斷安裝ISR服務(wù)例程
if (_int_install_isr(BSP_TIMER_INTERRUPT_VECTOR, (void (_CODE_PTR_)(pointer))_bsp_systick, NULL) == NULL) return MQX_TIMER_ISR_INSTALL_FAIL}
MQX對動態(tài)中斷向量表進(jìn)行分組管理, 每組的節(jié)點數(shù)由配置文件small_ram_config.h中的宏MQX_SPARSE_ISR_SHIFT的定義值決定, 缺省值一般為3, 每組的節(jié)點數(shù)為23=8. 初始化的動態(tài)中斷向量鏈接表頭節(jié)點為一個中斷服務(wù)的數(shù)組指針, 數(shù)組的大小由給定的中斷向量數(shù)除以8得到, 每組數(shù)組元素指針指向一組鏈表. 當(dāng)中斷事件產(chǎn)生后, MQX的中斷處理系統(tǒng)將在中斷向量鏈表中查詢相應(yīng)的服務(wù)函數(shù)并調(diào)用執(zhí)行. 動態(tài)中斷向量表機(jī)制中中斷服務(wù)例程可在系統(tǒng)運行過程中安裝更新, 根據(jù)不同需要可以為同一中斷源動態(tài)配置中斷服務(wù)例程, 這樣使得中斷處理更加靈活.
2) 初始化系統(tǒng)時間滴答. MQX操作系統(tǒng)運行時, 需要一個滴答(tick)時鐘信號, 驅(qū)動操作系統(tǒng)的時間管理系統(tǒng)工作. ARM Cortex-M4處理器內(nèi)部提供了一個Systick定時器, 是一個可編程的硬件模塊, 以固定的頻率產(chǎn)生中斷. 該中斷就是Systick中斷, 它所處理的中斷處理程序負(fù)責(zé)更新系統(tǒng)時間, 也負(fù)責(zé)執(zhí)行需要周期性運行的任務(wù). 系統(tǒng)滴答包括滴答計數(shù)TICKS與硬件滴答計數(shù)HW_TICKS, 初始化過程如下:
//初始化系統(tǒng)ticks變量
kernel_data->TIMER_HW_REFERENCE = (BSP_SYSTEM_CLOCK / BSP_ALARM_FREQUENCY);
_time_set_ticks_per_sec(BSP_ALARM_FREQUENCY);
_time_set_hwticks_per_tick(kernel_data->TIMER_HW_REFERENCE);
_time_set_hwtick_function(_bsp_get_hwticks, (pointer)NULL);
在AMWXFW工程框架中BSP_SYSTEM_CLOCK為96M, BSP_ALARM_FREQUENCY為200, 由以上初始化代碼可知滴答時間為1/200=5 ms, 硬滴答時間為200/96M=1/480 ms, 當(dāng)?shù)未鹩嫈?shù)器TICKS=10與硬滴答計數(shù)器HW_TICKS=48時, 則系統(tǒng)運行了(10×5+48/480)=50.1 ms, Systick中斷執(zhí)行了10次.
3.3任務(wù)初始化與調(diào)度
1) 啟動系統(tǒng)初始化任務(wù). 系統(tǒng)初始化任務(wù)是MQX系統(tǒng)創(chuàng)建的初始化任務(wù), 完成BSP設(shè)備初始化和自動運行任務(wù)加入就緒任務(wù)隊列兩項工作. 通過_mqx_init_task()函數(shù)完成, 在其中利用_bsp_init()函數(shù)完成dma設(shè)備列表初始化、 內(nèi)核IO子系統(tǒng)初始化、 默認(rèn)UART調(diào)試串口初始化、 內(nèi)核串行IO端口初始化. 為了提高啟動速度, 應(yīng)將所有非系統(tǒng)必要的硬件設(shè)備初始化操作均可以調(diào)整到用戶設(shè)計的初始化硬件設(shè)備任務(wù)中進(jìn)行.
2) 啟動空閑任務(wù)初始化. 為便于維護(hù)系統(tǒng)中的任務(wù)隊列, MQX會創(chuàng)建一個空閑任務(wù). 當(dāng)所有應(yīng)用任務(wù)均不再執(zhí)行, 系統(tǒng)仍然運行此空閑任務(wù), 以保證MQX的調(diào)度系統(tǒng)保持工作狀態(tài).
3) 啟動任務(wù)調(diào)度器. 在做好所有啟動MQX的準(zhǔn)備后, 啟動調(diào)度程序_sched_start_internal(), 系統(tǒng)的控制權(quán)就轉(zhuǎn)移給調(diào)度系統(tǒng). 在調(diào)度系統(tǒng)的管理下, 根據(jù)系統(tǒng)使用的調(diào)度策略依次調(diào)度各個任務(wù)執(zhí)行, 實現(xiàn)系統(tǒng)功能.
4結(jié)語
操作系統(tǒng)的啟動過程包含對操作系統(tǒng)運行時所需資源的初始化, 明晰其執(zhí)行流程可快速把握操作系統(tǒng)的整體架構(gòu). 本文通過對AMQXFW工程框架執(zhí)行流程的分析, 將MQX操作系統(tǒng)的啟動流程界定為芯片啟動和操作系統(tǒng)啟動兩個獨立的過程, 簡要給出了前期的引導(dǎo)啟動過程, 著重分析了進(jìn)入操作系統(tǒng)后的內(nèi)核數(shù)據(jù)區(qū)、 初始化中斷和系統(tǒng)滴答的初始化, 以及任務(wù)調(diào)度啟動過程. 對MQX的啟動流程分析可以為優(yōu)化啟動過程、 簡化執(zhí)行流程、 提升啟動速度等進(jìn)一步研究工作奠定基礎(chǔ).
參考文獻(xiàn):
[1] Freescale. Freescale MQX RTOS 4.1.0[EB/OL]. (2014-02-16)[2014-03-02]. http://www.freescale.com/mqx.
[2] 陳鵬, 王樹志, 張全勝, 等. 基于狀態(tài)保持恢復(fù)的嵌入式Linux快速啟動方法的研究[J]. 微計算機(jī)信息, 2012(9): 48-50.
[3] 溫圣軍, 張魯國. 可重構(gòu)嵌入式系統(tǒng)安全啟動流程設(shè)計與實現(xiàn)[J]. 計算機(jī)工程, 2009, 35(20): 134-136.
[4] 鄧國榮, 劉厚欽. 基于NOR Flash的OMAPL138雙核系統(tǒng)自舉引導(dǎo)啟動實現(xiàn)[J]. 電子技術(shù)應(yīng)用, 2014, 40(2): 19-22.
[5] 羅蕾. 嵌入式實時操作系統(tǒng)及應(yīng)用開發(fā)[M]. 北京: 北京航空航天大學(xué)出版社, 2011.
[6] 湯書森, 劉棟. 基于ARM處理器PXA270&Linux的嵌入式系統(tǒng)的啟動過程分析[J]. 甘肅科技, 2011, 27(6): 14-16.
[7] 蘇勇. 嵌入式實時操作系統(tǒng)MQX應(yīng)用框架研究[D]. 蘇州: 蘇州大學(xué), 2013.
[8] ARM. Cortex-M4 devices generic user guide[EB/OL]. (2010-12-26)[2011-06-08]. http://www.arm.com.
[9] Freescale. K60 sub-family reference manual rev.6[EB/OL]. (2011-11-12) [2012-03-18]. http://www.freescale.com.
[10] 王宜懷, 吳瑾, 蔣銀珍. 嵌入式系統(tǒng)原理與實踐-ARM Cortex-M4 Kinetis微控制器[M]. 北京: 電子工業(yè)出版社, 2012.
[11] 石晶, 王宜懷, 蘇勇, 等. 基于ARM Cortex-M4的MQX中斷機(jī)制分析與中斷程序框架設(shè)計[J]. 計算機(jī)科學(xué), 2013, 40(6): 41-44.
[12] Freescale. Freescale MQX RTOS user’s guide rev.6[EB/OL]. (2014-02-12)[2014-05-13].http://www.freescale.com/mqx.
(責(zé)任編輯: 林曉)
Analysis of the boot process of MQX RTOS
JIANG Jianwu1, 2, WANG Yihuai1
(1. School of Computer Science and Technology, Soochow University, Suzhou, Jiangsu 215006, China;2. Department of Electronic and Information Engineering, Taizhou Polytechnic College, Taizhou, Jiangsu 225300, China)
Abstract:The boot process of embedded operating system is the leading process of its running. This paper deeply analyzes a series of problems existing in the boot process of embedded operating system startup process, including initial set kernel data structure and its initialization, the setting method of system interruption and clock required to Run the MQX operating system, the creating and starting process of the system initialization task and the idle task.It presents some of the operating system kernel level solutions, to solve differences start on the practical application in hot and cold reset, system clock tick by adjustment problems, so as to enhance the performance of various kinds of application projects with the MQX operating system, including real-time, stability, robustness.
Keywords:MQX RTOS; boot process; kernal data; ticks
中圖分類號:TP316.2
文獻(xiàn)標(biāo)識碼:A
基金項目:國家自然科學(xué)基金資助項目(60871086); 泰州職業(yè)技術(shù)學(xué)院碩博基金資助項目(TZYBS-14-5)
通訊作者:王宜懷(1962-), 教授, 主要從事嵌入式系統(tǒng)與物聯(lián)網(wǎng)、 智能控制等方面研究, Yihuaiw@suda.edu.cn
收稿日期:2014-07-07
文章編號:1000-2243(2016)02-0202-05
DOI:10.7631/issn.1000-2243.2016.02.0202