Huawei LiteOS内核剖析0–启动
Huawei LiteOS,千呼万唤始出来。今天终于在[华为开发者社区][1]下载到了liteOS的开源代码。该次开源,华为提供了针对cortex-m4的内核代码和HiLink Device SDK的库函数,虽然没有什么惊喜,不过这个号称最小的操作系统,还是值得我们去研究一下。
后面准备用一系列的文章,对Huawei LiteOS进行源码剖析。如有疏漏,欢迎大家指正。以下将Huawei LiteOS简称为LiteOS
首先我们看一下LiteOS这次开源的目录结构:
从目录结构大体可以看到,liteos主要包括了基础内核代码kernel和芯片平台代码platform。kernel目录中提供了基础内核代码,包括任务,ipc(进程间通信,其实LiteOS没有进程的概念,只能叫任务间通信),内存机制等。可谓麻雀虽小,五脏俱全了。接下来,我们就从系统配置和启动代码开始,一步步分析LiteOS的内核代码。
准备活动
1.Huawei LiteOS 源码
2.iar,相信大家自己可以搞到
3.ARM® CortexTM-M4 Processor Technical Reference Manual
4.cortex M3权威指南
系统配置
LiteOS仅提供了基于IAR的工程,我们先来看下其配置文件,Huawei_LiteOS_cortexMF411.icf(个人感觉该命名略显不专业了,可能是要表达cortex-M4核,使用的是STM32F411系列芯片)
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x0807FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000400;
define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x2000;
define symbol __ICFEDIT_size_heap__ = 0x2000;
/**** End of ICF editor section. ###ICF###*/
/*** VECTOR SIZE ***/
define symbol __ICFEDIT_region_VECTOR_start__ = 0x20000000;
define symbol __ICFEDIT_region_VECTOR_end__ = 0x200003FF;
/*** End of VECTOR SIZE ***/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
/*** VECTOR region***/
define region VECTOR_region = mem:[from __ICFEDIT_region_VECTOR_start__ to __ICFEDIT_region_VECTOR_end__];
/*** End of VECTOR region***/
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
/*** VECTOR ***/
place in VECTOR_region { section .vector };
/*** End of VECTOR ***/
place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block HEAP };
从以上配置我们可以获悉:该工程配置了512k的ROM和128k的RAM,其中RAM的前面1k配置给了 .vector段。ROM属性为只读,RAM属性为可读可写。另外还定义了8k的CSTACK和HEAP放在RAM空间中。(对icf不明白的同学可以自行google,iar的使用也不做介绍了,喜欢动手的小伙伴可以自行在网上找资源练习)
启动
在los_vendor.s中首先定义了段属性和__vector_table数组:
SECTION CSTACK:DATA:NOROOT(3)
SECTION .intvec:CODE:NOROOT(2)
...
DATA
__vector_table
DCD sfe(CSTACK)
DCD Reset_Handler ; Reset Handler
Reset_Handler
LDR R0, =osEnableFPU
BLX R0
LDR R0, =__iar_program_start
BX R0
END
首先来看SECTION,IAR汇编中对SECTION格式的定义是:
SECTION section : type [flag] [(align)]
第一个段定义不太清楚具体用处,第二个段定义了下面代码的类型为CODE段,放到上面icf文件定义的 .intvec段中,即0x08000000处,并在该首地址指定了中断向量表的前两个成员,首先初始化MSP寄存器的值,然后获取第一个指令的跳转地址,即执行 Reset_Handler。
接着定义了 Reset_Handler函数实现。
对应的实现非常简单,首先跳转到 osEnableFPU,初始化FPU寄存器。可以参看Technical Reference Manual中7.3.1 enable the fpu:
上面翻译成c语言就是
*(volatile UINT32 *)0xE000ED88 |= ((0xF << 20));
与LiteOS的表达一致。
接着,系统又跳转到了 __iar_program_start,这里面IAR做了什么,大家可以百度一下,基本上就是搬运一下代码,清0一下.bss段,如果想支持c++,再搞跑一下构造函数啥的。
接下来系统就会跑到main()函数了。做法基本上与ST给的demo一致(好像也没有什么其他做法了?)。
启动部分比较简单,大家的做法也都差不多了。启动就说到这,下一部分我们来了解一下LiteOS所包含的模块和对应的初始化代码。