鸿蒙系统的启动流程v3.0--Part 2: 基于Hi3861平台+LiteOS_M内核 原创 精华

发布于 2021-4-16 20:39
浏览
11收藏

鸿蒙系统的启动流程

liangkz 2021.04.16 Ver3.0

 

目录

Part 1: 基于Hi3516平台+LiteOS_A内核 

1. 第一阶段:U-Boot启动 

2. 第二阶段:汇编代码引导LiteOS-A内核 

3. 第三阶段:内核LiteOS-A的C语言启动阶段 

4. 第四阶段:鸿蒙系统框架层的启动 

5. 第四阶段:鸿蒙系统框架层的启动细节 

6. 鸿蒙应用(APP)的启动 

附录A. #task命令查看进程/线程信息(简表) 

Part 2: 基于Hi3861平台+LiteOS_M内核 

1. 第一阶段:U-Boot启动 

2. 第二阶段:汇编代码引导LiteOS-M内核 

3. 第三阶段:内核LiteOS-M的C语言启动阶段 

4. 第四阶段:鸿蒙系统框架层的启动 

5. 鸿蒙应用(APP)的启动 

声明:

升级文档到v2.0后可以声明是原创的了。这是上了朱有鹏老师的免费课《想读懂鸿蒙2.0源码,也许你需要先懂这些》(link:https://edu.51cto.com/course/27341.html?hm)之后,做的一些总结。

课程时间一个半小时,内容也很多,学习过程中我发现朱老师的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://harmonyos.51cto.com/posts/3893)

2021.04.15 v2.0 重新整理了第四阶段:鸿蒙系统框架层的启动:增加了新的理解内容,修改错误。增加了框架层的启动细节部分概述。(Link: https://harmonyos.51cto.com/posts/3893)
2021.04.16 v3.0 v1.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”项目,开始下载并安装组件到项目里。如下图:鸿蒙系统的启动流程v3.0--Part 2: 基于Hi3861平台+LiteOS_M内核-开源基础软件社区

    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_Wifiiot\vendor\hisi\hi3861\hi3861\build\build_tmp\logs\build_kernel.log

进行分析确认。

 

实际上我是这样确认的:

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

 

4. Test_Wifiiot\kernel\liteos_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_0LTS\kernel\liteos_m\targets 

这个目录下是目前liteos-m官方已经支持的目标平台软硬件环境,我们目前拿到的官方Hi3861开发平台,应该 就是cortex-m7_nucleo_f767zi_gcc 这一个。

注意,Test_Wifiiot\kernel\liteos_m目录下,并没有targets目录。

 

tagets目录下的STM32F767ZITx_FLASH.ld 就是bootloader引导程序,见该文件头部“Abstract”的描述。

/* Entry Point */

ENTRY(Reset_Handler)

 

2. 第二阶段:汇编代码引导LiteOS-M内核
OHOS1_1_0LTS\kernel\liteos_m\tagets目录下的startup_stm32f767xx.s 就是汇编代码引导程序。

 * @brief  This is the code that gets called when the processor first

 *          starts execution following a reset event. Only the absolutely

 *          necessary set is performed, after which the application

 *          supplied main() routine is called. 

 

代码入口在:

Reset_Handler:  

 

跑到到下面:

/* Call the clock system initialization function.*/

  bl  SystemInit

/* Call static constructors */

  bl __libc_init_array

/* Call the application's entry point.*/

  bl  main

  bx  lr    

 

 SystemInit代码在:

OHOS1_1_0LTS\kernel\liteos_m\targets\cortex-m7_nucleo_f767zi_gcc\Core\Src\system_stm32f7xx.c

  * @brief  Setup the microcontroller system

  *         Initialize the Embedded Flash Interface, the PLL and update the 

  *         SystemFrequency variable.

 

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


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

OHOS1_1_0LTS\kernel\liteos_m\targets\cortex-m7_nucleo_f767zi_gcc\Core\Src\main.c鸿蒙系统的启动流程v3.0--Part 2: 基于Hi3861平台+LiteOS_M内核-开源基础软件社区

Line95的调用的RunTaskSample(); 见同目录下的 task_sample.c

VOID RunTaskSample(VOID)
{
    UINT32 ret;
    ret = LOS_KernelInit();
    if (ret == LOS_OK) {
        TaskSample();
        LOS_Start();
    }
}

1. LOS_KernelInit()

位于OHOS1_1_0LTS\kernel\liteos_m\kernel\src\los_init.c

System kernel initialization function, configure all system modules

开始初始化liteos_m系统内核

2. TaskSample()

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

3. LOS_Start()

位于OHOS1_1_0LTS\kernel\liteos_m\kernel\src\los_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_Wifiiot\vendor\hisi\hi3861\hi3861\app\wifiiot_app\src\app_main.c

hi_void app_main(hi_void)
{
    printf("#########################################################\n");
    printf("[app_main] LiteOS-M Kernel(ROM) inited.\n");

    printf("[app_main] app_main:: Begin:\n");
   .
   .  //中间做了一大堆硬件初始化,调用的接口都被封装了的。
   .
    printf("[app_main] ::HOS_SystemInit():\r\n");
    HOS_SystemInit();

    printf("[app_main] app_main End!\r\n");
    printf("#########################################################\r\n");
}

 

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

log的格式一般来说是“[c文件名] 函数名 打印信息”,如:

“[cmsis_liteos2] osThreadNew: TaskName[HmosTask] TaskID[9]

表示这句log在 cmsis_liteos2.c 文件内的osThreadNew()函数里打印“TaskName[HmosTask] TaskID[9]”信息。

code@ 标记函数所在代码文件路径

 

伪代码段开始:

code@\vendor\hisi\hi3861\hi3861\app\wifiiot_app\src\app_main.c

app_main

{

    printf("#########################################################\n");

    printf("[app_main] LiteOS-M Kernel(ROM) inited.\n");

    printf("[app_main] app_main:: Begin:\n");

    .

   .  //中间做了一大堆硬件初始化,调用的接口都被封装了的。

   .

    printf("[app_main] ::HOS_SystemInit():\r\n");

    code@\base\startup\services\bootstrap_lite\source\system_init.c

    HOS_SystemInit();

   {  

  #bootstrap_lite: bootstrap启动引导组件,提供了各服务和功能的【启动入口标识】。

  #在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。

 

  printf("[system_init] HOS_SystemInit begin: %%%%%%%%%%%%%%%%%%%%%%%\n");

  printf("[system_init] MODULE_INIT(bsp)=============================\n");

  MODULE_INIT(bsp);

  printf("[system_init] MODULE_INIT(device)==========================\n");

  MODULE_INIT(device);

  printf("[system_init] MODULE_INIT(core)============================\n");

  MODULE_INIT(core);

  {

   code@\base\hiviewdfx\frameworks\hilog_lite\mini\hiview_log.c

   #第二个参数是priority, range is [0, 4],Default priority is 2

   printf("[hiview_log] HiLogInit. CORE_INIT_PRI(HiLogInit, 0)\n");  //priority is 0

   #log系统

   

   code@\vendor\hisi\hi3861\hi3861_adapter\hals\communication\wifi_lite\wifiservice\source\wifi_device_util.c

   printf("[wifi_device_util] InitWifiGlobalLock. CORE_INIT(InitWifiGlobalLock)\n");  

   #Wifi模块

  }

  

  printf("[system_init] SYS_INIT(service)============================\n");

  SYS_INIT(service);

  {

   -----------------------------------------------------

   code@\base\startup\services\bootstrap_lite\source\bootstrap_service.c

   printf("[bootstrap_service] SYS_SERVICE_INIT(Init).\n");

   #bootstrap_lite: bootstrap启动引导组件,提供了各服务和功能的【启动入口标识】。

   #在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。   

   #这一步会SAMGR_GetInstance,导致

   {

    #系统服务框架 system ability (SA) framework

    code@\foundation\distributedschedule\services\samgr_lite\samgr\source\samgr_lite.c

    printf("[samgr_lite] Init.\n");

    static void Init(void)

    #这个没有SYS_SERVICE_INIT括住,但是 g_samgrImpl 是一个全局对象,

    #SAMGR_GetInstance()->RegisterService((Service *)&bootstrap); 时会首先 init g_samgrImpl,

    #然后向全局对象 g_samgrImpl 注册服务:name: Bootstrap

   }

   -----------------------------------------------------

   code@\foundation\distributedschedule\services\samgr_lite\communication\broadcast\source\broadcast_service.c

   #M核和A核进程内事件的广播服务

   printf("[broadcast_service] SYS_SERVICE_INIT(Init).\n");

   {

    #同上,会在 SAMGR_GetInstance()->RegisterService((Service *)&g_broadcastService); 

    #向全局对象 g_samgrImpl 注册服务:name: Broadcast

   }

   -----------------------------------------------------

   code@\base\hiviewdfx\services\hiview_lite\hiview_service.c

   #提供DFX子系统整体的初始化功能,控制各组件按需启动

   printf("[hiview_service] SYS_SERVICE_INIT(Init).\n");

   {

    #同上,会在 SAMGR_GetInstance()->RegisterService((Service *)&g_hiviewService); 

    #向全局对象 g_samgrImpl 注册服务:name: hiview

   }

   -----------------------------------------------------

   code@\foundation\distributedschedule\services\samgr_lite\samgr_server\source\samgr_server.c

   #进程间服务调用的IPC地址管理和访问控制

   printf("[samgr_service] InitializeRegistry. SYS_SERVICE_INIT(InitializeRegistry)\n");

   SYS_SERVICE_INIT(InitializeRegistry);

   #总共搜到4个“SYS_SERVICE_INIT”,但最后一个samgr_service的log没见打印出来!!!!

   #难道是samgr_service不需要启动,只用 samgr_lite 来管理 g_samgrImpl 就可以了??

   -----------------------------------------------------

  }

  

  printf("[system_init] SYS_INIT(feature)============================\n");

  SYS_INIT(feature);

  {

   code@foundation\distributedschedule\services\samgr_lite\communication\broadcast\source\pub_sub_feature.c

   printf("[pub_sub_feature] Init. SYS_FEATURE_INIT(Init)\n");

  }

  

  printf("[system_init] MODULE_INIT(run)=============================\n");

  //.zinitcall.run2.init 代码段里面的函数指针指向 SYS_RUN(APP)指向的APP, Default priority is 2,所以是 run2

  MODULE_INIT(run);

  {

   code@\applications\sample\wifi-iot\app\helloworld\helloworld.c

   printf("[helloworld] SYS_RUN(helloworld).\n");   //Default priority is 2

   

   code@\applications\sample\wifi-iot\app\iothardware\led.c

   printf("[led] SYS_RUN(LedEntry)\n");    //Default priority is 2

  }

  

  #系统服务框架子系统 [system ability (SA) framework]

  #系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及

  #多服务共进程、进程间服务调用等开发能力。其中:

  #M核:包含服务开发、服务的子功能开发、对外接口的开发以及多服务共进程的开发框架。

  #A核:在M核能力基础之上,包含了进程间服务调用、进程间服务调用权限控制、进程间服务接口的开发等能力。  

  #M核:系统依赖上bootstrap服务,在系统启动函数中调用OHOS_SystemInit()函数。

  #A核:系统依赖samgr库,在main函数中调用SAMGR_Bootstrap()函数。

  code@foundation\distributedschedule\services\samgr_lite

  printf("[system_init] SAMGR_Bootstrap()=============================\n");

  SAMGR_Bootstrap();  

  {

   printf("[samgr_lite] SAMGR_Bootstrap. Begin: \tsize=%d\n",size);

   printf("\tInitializeAllServices: size=%d\n",size);

    Init service:Bootstrap TaskPool:0xfa408 

    Init service:Broadcast TaskPool:0xfaa78 

    Init service:hiview    TaskPool:0xfac38

    

   static void InitializeAllServices(Vector *services)

   

   printf("[samgr_lite] SAMGR_Bootstrap. End.\n");

  }  

  printf("[system_init] HOS_SystemInit end. %%%%%%%%%%%%%%%%%%%%%%%%%%\n");

 }

 

 printf("[app_main] app_main End!\r\n");

    printf("#########################################################\r\n");

}

伪代码段结束。

 

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

 

log段开始:

ready to OS start

#########################################################

[app_main] LiteOS-M Kernel(ROM) inited.

[app_main] app_main:: Begin:

[app_main] ::sdk ver:Hi3861V100R001C00SPC025 2020-09-03 18:10:00

peripheral_init. 

hi_flash_init.   

hi_uart_init.    

app_io_init: uart0&uart1, other io NEED to open MACRO

        io:uart0

        io:uart1

        io:PWM

hi_pwm_init.

[app_main] ::hi_fs_init.

formatting spiffs...    

FileSystem mount ok.    

[app_main] ::hi_at_init.

[app_main] ::tcpip init.

[app_main] ::wifi init success!

 

[app_main] ::HOS_SystemInit():

[system_init] HOS_SystemInit begin: %%%%%%%%%%%

[system_init] MODULE_INIT(bsp)=============================

[system_init] MODULE_INIT(device)==========================

 

[system_init] MODULE_INIT(core)============================

[hiview_log] HiLogInit. CORE_INIT_PRI(HiLogInit, 0)

[wifi_device_util] InitWifiGlobalLock. CORE_INIT(InitWifiGlobalLock)

 

[system_init] SYS_INIT(service)============================

[bootstrap_service] SYS_SERVICE_INIT(Init).

[samgr_lite] Init.

[samgr_lite] RegisterService(name: Bootstrap)

 

[broadcast_service] SYS_SERVICE_INIT(Init).

[samgr_lite] RegisterService(name: Broadcast)

 

[hiview_service] SYS_SERVICE_INIT(Init).

[samgr_lite] RegisterService(name: hiview)

[hiview_service] Init.InitHiviewComponent.

 

[system_init] SYS_INIT(feature)============================

[pub_sub_feature] Init. SYS_FEATURE_INIT(Init)

 

[system_init] MODULE_INIT(run)=============================

[helloworld] SYS_RUN(helloworld).

[helloworld] Hello World. creating a HmosTask

[cmsis_liteos2] osThreadNew: TaskName[HmosTask] TaskID[9]

 

[led] SYS_RUN(LedEntry)

[led] LedEntry. creating a LedTask

[cmsis_liteos2] osThreadNew: TaskName[LedTask] TaskID[8]

 

[system_init] SAMGR_Bootstrap()=============================

[samgr_lite] SAMGR_Bootstrap. Begin:    size=3

        InitializeAllServices: size=3

        Add service:Bootstrap    to TaskPool:0xfa448...

        Add service:Broadcast    to TaskPool:0xfaab8...

        Add service:hiview       to TaskPool:0xfac78...

 

[task_manager] SAMGR_StartTaskPool:

[cmsis_liteos2] osThreadNew: TaskName[Bootstrap] TaskID[10]

        CreateTask[Bootstrap, 2048, 25]-OK!

[task_manager] SAMGR_StartTaskPool:

[cmsis_liteos2] osThreadNew: TaskName[Broadcast] TaskID[11]

        CreateTask[Broadcast, 2048, 32]-OK!

[task_manager] SAMGR_StartTaskPool:

[cmsis_liteos2] osThreadNew: TaskName[hiview] TaskID[12]

        CreateTask[hiview, 2048, 24]-OK!

 

[samgr_lite] SAMGR_Bootstrap. End.

[system_init] HOS_SystemInit end. %%%%%%%%%%%%%

[app_main] app_main End!

#########################################################

 

[samgr_lite] HandleInitRequest. to Init service:id[1][Broadcast]

[broadcast_service] Initialize.

[samgr_lite] HandleInitRequest. to Init service:id[0][Bootstrap]

[bootstrap_service] Initialize.

[samgr_lite] HandleInitRequest. to Init service:id[2][hiview]

[hiview_service] Initialize.

 

[samgr_lite] InitCompleted: manager->status[1]

[samgr_lite] InitCompleted[1->2]: SendBootRequest[BOOT_SYS_COMPLETED]: Initialized all core system services!

 

[samgr_lite] SAMGR_Bootstrap. Begin:    size=3

[samgr_lite] InitCompleted: manager->status[3]

[samgr_lite] InitCompleted[3->4]: SendBootRequest[BOOT_APP_COMPLETED]: Initialized all system and application services!

[samgr_lite] SAMGR_Bootstrap. End.

 

[samgr_lite] SAMGR_Bootstrap. Begin:    size=3

[samgr_lite] InitCompleted: manager->status[5]

[samgr_lite] SAMGR_Bootstrap. End.

 

00 00:00:00 0 196 D 0/HIVIEW: hilog init success.

00 00:00:00 0 196 D 0/HIVIEW: log limit init success.

00 00:00:00 0 196 I 1/SAMGR: Bootstrap core services(count:3).

00 00:00:00 0 196 I 1/SAMGR: Init service:0x4af12c TaskPool:0xfa448

00 00:00:00 0 196 I 1/SAMGR: Init service:0x4af468 TaskPool:0xfaab8

00 00:00:00 0 196 I 1/SAMGR: Init service:0x4af6c4 TaskPool:0xfac78

00 00:00:00 0  72 I 1/SAMGR: Init service [0x4af468] <time: 140ms> success!

00 00:00:00 0 228 I 1/SAMGR: Init service [0x4af12c] <time: 140ms> success!

00 00:00:00 0 172 D 0/HIVIEW: hiview Initialize success.

00 00:00:00 0 172 I 1/SAMGR: Init service [0x4af6c4] <time: 140ms> success!

00 00:00:00 0 172 I 1/SAMGR: Initialized all core system services!

00 00:00:00 0 228 I 1/SAMGR: Bootstrap system and application services(count:0).

00 00:00:00 0 228 I 1/SAMGR: Initialized all system and application services!

00 00:00:00 0 228 I 1/SAMGR: Bootstrap dynamic registered services(count:0).

 

[helloworld] Hello HarmonyOS! awake[3]!

[helloworld] Hello HarmonyOS! awake[2]!

[helloworld] Hello HarmonyOS! awake[1]!

[helloworld] HelloTask terminated!

log段结束。

 

5. 鸿蒙应用(APP)的启动
我在Test_Wifiiot\applications\sample\wifi-iot\app目录下放置了两个应用,BUILD.gn文件如下:

lite_component("app") {

    features = [

        "startup",

        "helloworld:helloworld",

        "iothardware:led",

    ]

}

两个应用的入口函数分别是:

SYS_RUN(helloworld);

SYS_RUN(LedEntry);

这两个应用都在上面伪代码段中的MODULE_INIT(run);的时候被调用启动了。

 

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
鸿蒙系统的启动流程v3.0-2021.04.16.pdf 2.87M 228次下载
伪代码+log.rar 3.34K 94次下载
已于2021-4-16 21:12:24修改
9
收藏 11
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