OpenHarmony_LiteOS-M内核移植


📚往期学习笔录📝:

📝 鸿蒙(HarmonyOS)北向开发知识点记录~
📝 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
📝 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
📝 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
📝 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
📝 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
📝 记录一场鸿蒙开发岗位面试经历~
📝 持续更新中……


一、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 familyARM architectureProcessorFeatureCache(I / D),MMUTypicalMIPS@MHz
ARMv7-MSC300As Cortex-M31.25 DMIPS/MHz
Cortex-MARMv6-MCortex-M0**Microcontroller profile, most Thumb + some Thumb-2,[**12]hardware multiply instruction (optional small), optional system timer, optional bit-banding memoryOptional cache, no TCM, no MPU0.84 DMIPS/MHz
Cortex-M0+**Microcontroller profile, most Thumb + some Thumb-2,[**12]hardware multiply instruction (optional small), optional system timer, optional bit-banding memoryOptional cache, no TCM, optional MPU with 8 regions0.93 DMIPS/MHz**[14]
Cortex-M1Microcontroller profile, most Thumb + some Thumb-2,[12]hardware multiply instruction (optional small), OS option adds SVC / banked stack pointer, optional system timer, no bit-banding memoryOptional cache, 0–1024 KB I-TCM, 0–1024 KB D-TCM, no MPU136 DMIPS @ 170 MHz,[15][16]**[17]
ARMv7-MCortex-M3Microcontroller profile, Thumb / Thumb-2, hardware multiply and divide instructions, optional bit-banding memoryOptional cache, no TCM, optional MPU with 8 regions1.25 DMIPS/MHz**[18]
ARMv7E-MCortex-M4Microcontroller profile, Thumb / Thumb-2 / DSP / optional VFPv4-SP single-precisionFPU, hardware multiply and divide instructions, optional bit-banding memoryOptional cache, no TCM, optional MPU with 8 regions1.25 DMIPS/MHz (1.27 w/FPU)**[19]
Cortex-RARMv7-RCortex-R4Real-time profile, Thumb / Thumb-2 / DSP / optional VFPv3FPU, hardware multiply and optional divide instructions, optional parity & ECC for internal buses / cache / TCM, 8-stage pipeline dual-core running lockstep with fault logic0–64 KB / 0–64 KB, 0–2 of 0–8MB TCM, opt. MPU with 8/12 regions1.67 DMIPS/MHz [26]
Cortex-R5Real-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)[28]0–64 KB / 0–64 KB, 0–2 of 0–8 MB TCM, opt. MPU with 12/16 regions1.67 DMIPS/MHz[26]**[29]
Cortex-A (32-bit)ARMv7-ACortex-A5Application profile, ARM / Thumb / Thumb-2 / DSP / SIMD / Optional VFPv4-D16 FPU / 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 + TrustZone1.57 DMIPS/MHz per core
Cortex-A7Application profile, ARM / Thumb / Thumb-2 / DSP / VFPv4 FPU / NEON / Jazelle RCT and DBX / Hardware virtualization, in-order execution, superscalar , 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 [37]8−64 KB / 8−64 KB L1, 0–1 MB L2, MMU + TrustZone1.9 DMIPS/MHz per core[38]
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

存储器保护单元

对应的实现文件:用于保护内存和外设存储器。未启用保护

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值