OpenHarmony移植案例與原理 - startup子系統之bootstrap_lite服務啟動引導部件(2)
2.3 OHOS_SystemInit函數
函數OHOS_SystemInit()定義在文件base\startup\bootstrap_lite\services\source\system_init.c,代碼如下。調用宏函數MODULE_INIT、SYS_INIT和函數SAMGR_Bootstrap()進行初始化啟動。
void OHOS_SystemInit(void) { MODULE_INIT(bsp); MODULE_INIT(device); MODULE_INIT(core); SYS_INIT(service); SYS_INIT(feature); MODULE_INIT(run); SAMGR_Bootstrap(); }
我們詳細分析下宏函數MODULE_INIT和SYS_INIT的源代碼,這2個宏函數在文件base\startup\bootstrap_lite\services\source\core_main.h中定義,代碼如下。這些宏函數的參數大都為name和step,name取值為bsp、device、core、service、feature、run,step取值為0。從⑺和⑻處可以看出,分別調用SYS_CALL、MODULE_CALL兩個宏,第二個參數設置為0。⑸處定義的MODULE_BEGIN函數,用于返回鏈接腳本中定義的代碼段的開始地址,當傳入參數為bsp時,返回&__zinitcall_bsp_start,MODULE_BEGIN函數被展開為如下片段:
{ extern InitCall __zinitcall_sys_start; \ InitCall *initCall = &__zinitcall_bsp_start; \ (initCall); \ }
⑹處定義的MODULE_END函數,用于返回鏈接腳本中定義的代碼段的結束地址,當傳入參數為bsp時,返回&__zinitcall_bsp_end,MODULE_END函數被展開為如下片段:
{ extern InitCall __zinitcall_bsp_end; \ InitCall *initCall = &__zinitcall_bsp_end; \ (initCall); \ }
⑶和⑷處定義的SYS_BEGIN、SYS_END代碼類似,分于返回鏈接腳本中定義的標記系統服務或特性的代碼段的開始、結束地址,即&__zinitcall_sys_service_start、&__zinitcall_sys_service_end、&__zinitcall_sys_feature_start、&__zinitcall_sys_feature_end。⑴處定義的SYS_CALL函數,分別獲取鏈接腳本中zInit代碼段的開始initcall和結束地址initend,這些地址存放的是初始化函數的地址,語句 (*initcall)()會循環調用執行這些初始化函數。⑵處MODULE_CALL宏類似。
⑴ #define SYS_CALL(name, step) \ do { \ InitCall *initcall = (InitCall *)(SYS_BEGIN(name, step)); \ InitCall *initend = (InitCall *)(SYS_END(name, step)); \ for (; initcall < initend; initcall++) { \ (*initcall)(); \ } \ } while (0) ⑵ #define MODULE_CALL(name, step) \ do { \ InitCall *initcall = (InitCall *)(MODULE_BEGIN(name, step)); \ InitCall *initend = (InitCall *)(MODULE_END(name, step)); \ for (; initcall < initend; initcall++) { \ (*initcall)(); \ } \ } while (0) ...... ⑶ #define SYS_BEGIN(name, step) \ ({ extern InitCall __zinitcall_sys_##name##_start; \ InitCall *initCall = &__zinitcall_sys_##name##_start; \ (initCall); \ }) ⑷ #define SYS_END(name, step) \ ({ extern InitCall __zinitcall_sys_##name##_end; \ InitCall *initCall = &__zinitcall_sys_##name##_end; \ (initCall); \ }) ⑸ #define MODULE_BEGIN(name, step) \ ({ extern InitCall __zinitcall_##name##_start; \ InitCall *initCall = &__zinitcall_##name##_start; \ (initCall); \ }) ⑹ #define MODULE_END(name, step) \ ({ extern InitCall __zinitcall_##name##_end; \ InitCall *initCall = &__zinitcall_##name##_end; \ (initCall); \ }) ⑺ #define SYS_INIT(name) \ do { \ SYS_CALL(name, 0); \ } while (0) ⑻ #define MODULE_INIT(name) \ do { \ MODULE_CALL(name, 0); \ } while (0)
3、 bootstrap_lite服務啟動引導部件實現原理之bootstrap_service
在文件base\startup\bootstrap_lite\services\source\bootstrap_service.h中定義了2個宏函數INIT_APP_CALL和INIT_TEST_CALL,分別用來調用代碼段&__zinitcall_app_XXX_start、&__zinitcall_app_XXX_end和&__zinitcall_test_start、&__zinitcall_test_end之間的初始化啟動函數。bootstrap_service.h文件中的宏和base\startup\bootstrap_lite\services\source\core_main.h文件中的宏類似,不再一一分析。
3.1 結構體struct Bootstrap
在文件base\startup\bootstrap_lite\services\source\bootstrap_service.c中定義了結構體struct Bootstrap,如下代碼⑵處。其中結構體中的INHERIT_SERVICE定義在文件foundation/distributedschedule/samgr_lite/interfaces/kits/samgr/service.h,見代碼片段⑴處。
⑴ #define INHERIT_SERVICE \ const char *(*GetName)(Service * service); \ BOOL (*Initialize)(Service * service, Identity identity); \ BOOL (*MessageHandle)(Service * service, Request * request); \ TaskConfig (*GetTaskConfig)(Service * service) ...... ⑵ typedef struct Bootstrap { INHERIT_SERVICE; Identity identity; uint8 flag; } Bootstrap;
結構體Identity定義在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\message.h中,用于標識一個服務或特性。
/** * @brief Identifies a service and feature. * * You can use this structure to identity a {@link IUnknown} feature to which messages will be * sent through the asynchronous function of {@link IUnknown}. \n * */ struct Identity { /** Service ID */ int16 serviceId; /** Feature ID */ int16 featureId; /** Message queue ID */ MQueueId queueId; };
3.2 Init(void)函數
講解移植適配示例時,我們已經知道,bootstrap_lite部件會編譯//base/startup/bootstrap_lite/services/source/bootstrap_service.c,該文件通過函數宏SYS_SERVICE_INIT將Init()函數符號灌段到__zinitcall_sys_service_start和__zinitcall_sys_service_end代碼段中,代碼片段如下。下文再詳細分析GetName、Initialize、MessageHandle和GetTaskConfig函數。
static const char *GetName(Service *service); static BOOL Initialize(Service *service, Identity identity); static TaskConfig GetTaskConfig(Service *service); static BOOL MessageHandle(Service *service, Request *request); static void Init(void) { static Bootstrap bootstrap; bootstrap.GetName = GetName; bootstrap.Initialize = Initialize; bootstrap.MessageHandle = MessageHandle; bootstrap.GetTaskConfig = GetTaskConfig; bootstrap.flag = FALSE; SAMGR_GetInstance()->RegisterService((Service *)&bootstrap); } SYS_SERVICE_INIT(Init);
3.3 GetName和Initialize函數
GetName函數代碼如下,其中BOOTSTRAP_SERVICE定義在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\samgr_lite.h中,取值為"Bootstrap",表示啟動引導服務。
static const char *GetName(Service *service) { (void)service; return BOOTSTRAP_SERVICE; }
Initialize函數定義如下,用于設置啟動引導服務的標識信息。
static BOOL Initialize(Service *service, Identity identity) { Bootstrap *bootstrap = (Bootstrap *)service; bootstrap->identity = identity; return TRUE; }
3.4 MessageHandle函數和GetTaskConfig函數
MessageHandle函數和GetTaskConfig函數代碼如下,MessageHandle函數用于處理各種請求,請求消息編號定義request->msgId定義在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\samgr_lite.h中的枚舉enum BootMessage,如下⑴處所示。在MessageHandle函數中,當請求的消息編號為BOOT_SYS_COMPLETED系統服務初始化完成時,檢查應用服務是否加載。當應用沒有加載時,執行INIT_APP_CALL宏函數調用zInit代碼段上的應用服務和應用特性初始化函數。然后執行⑶,調用函數SAMGR_SendResponseByIdentity進行響應。GetTaskConfig函數用于獲取任務配置。
⑴ typedef enum BootMessage { /** Message indicating that the core system service is initialized */ /** 標識核心系統服務初始化完成 */ BOOT_SYS_COMPLETED, /** Message indicating that the system and application-layer services are initialized */ /** 標識應用層服務初始化完成 */ BOOT_APP_COMPLETED, /** Message indicating service registration during running */ /** 標識運行時的服務注冊 */ BOOT_REG_SERVICE, /** Maximum number of message IDs */ /** 標識消息最大值,butt是煙蒂;屁股;槍托的意思,表示尾部吧 */ BOOTSTRAP_BUTT } BootMessage; ...... static BOOL MessageHandle(Service *service, Request *request) { Bootstrap *bootstrap = (Bootstrap *)service; switch (request->msgId) { case BOOT_SYS_COMPLETED: ⑵ if ((bootstrap->flag & LOAD_FLAG) != LOAD_FLAG) { INIT_APP_CALL(service); INIT_APP_CALL(feature); bootstrap->flag |= LOAD_FLAG; } ⑶ (void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL); break; case BOOT_APP_COMPLETED: (void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL); break; case BOOT_REG_SERVICE: (void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL); break; default: break; } return TRUE; } static TaskConfig GetTaskConfig(Service *service) { (void)service; // The bootstrap service uses a stack of 2 KB (0x800) in size and a queue of 20 elements. // You can adjust it according to the actual situation. TaskConfig config = {LEVEL_HIGH, PRI_NORMAL, 0x800, 20, SHARED_TASK}; return config; }
參考站點
OpenHarmony / startup_bootstrap_lite
HarmonyOS Device > 文檔 > 指南 > 基礎能力: bootstrap服務啟動組件
啟動恢復子系統.md
輕量帶屏解決方案之恒玄芯片移植案例
小結
本文介紹了startup子系統之bootstrap_lite服務啟動引導部件的移植適配案例及原理。因為時間關系,倉促寫作,或能力限制,若有失誤之處,請各位讀者多多指正。感謝閱讀,有什么問題,請留言。
Bootstrap IoT 輕量級操作系統 LiteOS
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。