共计 3039 个字符,预计需要花费 8 分钟才能阅读完成。
引言
OpenHarmony 作为一款万物互联的操作系统,笼罩了从嵌入式实时物联网操作系统到挪动操作系统的全笼罩,其中内核包含 LiteOS-M,LiteOS- A 和 Linux。LiteOS- M 内核是面向 IoT 畛域构建的轻量级物联网操作系统内核,次要面向没有 MMU 的处理器,架构如图 1 - 1 所示。
图 1 -1 LiteOS- M 架构图
Hi3861 是一款高度集成的 2.4GHz SoC WiFi 芯片,采纳高性能 32bit 微处理器,最大工作频率 160MHz,内嵌 SRAM 352KB、ROM 288KB、Flash 2MB。目前市面上的采纳 LiteOS- M 的 OpenHarmony 开发板厂商有深开鸿、润和软件、小熊派,因为海思的 SDK 是以库文件的模式提供的,所以不同的 Hi3861 芯片开发板启动流程是一样的。
Hi3861 Boot 介绍
Boot 是操作系统启动之前的软件,通用叫法是 bootloader,Hi3861 的 boot 分为 4 局部:RomBoot、FlashBoot、LoaderBoot、CommonBoot,如图 2 - 1 所示。
图 2 -1 Hi3861 Boot 启动流程
● RomBoot 性能包含:加载 LoaderBoot 到 RAM,进一步利用 LoaderBoot 下载镜像到 Flash、烧写 EFUSE,校验并疏导 FlashBoot。FlashBoot 分为 AB 面,A 面校验胜利间接启动,校验失败会去校验 B 面,B 面校验胜利会修复 A 面再疏导启动,否则复位重启。
● FlashBoot 性能包含:降级固件,校验并疏导固件。
● LoaderBoot 性能包含:下载镜像到 Flash,烧写 EFUSE(例如:平安启动 /Flash 加密相干密钥等)。
● CommonBoot 为 Flashboot 与 LoaderBoot 共用的功能模块。
相干文件介绍
Hi3861 的 LiteOS- M 代码是 SDK 中以库文件的模式提供的,尽管咱们无奈看到源代码,但这不代表咱们剖析不了启动流程,咱们能够从剖析 map 文件和 asm 这两个文件动手。这两个文件都是编译链接工具生成的,其中 asm 文件是汇编程序源文件,能够查看函数之间的调用关系,map 文件里包含全局符号、函数地址及占用的空间和地位。map 和 asm 文件次要作用是当开发板解体时用于剖析其解体的起因,咱们剖析函数跳转关系时并不需要晓得太多汇编,只须要晓得根本的跳转语句和赋值语句即可,这两个文件位于 out 目录下和操作系统固件平级的目录,如图 3 -1。
图 3 -1 Hi3861 asm 和 map 文件位置图
一个编译实现的固件通常有以下几局部:
1) RO 段包含只读代码段 (code 段 /.text 段) 和常量段 (RO Data 段 /.constdata 段)。
2) RW 段(.data 段) 指已被初始化成非 0 值的变量段。
3) ZI 段 (.bss 段) 指未被初始化或初始化为 0 的变量段。
咱们源代码的函数和字符串常量都位于 text 段。
LiteOS- M 启动流程介绍
1) 嵌入式处理器和操作系统都具备相似的构造启动流程也大体类似,从芯片上电开始 Boot 把控制权交给操作系统,Hi3861 从 Boot 跳转到操作系统代码如下:
这部分是将该地址当函数作为跳转,因为 FlashBoot 和 kernel,是两套代码程序,他们之间没有依赖援用关系,然而他们在一个地址空间,所以间接地址跳转,这也是从 Boot 到 kernel 通用的跳转形式。
2) 芯片启动是从中断向量表的复位中断处理程序开始,接着把数据从 Flash 复制到 RAM、清空 bss 数据段、初始化时钟、跳转到 main 函数。咱们通过查看 asm 文件的 main 函数,能够看出其中调用的函数如图 4 - 1 所示,从图 4 -1 咱们可得悉调用的函数包含设置串口、校验版本号、配置板子、Kernel 初始化、利用初始化和操作系统的调度运行,其中 main 函数位于 liblitekernel_flash.a(main.o)文件中。
图 4 -1 main 函数调用关系
LOS_KernelInit 是负责初始化内核数据结构的,如图 4 - 2 所示,次要函数有 OsMemSystemInit(内存初始化)、OsHwiInit(中断初始化)、OsTaskInit(工作初始化),这些过程次要目标是把内核相干的变量初始化,筹备好全局信息,不便 API 函数去调用,API 函数调用必须在这些初始化实现后才能够。
3) 从 AppInit 开始脱离了 sdk,能够看到源代码了,AppInit 函数位于 libwifiiot_app.a(app_main.o)中,局部截图如图 4 -3,源代码为 app_main.c, 其中调用的函数包含获取 sdk 版本号,外设初始化,ipc 初始化,flash 分区,WiFi 初始化,tcp/ip 初始化,而后跳转到了 OpenHarmony 特有的函数 OHOS_Main。
OHOS_Main 位于 libwifiiot_app.a(ohos_main.o)中,源代码为 ohos_main.c, 次要实现 OpenHarmony 零碎相干和用户利用相干的调用,里边次要函数是 OHOS_SystemInit,如图 4 -4,在其中调用了用户本人写的利用工作相干代码,如图 4 -5,从而实现了在 LOS_start 之前把工作列表填好,这样能力保障用户工作或定时等性能参加了系统调度。
图 4 -2 LOS_KernelInit 函数调用关系
图 4 -3 app_main 函数调用关系
图 4 -4 OHOS_Main 函数调用关系
图 4 -5 OHOS_SystemInit 函数调用关系
用户利用的启动原理
1) 在图 4 - 5 中呈现的函数 MODULE_INIT(run), 就是调用最终调用用户程序的代码。
这是个宏定义,开展的调用关系:\base\startup\bootstrap_lite\services\source\core_main.h 定义,从 MODULE_CALL、MODULE_BEGIN、MODULE_END,最终调用的地址是__zinitcall_##name##_start,MODULE_INIT(run)调用的函数地址是__zinitcall_run_start。
通过查看链接文件得出__zinitcall_run_start 蕴含.zinitcall.run0.init),如图 5 - 1 所示。
图 5 -1 __zinitcall_run_start 链接关系
查看 map 文件发现咱们本人的应用程序文件就在.zinitcall.run2.init 中,如图 5 - 2 所示。
图 5 -2 led_exapmle 文件在 map 中的地位
2) 从运行角度看启动中调用到了应用程序 led_exapmle,所谓地位为.zinitcall.run2.init,但咱们在应用程序中的关联函数是 SYS_RUN(LedExampleEntry),SYS_RUN 的开展关系如图 5 - 3 所示,最终即是 zinitcall.run2.init,和程序运行时候的调用匹配在一起了。应用程序的调用关系就是编译链接阶段生成指定的段,初始化时调用指定段,这样实现了 LiteOS- M 的操作系统代码与利用程序代码的解耦。
图 5 -3 SYS_RUN 的开展关系
总结
本文向大家讲述了在没有局部源代码的状况下,如何通过对 map 文件和 asm 文件的剖析从而得出 Hi3861 芯片开发板 LiteOS- M 的启动流程。总体过程就是最小硬件零碎的配置实现后,LOS_KernelInit 负责初始化零碎到一个适合的状态,AppInit 调用 OpenHarmony 和利用相干代码,最初 LOS_Start 负责把操作系统运行起来。