OpenHarmony_LiteOS-M内核移植
一、LiteOS-M介绍 LiteOS-M 内核是面向轻量级物联网操作系统内核。具有小体积、低功耗、高性能的特点。根据与硬件相关性,主要分为以下两大块: 硬件相关层 arch 向上提供统一的HAL接口。以及HAL硬件及平台相关接口的实现 硬件无关层 Kernel: LiteOS 内核源码,任务调度、信号量等实现 Componets 可选组件,网络、文件系统等模块 Utils 工具相关,提供
一、LiteOS-M介绍
LiteOS-M 内核是面向轻量级物联网操作系统内核。具有小体积、低功耗、高性能的特点。根据与硬件相关性,主要分为以下两大块:
-
-
arch 向上提供统一的HAL接口。以及HAL硬件及平台相关接口的实现
-
-
硬件无关层
-
Kernel: LiteOS 内核源码,任务调度、信号量等实现
-
Componets 可选组件,网络、文件系统等模块
-
Utils 工具相关,提供错误处理、调测等能力
-
KAL 内核抽象层。向上层提供标准的操作系统接口
-
组织结构如下图所示:

源码中目录结构如下:
. ├── arch # 内核指令架构层目录 ├── components # 可选组件 ├── drivers # 驱动框架Kconfig ├── kal # 内核抽象层 ├── kernel # 内核最小功能集支持 └── utils # 通用工具
二、LitesOS源码介绍
2.1、硬件无关代码
以下是LiteOS的核心功能源码。
./kernel ├── include │ ├── los_config.h //系统时钟、系统节拍、堆栈、任务、裁剪等配置 └── src ├── los_event.c //事件初始化 ├── los_init.c //内核初始化 内核启动 ├── los_mux.c //互斥锁 ├── los_queue.c //队列 ├── los_sched.c //任务调度 ├── los_sem.c //信号量 ├── los_sortlink.c //排序链表 ├── los_swtmr.c //软件定时器 ├── los_task.c //任务创建 ├── los_tick.c //Tick时钟 └── mm ├── los_membox.c //静态内存管理 └── los_memory.c //动态内存管理
2.2、硬件相关代码 以cortex-m3为例
./arch ├── arm │ ├── cortex-m3 特定体系架构层 │ │ └── keil │ │ ├── los_arch_atomic.h # 头文件 与平台相关的arch原子操作定义 │ │ ├── los_arch_context.h # 任务调度初始化 │ │ ├── los_arch_interrupt.h # 头文件 中断接管与处理 │ │ ├── los_arch_timer.h # 头文件 systick底层实现 │ │ ├── los_atomic.S # 与平台相关的arch原子操作实现 对内存的一些操作 没看到使用 │ │ ├── los_context.c # 任务调度初始化 │ │ ├── los_dispatch.S # 中断开关、任务调度等实现 │ │ ├── los_exc.S # 异常向量处理(向量号为负值) │ │ ├── los_interrupt.c # 中断接管与处理 │ │ ├── los_startup.s # 向量表->复位向量,main入口 │ │ └── los_timer.c # systick底层实现 ├── include 通用体系架构层 │ ├── los_arch.h # 定义arch初始化 │ ├── los_atomic.h # 定义通用arch原子操作 │ ├── los_context.h # 定义通用arch上下文切换 │ ├── los_interrupt.h # 定义通用arch中断 │ ├── los_mpu.h # 定义通用arch内存保护 │ └── los_timer.h # 定义通用arch定时器
三、内核及编译平台介绍
arm处理器目前在智能手机及平板电脑占有率达到95%。Cortex-M系列在中低端嵌入式硬件也占据了绝对的领导地位。以下arm家族内核介绍:

