[文章]鸿蒙系统的启动流程v3.0: 基于Hi3861平台+LiteOS_M内核

阅读量0
0
2
文章转载自:liangkz

声明:
升级文档到v2.0后可以声明是原创的了。这是上了朱有鹏老师的免费课《想读懂鸿蒙2.0源码,也许你需要先懂这些》之后,做的一些总结。

课程时间一个半小时,内容也很多,学习过程中我发现朱老师的ppt上部分代码/文件,在我本地的鸿蒙系统代码上找不到,或者路径不相同,所以我就做了一些整理。
这里仅摘取课程中的鸿蒙系统在HI3516DV300平台上的启动流程部分(从30:00开始讲解启动过程)进行汇总和整理,如有错误,请朱老师和各位同学指正。后继在学习过程中会继续对本文当作修正升级。

v1.0/2.0版本都是基于Hi3516平台+LiteOS_A内核的启动流程分析,即Part 1【鸿蒙系统的启动流程v2.0】
v3.0 版本开始增加基于Hi3861平台+LiteOS_M内核的启动流程分析,即Part 2。

更新记录:
2021.04.11
v1.0初始版本,有不少理解不到位或错误的地方,详见第一版文档《鸿蒙系统的启动流程v1.0》的附件pdf 文档。(Link:https://bbs.elecfans.com/jishu_2272471_1_1.html )
2021.04.15v2.0重新整理了第四阶段:鸿蒙系统框架层的启动:增加了新的理解内容,修改错误。增加了框架层的启动细节部分概述。(Link: https://bbs.elecfans.com/jishu_2272487_1_1.html)
2021.04.16v3.0v1.0/2.0版本都是基于Hi3516平台+LiteOS_A内核的启动流程分析。v3.0增加了Part 2,基于Hi3861平台+LiteOS_M内核的启动流程分析。

Part 2: 基于Hi3861平台+LiteOS_M内核
说明:
1. 我本地的OpenHarmony 1.1.0 LTS(2021-04-01)代码根目录OHOS1_1_0LTS,如Part 1前文所述。
2. 我有Hi3861_Wifiiot开发板和开发环境,如下:

2.1 在Linux环境下的DecEco IDE下创建新工程“Test_Wifiiot”,在“HPM”标签下找到“@ohos/wifi_iot”,  点击“Install to project”选择“Test_Wifiiot”项目,开始下载并安装组件到项目里。如下图:
2.2 打开工程,可以一键build,也可以在终端输入“python build.py wifiiot”指令进行build。

2.3 在Window主机下,打开DevEco IDE,做好相关配置,连接好Hi3861开发板,烧录上面编好的软件,也可以用HiBurn工具进行烧录。

2.4 烧录完成后,重启开发板,抓取log分析。

3. 网上找到的信息,Hi3861平台的LiteOS_M内核是固化在板子ROM上的,官方文档对Hi3861开发板的说明并没 有提到这一点,见【Hi3861开发板介绍】。

也就是说上面的烧录过程,其实并不会烧录内核部分的代码。

甚至在上面的Test_Wifiiot项目中都不会编译 LiteOS_M的内核代码,可以查看build脚本和build log:
Test_Wifiiotvendorhisihi3861hi3861uilduild_tmplogsuild_kernel.log
进行分析确认。

实际上我是这样确认的:
修改 Test_Wifiiotkernelliteos_mkernellos_init.c (或者子目录的los_xxx.c文件),添加log,故意写入错误的语法,希望触发编译错误。实际编译OK,说明其实没有编译到这部分代码。烧录软件后,添加的log,一个都没打印出来。

4. Test_Wifiiotkernelliteos_m目录下的kernel 虽然没有编译,但是components是有编译的,因为这下面是非常 重要的KAL组件。

KAL(Kernel Abstract Layer,内核抽象层),是鸿蒙系统框架层(Framework)与内核(LiteOS_M、LiteOS_A、Linux内核) 之间的接口,鸿蒙系统框架层与内核层是通过KAL接口进行隔离和解耦的。

KAL可以按照cmsis标准或者posix标准来实现Framework和kernel的对接,目前代码看到的是按cmsis-rtos v2 标准来实现的,详情见components 目录下的代码,可以在里面加log,跑起来可以打印log。

这个components就非常重要了,例如,在helloworld上创建线程时,需要在BUILD.gn中include "//kernel/liteos_m/components/cmsis/2.0" 路径,代码中#include "cmsis_os2.h"头文件,否则会编译失败。

5. 因为上面3的原因,我们无法抓取LiteOS_M内核的log进行分析,只能直接看OHOS1_1_0LTS中的LiteOS_M内核代码进行分析了。

1. 第一阶段:U-Boot启动
无log。
OHOS1_1_0LTSkernelliteos_mtargets
这个目录下是目前liteos-m官方已经支持的目标平台软硬件环境,我们目前拿到的官方Hi3861开发平台,应该 就是cortex-m7_nucleo_f767zi_gcc 这一个。
注意,Test_Wifiiotkernelliteos_m目录下,并没有targets目录。

tagets目录下的STM32F767ZITx_FLASH.ld 就是bootloader引导程序,见该文件头部“Abstract”的描述。
  1. /* Entry Point */
  2. ENTRY(Reset_Handler)
复制代码

2. 第二阶段:汇编代码引导LiteOS-M内核
OHOS1_1_0LTSkernelliteos_m        agets目录下的startup_stm32f767xx.s 就是汇编代码引导程序。
  1. * @Brief  This is the code that gets called when the processor first
  2. *          starts execution following a reset event. Only the absolutely
  3. *          necessary set is performed, after which the application
  4. *          supplied main() routine is called.
复制代码

代码入口在:
Reset_Handler:  

跑到到下面:
  1. /* Call the clock system initialization function.*/
  2.   bl  SystemInit
  3. /* Call static constructors */
  4.   bl __libc_init_array
  5. /* Call the application's entry point.*/
  6.   bl  main
  7.   bx  lr   
复制代码

SystemInit代码在:
  1. OHOS1_1_0LTSkernelliteos_m        argetscortex-m7_nucleo_f767zi_gccCoreSrcsystem_stm32f7xx.c
  2.   * @brief  Setup the microcontroller system
  3.   *         Initialize the Embedded Flash Interface, the PLL and update the
  4.   *         SystemFrequency variable.
复制代码

main则是进入内核LiteOS-M启动的C语言阶段的入口。

3. 第三阶段:内核LiteOS-M的C语言启动阶段
上面汇编阶段调用的main函数,位于:
OHOS1_1_0LTSkernelliteos_m        argetscortex-m7_nucleo_f767zi_gccCoreSrcmain.c

Line95的调用的RunTaskSample(); 见同目录下的 task_sample.c
  1. VOID RunTaskSample(VOID)
  2. {
  3.     UINT32 ret;
  4.     ret = LOS_KernelInit();
  5.     if (ret == LOS_OK) {
  6.         TaskSample();
  7.         LOS_Start();
  8.     }
  9. }
复制代码

1. LOS_KernelInit()
位于OHOS1_1_0LTSkernelliteos_mkernelsrclos_init.c
System kernel initialization function, configure all system modules

开始初始化liteos_m系统内核

2. TaskSample()
同在task_sample.c文件内定义,上面初始化系统内核成功后,创建两个sample task。

3. LOS_Start()
位于OHOS1_1_0LTSkernelliteos_mkernelsrclos_init.c
开始任务调度

4. 第四阶段:鸿蒙系统框架层的启动
以上三个阶段,都是在完整的鸿蒙系统代码OHOS1_1_0LTS工程下查看和分析的,从这里开始就需要切换回到Test_Wifiiot工程上去阅读、修改、编译代码,烧录bin,抓log分析了。

LiteOS-M的内核源代码我没怎么看,具体怎么切换到鸿蒙系统框架层去运行,我还不大清楚。

从Hi3861开发板上抓取的log,第一行就是“ready to OS start”,表明LiteOS-M内核已经启动OK了。

接下来就进入到鸿蒙系统的框架层的启动,这一部分与 Part 1 的第4节Hi3516平台上的鸿蒙系统的框架层的启动有一些差别。

这个入口,并不是"/bin/init",而是app_main.c文件的app_main()函数。

Test_Wifiiotvendorhisihi3861hi3861appwifiiot_appsrcapp_main.c
  1. hi_void app_main(hi_void)
  2. {
  3.     printf("#########################################################
  4. ");
  5.     printf("[app_main] LiteOS-M Kernel(ROM) inited.
  6. ");

  7.     printf("[app_main] app_main:: Begin:
  8. ");
  9.    .
  10.    .  //中间做了一大堆硬件初始化,调用的接口都被封装了的。
  11.    .
  12.     printf("[app_main] ::HOS_SystemInit():
  13. ");
  14.     HOS_SystemInit();

  15.     printf("[app_main] app_main End!
  16. ");
  17.     printf("#########################################################
  18. ");
  19. }
复制代码

接下来我将贴上一段伪代码,加上我写的log,通过在Hi3861开发平台上抓取log来做对应的分析以便理解其启动流程。

log的格式一般来说是“[c文件名] 函数名 打印信息”,如:
“[cmsis_liteos2] osThreadNew: TaskName[HmosTask] TaskID[9]”
表示这句log在 cmsis_liteos2.c 文件内的osThreadNew()函数里打印“TaskName[HmosTask] TaskID[9]”信息。
code@ 标记函数所在代码文件路径

伪代码段开始:
  1. code@vendorhisihi3861hi3861appwifiiot_appsrcapp_main.c
  2. app_main
  3. {
  4.     printf("#########################################################
  5. ");
  6.     printf("[app_main] LiteOS-M Kernel(ROM) inited.
  7. ");
  8.     printf("[app_main] app_main:: Begin:
  9. ");
  10.     .
  11.    .  //中间做了一大堆硬件初始化,调用的接口都被封装了的。
  12.    .
  13.     printf("[app_main] ::HOS_SystemInit():
  14. ");
  15.     code@asestartupservicesootstrap_litesourcesystem_init.c
  16.     HOS_SystemInit();
  17.    {  
  18.   #bootstrap_lite: bootstrap启动引导组件,提供了各服务和功能的【启动入口标识】。
  19.   #在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。

  20.   printf("[system_init] HOS_SystemInit begin: %%%%%%%%%%%%%%%%%%%%%%%
  21. ");
  22.   printf("[system_init] MODULE_INIT(bsp)=============================
  23. ");
  24.   MODULE_INIT(bsp);
  25.   printf("[system_init] MODULE_INIT(device)==========================
  26. ");
  27.   MODULE_INIT(device);
  28.   printf("[system_init] MODULE_INIT(core)============================
  29. ");
  30.   MODULE_INIT(core);
  31.   {
  32.    code@asehiviewdfxframeworkshilog_liteminihiview_log.c
  33.    #第二个参数是priority, range is [0, 4],Default priority is 2
  34.    printf("[hiview_log] HiLogInit. CORE_INIT_PRI(HiLogInit, 0)
  35. ");  //priority is 0
  36.    #log系统
  37.    
  38.    code@vendorhisihi3861hi3861_adapterhalscommunicationwifi_litewifiservicesourcewifi_device_util.c
  39.    printf("[wifi_device_util] InitWifiGlobalLock. CORE_INIT(InitWifiGlobalLock)
  40. ");  
  41.    #Wifi模块
  42.   }
  43.   
  44.   printf("[system_init] SYS_INIT(service)============================
  45. ");
  46.   SYS_INIT(service);
  47.   {
  48.    -----------------------------------------------------
  49.    code@asestartupservicesootstrap_litesourceootstrap_service.c
  50.    printf("[bootstrap_service] SYS_SERVICE_INIT(Init).
  51. ");
  52.    #bootstrap_lite: bootstrap启动引导组件,提供了各服务和功能的【启动入口标识】。
  53.    #在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。   
  54.    #这一步会SAMGR_GetInstance,导致
  55.    {
  56.     #系统服务框架 system ability (SA) framework
  57.     code@foundationdistributedscheduleservicessamgr_litesamgrsourcesamgr_lite.c
  58.     printf("[samgr_lite] Init.
  59. ");
  60.     static void Init(void)
  61.     #这个没有SYS_SERVICE_INIT括住,但是 g_samgrImpl 是一个全局对象,
  62.     #SAMGR_GetInstance()->RegisterService((Service *)&bootstrap); 时会首先 init g_samgrImpl,
  63.     #然后向全局对象 g_samgrImpl 注册服务:name: Bootstrap
  64.    }
  65.    -----------------------------------------------------
  66.    code@foundationdistributedscheduleservicessamgr_litecommunicationroadcastsourceroadcast_service.c
  67.    #M核和A核进程内事件的广播服务
  68.    printf("[broadcast_service] SYS_SERVICE_INIT(Init).
  69. ");
  70.    {
  71.     #同上,会在 SAMGR_GetInstance()->RegisterService((Service *)&g_broadcastService);
  72.     #向全局对象 g_samgrImpl 注册服务:name: Broadcast
  73.    }
  74.    -----------------------------------------------------
  75.    code@asehiviewdfxserviceshiview_litehiview_service.c
  76.    #提供DFX子系统整体的初始化功能,控制各组件按需启动
  77.    printf("[hiview_service] SYS_SERVICE_INIT(Init).
  78. ");
  79.    {
  80.     #同上,会在 SAMGR_GetInstance()->RegisterService((Service *)&g_hiviewService);
  81.     #向全局对象 g_samgrImpl 注册服务:name: hiview
  82.    }
  83.    -----------------------------------------------------
  84.    code@foundationdistributedscheduleservicessamgr_litesamgr_serversourcesamgr_server.c
  85.    #进程间服务调用的IPC地址管理和访问控制
  86.    printf("[samgr_service] InitializeRegistry. SYS_SERVICE_INIT(InitializeRegistry)
  87. ");
  88.    SYS_SERVICE_INIT(InitializeRegistry);
  89.    #总共搜到4个“SYS_SERVICE_INIT”,但最后一个samgr_service的log没见打印出来!!!!
  90.    #难道是samgr_service不需要启动,只用 samgr_lite 来管理 g_samgrImpl 就可以了??
  91.    -----------------------------------------------------
  92.   }
  93.   
  94.   printf("[system_init] SYS_INIT(feature)============================
  95. ");
  96.   SYS_INIT(feature);
  97.   {
  98.    code@foundationdistributedscheduleservicessamgr_litecommunicationroadcastsourcepub_sub_feature.c
  99.    printf("[pub_sub_feature] Init. SYS_FEATURE_INIT(Init)
  100. ");
  101.   }
  102.   
  103.   printf("[system_init] MODULE_INIT(run)=============================
  104. ");
  105.   //.zinitcall.run2.init 代码段里面的函数指针指向 SYS_RUN(APP)指向的APP, Default priority is 2,所以是 run2
  106.   MODULE_INIT(run);
  107.   {
  108.    code@applicationssamplewifi-iotapphelloworldhelloworld.c
  109.    printf("[helloworld] SYS_RUN(helloworld).
  110. ");   //Default priority is 2
  111.    
  112.    code@applicationssamplewifi-iotappiothardwareled.c
  113.    printf("[led] SYS_RUN(LedEntry)
  114. ");    //Default priority is 2
  115.   }
  116.   
  117.   #系统服务框架子系统 [system ability (SA) framework]
  118.   #系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及
  119.   #多服务共进程、进程间服务调用等开发能力。其中:
  120.   #M核:包含服务开发、服务的子功能开发、对外接口的开发以及多服务共进程的开发框架。
  121.   #A核:在M核能力基础之上,包含了进程间服务调用、进程间服务调用权限控制、进程间服务接口的开发等能力。   
  122.   #M核:系统依赖上bootstrap服务,在系统启动函数中调用OHOS_SystemInit()函数。
  123.   #A核:系统依赖samgr库,在main函数中调用SAMGR_Bootstrap()函数。
复制代码
  1.   code@foundationdistributedscheduleservicessamgr_lite
  2.   printf("[system_init] SAMGR_Bootstrap()=============================
  3. ");
  4.   SAMGR_Bootstrap();  
  5.   {
  6.    printf("[samgr_lite] SAMGR_Bootstrap. Begin:         size=%d
  7. ",size);
  8.    printf("        InitializeAllServices: size=%d
  9. ",size);
  10.     Init service:Bootstrap TaskPool:0xfa408
  11.     Init service:Broadcast TaskPool:0xfaa78
  12.     Init service:hiview    TaskPool:0xfac38

  13.    static void InitializeAllServices(Vector *services)

  14.    printf("[samgr_lite] SAMGR_Bootstrap. End.
  15. ");
  16.   }  
  17.   printf("[system_init] HOS_SystemInit end. %%%%%%%%%%%%%%%%%%%%%%%%%%
  18. ");
  19. }
  20. printf("[app_main] app_main End!
  21. ");
  22.     printf("#########################################################
  23. ");
  24. }
复制代码
伪代码段结束。

编译、烧录、上电、抓log,log基本上就能说明启动流程了,这里就不再进一步分析了,各位跑一遍代码就清楚了。

log段开始:
  1. ready to OS start
  2. #########################################################
  3. [app_main] LiteOS-M Kernel(ROM) inited.
  4. [app_main] app_main:: Begin:
  5. [app_main] ::sdk ver:Hi3861V100R001C00SPC025 2020-09-03 18:10:00
  6. peripheral_init.
  7. hi_flash_init.   
  8. hi_uart_init.   
  9. app_io_init: uart0&uart1, other io NEED to open MACRO
  10.         io:uart0
  11.         io:uart1
  12.         io:PWM
  13. hi_pwm_init.
  14. [app_main] ::hi_fs_init.
  15. formatting spiffs...   
  16. FileSystem mount ok.   
  17. [app_main] ::hi_at_init.
  18. [app_main] ::tcpip init.
  19. [app_main] ::wifi init success!

  20. [app_main] ::HOS_SystemInit():
  21. [system_init] HOS_SystemInit begin: %%%%%%%%%%%
  22. [system_init] MODULE_INIT(bsp)=============================
  23. [system_init] MODULE_INIT(device)==========================

  24. [system_init] MODULE_INIT(core)============================
  25. [hiview_log] HiLogInit. CORE_INIT_PRI(HiLogInit, 0)
  26. [wifi_device_util] InitWifiGlobalLock. CORE_INIT(InitWifiGlobalLock)

  27. [system_init] SYS_INIT(service)============================
  28. [bootstrap_service] SYS_SERVICE_INIT(Init).
  29. [samgr_lite] Init.
  30. [samgr_lite] RegisterService(name: Bootstrap)

  31. [broadcast_service] SYS_SERVICE_INIT(Init).
  32. [samgr_lite] RegisterService(name: Broadcast)

  33. [hiview_service] SYS_SERVICE_INIT(Init).
  34. [samgr_lite] RegisterService(name: hiview)
  35. [hiview_service] Init.InitHiviewComponent.

  36. [system_init] SYS_INIT(feature)============================
  37. [pub_sub_feature] Init. SYS_FEATURE_INIT(Init)

  38. [system_init] MODULE_INIT(run)=============================
  39. [helloworld] SYS_RUN(helloworld).
  40. [helloworld] Hello World. creating a HmosTask
  41. [cmsis_liteos2] osThreadNew: TaskName[HmosTask] TaskID[9]

  42. [led] SYS_RUN(LedEntry)
  43. [led] LedEntry. creating a LedTask
  44. [cmsis_liteos2] osThreadNew: TaskName[LedTask] TaskID[8]

  45. [system_init] SAMGR_Bootstrap()=============================
  46. [samgr_lite] SAMGR_Bootstrap. Begin:    size=3
  47.         InitializeAllServices: size=3
  48.         Add service:Bootstrap    to TaskPool:0xfa448...
  49.         Add service:Broadcast    to TaskPool:0xfaab8...
  50.         Add service:hiview       to TaskPool:0xfac78...

  51. [task_manager] SAMGR_StartTaskPool:
  52. [cmsis_liteos2] osThreadNew: TaskName[Bootstrap] TaskID[10]
  53.         CreateTask[Bootstrap, 2048, 25]-OK!
  54. [task_manager] SAMGR_StartTaskPool:
  55. [cmsis_liteos2] osThreadNew: TaskName[Broadcast] TaskID[11]
  56.         CreateTask[Broadcast, 2048, 32]-OK!
  57. [task_manager] SAMGR_StartTaskPool:
  58. [cmsis_liteos2] osThreadNew: TaskName[hiview] TaskID[12]
  59.         CreateTask[hiview, 2048, 24]-OK!

  60. [samgr_lite] SAMGR_Bootstrap. End.
  61. [system_init] HOS_SystemInit end. %%%%%%%%%%%%%
  62. [app_main] app_main End!
  63. #########################################################
  64. [samgr_lite] HandleInitRequest. to Init service:id[1][Broadcast]
  65. [broadcast_service] Initialize.
  66. [samgr_lite] HandleInitRequest. to Init service:id[0][Bootstrap]
  67. [bootstrap_service] Initialize.
  68. [samgr_lite] HandleInitRequest. to Init service:id[2][hiview]
  69. [hiview_service] Initialize.

  70. [samgr_lite] InitCompleted: manager->status[1]
  71. [samgr_lite] InitCompleted[1->2]: SendBootRequest[BOOT_SYS_COMPLETED]: Initialized all core system services!
  72. [samgr_lite] SAMGR_Bootstrap. Begin:    size=3
  73. [samgr_lite] InitCompleted: manager->status[3]
  74. [samgr_lite] InitCompleted[3->4]: SendBootRequest[BOOT_APP_COMPLETED]: Initialized all system and application services!

  75. [samgr_lite] SAMGR_Bootstrap. End.
  76. [samgr_lite] SAMGR_Bootstrap. Begin:    size=3
  77. [samgr_lite] InitCompleted: manager->status[5]
  78. [samgr_lite] SAMGR_Bootstrap. End.

  79. 00 00:00:00 0 196 D 0/HIVIEW: hilog init success.
  80. 00 00:00:00 0 196 D 0/HIVIEW: log limit init success.
  81. 00 00:00:00 0 196 I 1/SAMGR: Bootstrap core services(count:3).
  82. 00 00:00:00 0 196 I 1/SAMGR: Init service:0x4af12c TaskPool:0xfa448
  83. 00 00:00:00 0 196 I 1/SAMGR: Init service:0x4af468 TaskPool:0xfaab8
  84. 00 00:00:00 0 196 I 1/SAMGR: Init service:0x4af6c4 TaskPool:0xfac78
  85. 00 00:00:00 0  72 I 1/SAMGR: Init service [0x4af468] <time: 140ms> success!
  86. 00 00:00:00 0 228 I 1/SAMGR: Init service [0x4af12c] <time: 140ms> success!
  87. 00 00:00:00 0 172 D 0/HIVIEW: hiview Initialize success.
  88. 00 00:00:00 0 172 I 1/SAMGR: Init service [0x4af6c4] <time: 140ms> success!
  89. 00 00:00:00 0 172 I 1/SAMGR: Initialized all core system services!
  90. 00 00:00:00 0 228 I 1/SAMGR: Bootstrap system and application services(count:0).
  91. 00 00:00:00 0 228 I 1/SAMGR: Initialized all system and application services!
  92. 00 00:00:00 0 228 I 1/SAMGR: Bootstrap dynamic registered services(count:0).

  93. [helloworld] Hello HarmonyOS! awake[3]!
  94. [helloworld] Hello HarmonyOS! awake[2]!
  95. [helloworld] Hello HarmonyOS! awake[1]!
  96. [helloworld] HelloTask terminated!
复制代码
log段结束。

5. 鸿蒙应用(APP)的启动
我在Test_Wifiiotapplicationssamplewifi-iotapp目录下放置了两个应用,BUILD.gn文件如下:
  1. lite_component("app") {
  2.     features = [
  3.         "startup",
  4.         "helloworld:helloworld",
  5.         "iothardware:led",
  6.     ]
  7. }
复制代码
两个应用的入口函数分别是:
  1. SYS_RUN(helloworld);
  2. SYS_RUN(LedEntry);
复制代码
这两个应用都在上面伪代码段中的MODULE_INIT(run);的时候被调用启动了。



伪代码+log.rar
(3.34 KB, 下载次数: 1)

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友