引言
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),就是调用最终调用用户程序的代码。这是一个宏定义,展开的调用关系 :asestartupootstrap_liteservicessourcecore_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负责把操作系统运转起来。
炬光科技和New Source Technology LLC签署代理协议
中国WJ-700新型无人机首飞成功,综合素质达到了世界先进的水平
统联精密:现有MIM产能在旺季已到高位运行状态
锂金属电池失效的主要原因在于非活性锂
DCDC转换原理PWM占空比调制概述
Hi3861芯片开发板LiteOS-M的启动流程
中国大力发展自研芯片技术 在美对外投资并购受阻加剧
取消了耳机接口的小米6你还会喜欢吗?当然还有黑科技
Virtex7上DDR3的测试例程
接近开关控制电机正反转的方法
3海底电缆故障 Vocus提前为ASC做好准备
技术不成熟,可穿戴设备尚未达到理想标准
特高压输电的特点_特高压输电的优缺点
水利安全监测方案——基于RTU200的解决方案
传说中的《哈利波特Go》开发完毕 你要入坑吗?
转让注销、关闭工厂一系列都LED行业中正频繁上演
芯片有哪些常见的封装基板呢?
2X2 MIMO双路WiFi到底是什么,使得现在的手机纷纷以搭载此功能为荣?
不会真有人不知道行星减速机能用在这些领域吧?
Zeta拓扑电源原理及工作过程解析