Cortex系列 ARM公司在经典处理器ARM11以后的产品改用Cortex命名,并分成A、R和M三类,旨在为各种不同的市场提供服务。Cortex系列属于ARMv7架构,由于应用领域不同,基于v7架构的Cortex处理器系列所采用的技术也不相同,基于v7A的称为Cortex-A系列,基于v7R的称为Cortex-R系列,基于v7M的称为Cortex-M系列。
-
Application Processors(应用处理器):面向移动计算,智能手机,服务器等市场的的高端处理器。这类处理器运行在很高的时钟频率(超过1GHz),支持像Linux,Android,MS Windows和移动操作系统等完整操作系统需要的内存管理单元(MMU)。 如果规划开发的产品需要运行上述其中的一个操作系统,你需要选择ARM 应用处理器.
-
Real-time Processors (实时处理器):面向实时应用的高性能处理器系列,例如硬盘控制器,汽车传动系统和无线通讯的基带控制。多数实时处理器不支持MMU,不过通常具有MPU、Cache和其他针对工业应用设计的存储器功能。实时处理器运行在比较高的时钟频率(例如200MHz 到 >1GHz ),响应延迟非常低。虽然实时处理器不能运行完整版本的Linux和Windows操作系统, 但是支持大量的实时操作系统(RTOS)。
-
Microcontroller Processors(微控制器处理器):微控制器处理器通常设计成面积很小和能效比很高。通常这些处理器的流水线很短,最高时钟频率很低(虽然市场上有此类的处理器可以运行在200Mhz之上)。 并且,新的Cortex-M处理器家族设计的非常容易使用。因此,ARM 微控制器处理器在单片机和深度嵌入式系统市场非常成功和受欢迎。
Cortex-M 处理器家族更多的集中在低性能端,但是这些处理器相比于许多微控制器使用的传统处理器性能仍然很强大。例如,Cortex-M4 和 Cortex-M7 处理器应用在许多高性能的微控制器产品中,最大的时钟频率可以达到400Mhz。
芯片底层适配,主要区别在于内核指令集及编译平台区别
3.1、内核指令集区别
内核的区别,主要与CPU支持的指令集有关。以下是内核之间支持的指令集区别
| Product family | ARM architecture | Processor | Feature | (I / D), | Typical @ |
| ARMv7-M | SC300 | As Cortex-M3 | 1.25 DMIPS/MHz | ||
| ARMv6-M | Microcontroller profile, most Thumb + some Thumb-2,[ hardware multiply instruction (optional small), optional system timer, optional bit-banding memory | Optional cache, no TCM, no MPU | 0.84 DMIPS/MHz | ||
| Microcontroller profile, most Thumb + some Thumb-2,[ hardware multiply instruction (optional small), optional system timer, optional bit-banding memory | Optional cache, no TCM, optional MPU with 8 regions | 0.93 DMIPS/MHz | [ | ||
| Microcontroller profile, most Thumb + some Thumb-2,[ hardware multiply instruction (optional small), OS option adds SVC / banked stack pointer, optional system timer, no bit-banding memory | Optional cache, 0–1024 KB I-TCM, 0–1024 KB D-TCM, no MPU | 136 DMIPS @ 170 MHz,[ (0.8 DMIPS/MHz FPGA-dependent)[ | [ | ||
| ARMv7-M | Microcontroller profile, Thumb / Thumb-2, hardware multiply and divide instructions, optional bit-banding memory | Optional cache, no TCM, optional MPU with 8 regions | 1.25 DMIPS/MHz | [ | |
| ARMv7E-M | Microcontroller profile, Thumb / Thumb-2 / DSP / optional VFPv4-SP single-precision , hardware multiply and divide instructions, optional bit-banding memory | Optional cache, no TCM, optional MPU with 8 regions | 1.25 DMIPS/MHz (1.27 w/FPU) | [ | |
| ARMv7-R | Real-time profile, Thumb / Thumb-2 / DSP / optional VFPv3 , hardware multiply and optional divide instructions, optional parity & ECC for internal buses / cache / TCM, 8-stage pipeline dual-core running with fault logic | 0–64 KB / 0–64 KB, 0–2 of 0–8 TCM, opt. MPU with 8/12 regions | 1.67 DMIPS/MHz[ | ||
| Real-time profile, Thumb / Thumb-2 / DSP / optional VFPv3 FPU and precision, hardware multiply and optional divide instructions, optional parity & ECC for internal buses / cache / TCM, 8-stage pipeline dual-core running lock-step with fault logic / optional as 2 independent cores, low-latency peripheral port (LLPP), accelerator coherency port (ACP)[ | 0–64 KB / 0–64 KB, 0–2 of 0–8 MB TCM, opt. MPU with 12/16 regions | 1.67 DMIPS/MHz[ | [ | ||
| ARMv7-A | Application profile, ARM / Thumb / Thumb-2 / DSP / SIMD / Optional VFPv4-D16 / Optional NEON / Jazelle RCT and DBX, 1–4 cores / optional MPCore, snoop control unit (SCU), generic interrupt controller (GIC), accelerator coherence port (ACP) | 4−64 KB / 4−64 KB L1, MMU + TrustZone | 1.57 DMIPS/MHz per core | ||
| Application profile, ARM / Thumb / Thumb-2 / DSP / VFPv4 FPU / NEON / Jazelle RCT and DBX / Hardware virtualization, in-order execution, , 1–4 SMP cores, MPCore, Large Physical Address Extensions (LPAE), snoop control unit (SCU), generic interrupt controller (GIC), architecture and feature set are identical to A15, 8–10 stage pipeline, low-power design[ | 8−64 KB / 8−64 KB L1, 0–1 MB L2, MMU + TrustZone | 1.9 DMIPS/MHz per core | [ |
更多指令集参考: https://en.wikipedia.org/wiki/List_of_ARM_processors#cite_note-M0+-Spec-14
3.1.1 指令集介绍
ARM微处理器的在较新的体系结构中支持两种指令集:ARM指令集和Thumb指令集。其中,ARM指令为32位的长度,Thumb指令为16位长度。Thumb指令集为ARM指令集的功能子集,但与等价的ARM代码相比较,可节省30%~40%以上的存储空间,同时具备32位代码的所有优点。
以Cortex-M3内核为例:
-
Microcontroller profile:微控制器配置文件
-
ARM指令集:ARM指令是32位的指令,编代码全部是 32bits 的,每条指令能承载更多的信息,因此使用最少的指令完成功能, 所以在相同频率下运行速度也是最快的, 但也因为每条指令是32bits 的而占用了最多的程序空间。
-
Thumb指令集:Thumb指令是16位的指令长度,编代码全部是 16bits 的,每条指令所能承载的信息少,因此它需要使用更多的指令才能完成功能, 因此运行速度慢, 但它也占用了最少的程序空间,但是Thumb指令集中的数据处理指令的操作数仍然是32位,指令地址也为32位,并且有些处理器可以根据指令译码器将Thumb指令转换为32位的ARM指令
-
Thumb-2指令集:Thumb-2指令集是16+32混合,在前面两者之间取了一个平衡, 兼有二者的优势, 当一个 操作可以使用一条 32bits指令完成时就使用 32bits 的指令, 加快运行速度, 而当一次操作只需要一条16bits 指令完成时就使用16bits 的指令,节约存储空间
-
hardware multiply and divide instructions:硬件乘除法指令集
3.1.2 CPU寄存器介绍
ARM处理器共有37个寄存器,被分为若干个组(BANK),这些寄存器包括:
1 31个通用寄存器,包括程序计数器(PC指针),均为32位的寄存器。
2 6个状态寄存器用以标识CPU的工作状态及程序的运行状态,均为32位,只使用了其中的一部分。
-
R0~R7:通用寄存器。R0-R3 用作传入函数参数。传出函数返回值。R4-R7用于存放函数的局部变量
-
R4-R12:R8-R12 用于存放函数局部变量。在fiq模块下有自己的一套R8-R12。
-
R13 栈指针SP。不同模式下自己的 栈指针
-
R14 链接寄存器(Link Register),当执⾏⼦程序调⽤指令(BL)时,R14可得到R15(程序计数器PC)的备份。
-
R15 程序计数器PC。对于ARM指令集⽽⾔,PC总是指向当前指令的下两条指令的地址。
-
CPSR 程序状态寄存器。它包括条件标志位、中断禁止位、当前处理模式标志位等。
-
SPSR 备份程序状态寄存器。当异常发生时,用于保存CPSR的当前值。
3.1.3 处理器工作模式
-
usr 用户模式。ARM处理器正常的程序执行状态
-
sys 系统模式。运行具有特权的操作系统任务
-
svc 管理模式。操作系统保护模式
-
abt 数据访问终止模式。用于虚拟存储器及存储器保护
-
und 未定义指令终止模式。支持硬件协处理器的软件仿真
-
irq 中断模式.。用于通用的中断处理
-
fiq 快中断模式。支持高速数据传输或通道处理
除用户模式外,其余6种模式称为非用户模式或特权模式;用户模式和系统模式之外的5种模式称为异常模式。ARM处理器的运行模式可以通过软件改变,也可以通过外部中断或异常处理改变。
3.2、编译平台区别
在相同内核上,不同的编译平台语法也有部分差异。目前主流的嵌入式平台有MDK(ac5、ac6)、IAR、GCC等。
MDK:Keil 的 arm版本
ac5: MDK ARM Compiler5
ac6:MDK ARM Compiler6
GCC:Embedded Studio集成
MDK和IAR汇编区别示例:
1、#ifdef的使用 // IAR #ifdef MACRO_XX #endif //MDK(行首有空格) IF :DEF:MACRO_XX ENDIF 2、声明全局变量 // IAR PUBLIC // MDK EXPORT 3、函数实现 MDK不允许加":", IAR均可 ···
四、内核适配
LiteOS-M的芯片适配主要是实现与硬件相关的HAL接口。
即实现以下文件中定义的接口
├── include 通用体系架构层 │ ├── los_arch.h # 定义arch初始化 │ ├── los_atomic.h # 定义通用arch原子操作 │ ├── los_context.h # 定义通用arch上下文切换 │ ├── los_interrupt.h # 定义通用arch中断 │ ├── los_mpu.h # 定义通用arch内存保护 │ └── los_timer.h # 定义通用arch定时器
4.1、适配步骤
总体思路:让OS在一个芯片上跑起来,关键需要实现以下功能:
-
SystemTick的实现。给OS提供时钟节拍。
-
PendSV的中断处理。用于任务间的切换
-
其它中断异常、堆栈保护、中断开关等实现。
ARM内核适配流程如下图所示:

4.2、详细描述
先在对应的内核平台上创建如下文件:
. ├── arm │ ├── cortex-m3 │ │ └── keil │ │ ├── los_arch_atomic.h # 头文件 与平台相关的arch原子操作定义 │ │ ├── los_arch_context.h # 任务调度初始化 │ │ ├── los_arch_interrupt.h # 头文件 中断接管与处理 │ │ ├── los_arch_timer.h # 头文件 systick底层实现 │ │ ├── los_atomic.S # 与平台相关的arch原子操作实现 对内存的一些操作 没看到使用 │ │ ├── los_context.c # 任务调度初始化 │ │ ├── los_dispatch.S # 比如开中断、关中断等 │ │ ├── los_exc.S # 异常向量处理(向量号为负值) │ │ ├── los_interrupt.c # 中断接管与处理 │ │ ├── los_startup.s # 向量表->复位向量,main入口 │ │ └── los_timer.c # systick底层实现
具体的汇编功能实现可以参考其它操作系统,比如:ThreadX。找到对应的汇编文件参考。
详细接口说明如下:
4.2.1 los_arch.h
arch 初始化入口
对应的实现文件: los_context.c
VOID ArchInit(VOID);//arch初始化
4.2.2 los_timer.h
系统时钟节拍定时器相关
对应的实现文件: los_timer.c/los_arch_timer.h
接口描述:
#define LOS_SysTickTimerGet ArchSysTickTimerGet // 时钟节拍结构体获取 //关键实现以下回调函数功能 STATIC ArchTickTimer g_archTickTimer = { .freq = 0, //系统时钟 .irqNum = SysTick_IRQn, //中断号 .periodMax = LOSCFG_BASE_CORE_TICK_RESPONSE_MAX, //时钟节拍 .init = SysTickStart, //开始定时器 .getCycle = SysTickCycleGet,//获取当前定时器值 .reload = SysTickReload,//重新加载 .lock = SysTickLock,//使能 .unlock = SysTickUnlock,//禁止 .tickHandler = NULL,//时钟节拍中断中断实现 }; UINT32 ArchEnterSleep(VOID)//进入休眠
关于时钟节拍适配方法:
操作系统标准的时钟节拍中断是:OsTickHandler。以下是注册到硬件定时器相关的接口:
LITE_OS_SEC_TEXT_INIT UINT32 OsTickTimerInit(VOID) { UINT32 ret; UINT32 intSave; HWI_PROC_FUNC tickHandler = (HWI_PROC_FUNC)OsTickHandler;//得到标准时钟节拍中断 g_sysTickTimer = LOS_SysTickTimerGet();//得到底层定时器结构体 if ((g_sysTickTimer->init == NULL) || (g_sysTickTimer->reload == NULL) || (g_sysTickTimer->lock == NULL) || (g_sysTickTimer->unlock == NULL) || (g_sysTickTimer->getCycle == NULL)) { return LOS_ERRNO_SYS_HOOK_IS_NULL; } if (g_sysTickTimer->tickHandler != NULL) {//判断是否需要接管定时中断 tickHandler = g_sysTickTimer->tickHandler; } intSave = LOS_IntLock(); ret = g_sysTickTimer->init(tickHandler);//赋值时钟节拍中断,初始化tick、freq等信息 ··· return LOS_OK; }
4.2.3 los_interrupt.h
中断处理
对应的实现文件: los_interrupt.c、los_arch_interrupt.h、los_dispatch.S、los_exc.S
#define OS_INT_ACTIVE (ArchIsIntActive()) #define LOS_HwiCreate ArchHwiCreate //注册中断服务函数 #define LOS_HwiDelete ArchHwiDelete //删除中断服务函数 #define LOS_HwiTrigger ArchIntTrigger //挂起中断 #define LOS_IntRestore ArchIntRestore // 恢复中断 los_dispatch.S #define LOS_HwiEnable ArchIntEnable //中断使能 #define LOS_HwiDisable ArchIntDisable //中断禁止 #define LOS_HwiClear ArchIntClear //中断标志清除 #define LOS_HwiSetPriority ArchIntSetPriority //设置中断优先级 #define LOS_HwiCurIrqNum ArchIntCurIrqNum //得到当前中断号 #define LOS_IntLock ArchIntLock //打开irq总中断 los_dispatch.S #define LOS_IntUnLock ArchIntUnLock // 关闭irq中断 los_dispatch.S #define LOS_HwiOpsGet ArchIntOpsGet //得到中断结构体 //中断处理结构体 HwiControllerOps g_archHwiOps = { .enableIrq = HwiUnmask, .disableIrq = HwiMask, .setIrqPriority = HwiSetPriority, .getCurIrqNum = HwiNumGet, .triggerIrq = HwiPending, .clearIrq = HwiClear, };
关于外部中断实现的方法:
PendSV_Handler和SysTick_Handler应分别重新定义为HalPendSV和OsTickHandler
-
VOID HalHwiInit(VOID); 硬件相关中断初始化
main(VOID) ->LOS_KernelInit()->ArchInit()->HalHwiInit()//Hwi hardware interrupt
#define LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT 1(0 使用默认 1重定义中断向量表地址) LITE_OS_SEC_TEXT_INIT VOID HalHwiInit() { #if (LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT == 1) UINT32 index; g_hwiForm[0] = 0; /* [0] Top of Stack */ g_hwiForm[1] = 0; /* [1] reset */ for (index = 2; index < OS_VECTOR_CNT; index++) { g_hwiForm[index] = (HWI_PROC_FUNC)HalHwiDefaultHandler; } /* Exception handler register */ g_hwiForm[NonMaskableInt_IRQn + OS_SYS_VECTOR_CNT] = HalExcNMI; g_hwiForm[HARDFAULT_IRQN + OS_SYS_VECTOR_CNT] = HalExcHardFault; g_hwiForm[MemoryManagement_IRQn + OS_SYS_VECTOR_CNT] = HalExcMemFault; g_hwiForm[BusFault_IRQn + OS_SYS_VECTOR_CNT] = HalExcBusFault; g_hwiForm[UsageFault_IRQn + OS_SYS_VECTOR_CNT] = HalExcUsageFault; g_hwiForm[SVCall_IRQn + OS_SYS_VECTOR_CNT] = HalSVCHandler; g_hwiForm[PendSV_IRQn + OS_SYS_VECTOR_CNT] = HalPendSV; g_hwiForm[SysTick_IRQn + OS_SYS_VECTOR_CNT] = OsTickHandler; /* Interrupt vector table location */ SCB->VTOR = (UINT32)(UINTPTR)g_hwiForm; //中断向量重映射 #endif ··· } -
LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiCreate(HWI_HANDLE_T hwiNum,
HWI_PRIOR_T hwiPrio,
HWI_MODE_T hwiMode,
HWI_PROC_FUNC hwiHandler,
HwiIrqParam *irqParam)
中断注册,设置中断号,优先级,回调函数等参数
LiteOS-M 执行外部中断有以下两种方式:
-
方式一:响应IRQ异常,根据中断号执行中断服务函数
//1、注册中断服务函数,所有异常使用统一入口 ArchHwiCreate-> OsSetVector(hwiNum, hwiHandler)-> g_hwiForm[num + OS_SYS_VECTOR_CNT] = HalInterrupt; //2、IRQ异常中断响应入口 HalExceptIrqHdl: SUB LR, LR, #4 SAVE_CONTEXT BLX HalInterrupt RETSORE_CONTEXT //3、根据中断号执行中断服务函数 LITE_OS_SEC_TEXT VOID HalInterrupt(VOID) { ··· hwiIndex = HwiNumGet();//读取中断号 ··· if (g_hwiHandlerForm[hwiIndex] != 0) {//执行中断服务函数 g_hwiHandlerForm[hwiIndex](); } ··· }
-
方式二:根据向量表,硬件直接执行对应的中断服务函数
ArchHwiCreate-> OsSetVector(hwiNum, hwiHandler)-> g_hwiForm[num + OS_SYS_VECTOR_CNT] = hwiHandler;
由于cortex-M3 不支持IRQ, 所以会使用方式二。
4.2.4 los_context.h
任务调度
对应的实现文件: los_context.c、los_arch_context.h、los_dispatch.S
LITE_OS_SEC_TEXT_INIT VOID ArchInit(VOID)//硬件接口初始化 VOID *ArchTskStackInit(UINT32 taskID, UINT32 stackSize, VOID *topStack);//任务栈初始化 LITE_OS_SEC_TEXT_MINOR NORETURN VOID ArchSysExit(VOID);//退出处理 VOID ArchTaskSchedule(VOID);//设置软件中断标记 los_dispatch.S UINT32 ArchStartSchedule(VOID);//启动任务调度 VOID *ArchSignalContextInit(VOID *stackPointer, VOID *stackTop, UINTPTR sigHandler, UINT32 param);
4.2.5 los_atomic.h
与平台相关的arch原子操作实现
对应的实现文件: los_arch_atomic.h/los_atomic.S
//以下实现在los_atomic.S中。未在其它地方引用 #define LOS_AtomicRead ArchAtomicRead #define LOS_AtomicSet ArchAtomicSet #define LOS_AtomicAdd ArchAtomicAdd #define LOS_AtomicSub ArchAtomicSub #define LOS_AtomicInc ArchAtomicInc #define LOS_AtomicIncRet ArchAtomicIncRet #define LOS_AtomicDec ArchAtomicDec #define LOS_AtomicDecRet ArchAtomicDecRet #define LOS_Atomic64Read ArchAtomic64Read #define LOS_Atomic64Set ArchAtomic64Set #define LOS_Atomic64Add ArchAtomic64Add #define LOS_Atomic64Sub ArchAtomic64Sub #define LOS_Atomic64Inc ArchAtomic64Inc #define LOS_Atomic64IncRet ArchAtomic64IncRet #define LOS_Atomic64Dec ArchAtomic64Dec #define LOS_Atomic64DecRet ArchAtomic64DecRet #define LOS_AtomicXchg32bits ArchAtomicXchg32bits #define LOS_AtomicXchg64bits ArchAtomicXchg64bits #define LOS_AtomicCmpXchg32bits ArchAtomicCmpXchg32bits #define LOS_AtomicCmpXchg64bits ArchAtomicCmpXchg64bits
4.2.6 los_mpu.h
存储器保护单元
对应的实现文件:用于保护内存和外设存储器。未启用保护
更多推荐

所有评论(0)