华为云用户手册

  • 中断相关概念 中断号 每个中断请求信号都会有特定的标志,使得计算机能够判断是哪个设备提出的中断请求,这个标志就是中断号。 中断请求 “紧急事件”需向CPU提出申请(发一个电脉冲信号),要求中断,及要求CPU暂停当前执行的任务,转而处理该“紧急事件”,这一申请过程称为中断请求。 中断优先级 为使系统能够及时响应并处理所有中断,系统根据中断时间的重要性和紧迫程度,将中断源分为若干个级别,称作中断优先级。 中断处理程序 当外设产生中断请求后,CPU暂停当前的任务,转而响应中断申请,即执行中断处理程序。产生中断的每个设备都有相应的中断处理程序。 中断嵌套 中断嵌套也称为中断抢占,指的是正在执行一个中断处理程序时,如果有另一个优先级更高的中断源提出中断请求,这时会暂时终止当前正在执行的优先级较低的中断源的中断处理程序,转而去处理更高优先级的中断请求,待处理完毕,再返回到之前被中断的处理程序中继续执行。 中断触发 中断源向中断控制器发送中断信号,中断控制器对中断进行仲裁,确定优先级,将中断信号送给CPU。中断源产生中断信号的时候,会将中断触发器置“1”,表明该中断源产生了中断,要求CPU去响应该中断。 中断触发类型 外部中断申请通过一个物理信号发送到NVIC/GIC,可以是电平触发或边沿触发。 中断向量 中断服务程序的入口地址。 中断向量表 存储中断向量的存储区,中断向量与中断号对应,中断向量在中断向量表中按照中断号顺序存储。 中断共享 当外设较少时,可以实现一个外设对应一个中断号,但为了支持更多的硬件设备,可以让多个设备共享一个中断号,共享同一个中断号的中断处理程序形成一个链表。当外部设备产生中断申请时,系统会遍历执行中断号对应的中断处理程序链表直到找到对应设备的中断处理程序。在遍历执行过程中,各中断处理程序可以通过检测设备ID,判断是否是这个中断处理程序对应的设备产生的中断。 核间中断 对于多核系统,中断控制器允许一个CPU的硬件线程去中断其他CPU的硬件线程,这种方式被称为核间中断。核间中断的实现基础是多CPU内存共享,采用核间中断可以减少某个CPU负荷过大,有效提升系统效率。目前只有GIC中断控制器支持。
  • 功能 Huawei LiteOS的双向链表模块为用户提供下面几种功能,接口详细信息可以查看API参考。 功能分类 接口名 描述 初始化链表 LOS_ListInit 将指定节点初始化为双向链表节点 LOS_DL_LIST_HEAD 定义一个节点并初始化为双向链表节点 增加节点 LOS_ListAdd 将指定节点插入到双向链表头端 LOS_ListHeadInsert 将指定节点插入到双向链表头端,同LOS_ListAdd LOS_ListTailInsert 将指定节点插入到双向链表尾端 删除节点 LOS_ListDelete 将指定节点从链表中删除 LOS_ListDelInit 将指定节点从链表中删除,并使用该节点初始化链表 判断双向链表是否为空 LOS_ListEmpty 判断链表是否为空 获取节点 LOS_DL_LIST_LAST 获取指定节点的前驱结点 LOS_DL_LIST_FIRST 获取指定节点的后继结点 获取结构体信息 LOS_DL_LIST_ENTRY 获取包含链表的结构体地址,接口的第一个入参表示的是链表中的某个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称 LOS_OFF_SET_OF 获取指定结构体内的成员相对于结构体起始地址的偏移量 遍历双向链表 LOS_DL_LIST_FOR_EACH 遍历双向链表 LOS_DL_LIST_FOR_EACH_SAFE 遍历双向链表,并存储当前节点的后继节点用于安全校验 遍历包含双向链表的结构体 LOS_DL_LIST_FOR_EACH_ENTRY 遍历指定双向链表,获取包含该链表节点的结构体地址 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE 遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址 LOS_DL_LIST_FOR_EACH_ENTRY_HOOK 遍历指定双向链表,获取包含该链表节点的结构体地址,并在每次循环中调用钩子函数
  • 开发流程 双向链表的典型开发流程: 调用LOS_ListInit/LOS_DL_LIST_HEAD初始双向链表。 调用LOS_ListAdd/LOS_ListHeadInsert向链表头部插入节点。 调用LOS_ListTailInsert向链表尾部插入节点。 调用LOS_ListDelete删除指定节点。 调用LOS_ListEmpty判断链表是否为空。 调用LOS_ListDelInit删除指定节点并以此节点初始化链表。
  • 功能 Huawei LiteOS 的自旋锁模块为用户提供下面几种功能,接口详细信息可以查看API参考。 功能分类 接口名 描述 初始化自旋锁 LOS_SpinInit 动态初始化自旋锁 SPIN_LOCK_INIT 静态初始化自旋锁 申请/释放自旋锁 LOS_SpinLock 申请指定的自旋锁,如果无法获取锁,会一直循环等待 LOS_SpinTrylock 尝试申请指定的自旋锁,如果无法获取锁,直接返回失败,而不会一直循环等待 LOS_SpinUnlock 释放指定的自旋锁 申请/释放自旋锁(同时进行关中断保护) LOS_SpinLockSave 关中断后,再申请指定的自旋锁 LOS_SpinUnlockRestore 先释放指定的自旋锁,再恢复中断状态 获取自旋锁持有状态 LOS_SpinHeld 检查自旋锁是否已经被持有
  • 软件定时器错误码 对存在失败可能性的操作返回对应的错误码,以便快速定位错误原因。 序号 定义 实际数值 描述 参考解决方案 1 LOS_ERRNO_SWTMR_PTR_NULL 0x02000300 软件定时器回调函数为空 定义软件定时器回调函数 2 LOS_ERRNO_SWTMR_INTERVAL_NOT_SUITED 0x02000301 软件定时器的定时时长为0 重新定义定时器的定时时长 3 LOS_ERRNO_SWTMR_MODE_INVALID 0x02000302 不正确的软件定时器模式 确认软件定时器模式,范围为[0,2] 4 LOS_ERRNO_SWTMR_RET_PTR_NULL 0x02000303 入参的软件定时器ID指针为NULL 定义ID变量,传入有效指针 5 LOS_ERRNO_SWTMR_MAXSIZE 0x02000304 软件定时器个数超过最大值 重新设置软件定时器最大个数,或者等待一个软件定时器释放资源 6 LOS_ERRNO_SWTMR_ID_INVALID 0x02000305 入参的软件定时器ID不正确 确保入参合法 7 LOS_ERRNO_SWTMR_NOT_CREATED 0x02000306 软件定时器未创建 创建软件定时器 8 LOS_ERRNO_SWTMR_NO_MEMORY 0x02000307 初始化软件定时器模块时,内存不足 调整OS_SYS_MEM_SIZE,以确保有足够的内存供软件定时器使用 9 LOS_ERRNO_SWTMR_MAXSIZE_INVALID 0x02000308 暂不使用该错误码 - 10 LOS_ERRNO_SWTMR_HWI_ACTIVE 0x02000309 在中断中使用定时器 修改源代码确保不在中断中使用 11 LOS_ERRNO_SWTMR_HANDLER_POOL_NO_MEM 0x0200030a 暂不使用该错误码 - 12 LOS_ERRNO_SWTMR_QUEUE_CREATE_FAILED 0x0200030b 在软件定时器初始化时,创建定时器队列失败 调整OS_SYS_MEM_SIZE,以确保有足够的内存供软件定时器创建队列 13 LOS_ERRNO_SWTMR_TASK_CREATE_FAILED 0x0200030c 在软件定时器初始化时,创建定时器任务失败 调整OS_SYS_MEM_SIZE,以确保有足够的内存供软件定时器创建任务 14 LOS_ERRNO_SWTMR_NOT_STARTED 0x0200030d 未启动软件定时器 启动软件定时器 15 LOS_ERRNO_SWTMR_STATUS_INVALID 0x0200030e 不正确的软件定时器状态 检查确认软件定时器状态 16 LOS_ERRNO_SWTMR_SORTLIST_NULL 0x0200030f 暂不使用该错误码 - 17 LOS_ERRNO_SWTMR_TICK_PTR_NULL 0x02000310 用以获取软件定时器剩余Tick数的入参指针为NULL 定义有效变量以传入有效指针 18 LOS_ERRNO_SWTMR_SORTLINK_CREATE_FAILED 0x02000311 在软件定时器初始化时,创建定时器链表失败 调整OS_SYS_MEM_SIZE,以确保有足够的内存供软件定时器创建链表 错误码定义见错误码简介。8~15位的所属模块为软件定时器模块,值为0x03。
  • 功能 Huawei LiteOS的软件定时器模块为用户提供下面几种功能,接口详细信息可以查看API参考。 表1 功能分类 接口名 描述 创建/删除定时器 LOS_SwtmrCreate 创建定时器,设置定时器的定时时长、定时器模式、回调函数,并返回定时器ID LOS_SwtmrDelete 删除定时器 启动/停止定时器 LOS_SwtmrStart 启动定时器 LOS_SwtmrStop 停止定时器 获得软件定时器剩余Tick数 LOS_SwtmrTimeGet 获得软件定时器剩余Tick数
  • 结果验证 得到的结果为: Create Timer1 successstart Timer1 sucesstick =800Stop Timer1 sucessg_timerCount1=1201tick_last1=1201delete Timer1 successStart Timer2g_timerCount2=1tick_last2=1301g_timerCount2=2tick_last2=1401g_timerCount2=3tick_last2=1501g_timerCount2=4tick_last2=1601g_timerCount2=5tick_last2=1701g_timerCount2=6tick_last2=1801g_timerCount2=7tick_last2=1901g_timerCount2=8tick_last2=2001g_timerCount2=9tick_last2=2101g_timerCount2=10tick_last2=2201
  • 编程示例 前提条件:在menuconfig菜单中完成任务模块的配置。 UINT32 g_taskHiId;UINT32 g_taskLoId;#define TSK_PRIOR_HI 4#define TSK_PRIOR_LO 5UINT32 Example_TaskHi(VOID){ UINT32 ret; printf("Enter TaskHi Handler.\r\n"); /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(g_taskLoId任务) */ ret = LOS_TaskDelay(2); if (ret != LOS_OK) { printf("Delay Task Failed.\r\n"); return LOS_NOK; } /* 2个Tick时间到了后,该任务恢复,继续执行 */ printf("TaskHi LOS_TaskDelay Done.\r\n"); /* 挂起自身任务 */ ret = LOS_TaskSuspend(g_taskHiId); if (ret != LOS_OK) { printf("Suspend TaskHi Failed.\r\n"); return LOS_NOK; } printf("TaskHi LOS_TaskResume Success.\r\n"); return ret;}/* 低优先级任务入口函数 */UINT32 Example_TaskLo(VOID){ UINT32 ret; printf("Enter TaskLo Handler.\r\n"); /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(背景任务) */ ret = LOS_TaskDelay(2); if (ret != LOS_OK) { printf("Delay TaskLo Failed.\r\n"); return LOS_NOK; } printf("TaskHi LOS_TaskSuspend Success.\r\n"); /* 恢复被挂起的任务g_taskHiId */ ret = LOS_TaskResume(g_taskHiId); if (ret != LOS_OK) { printf("Resume TaskHi Failed.\r\n"); return LOS_NOK; } printf("TaskHi LOS_TaskDelete Success.\r\n"); return ret;}/* 任务测试入口函数,创建两个不同优先级的任务 */UINT32 Example_TskCaseEntry(VOID){ UINT32 ret; TSK_INIT_PA RAM _S initParam; /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ LOS_TaskLock(); printf("LOS_TaskLock() Success!\r\n"); initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi; initParam.usTaskPrio = TSK_PRIOR_HI; initParam.pcName = "TaskHi"; initParam.uwStackSize = LOSCFG_TASK_MIN_STACK_SIZE; initParam.uwResved = LOS_TASK_STATUS_DETACHED; /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ ret = LOS_TaskCreate(&g_taskHiId, &initParam); if (ret != LOS_OK) { LOS_TaskUnlock(); printf("Example_TaskHi create Failed!\r\n"); return LOS_NOK; } printf("Example_TaskHi create Success!\r\n"); initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo; initParam.usTaskPrio = TSK_PRIOR_LO; initParam.pcName = "TaskLo"; initParam.uwStackSize = LOSCFG_TASK_MIN_STACK_SIZE; initParam.uwResved = LOS_TASK_STATUS_DETACHED; /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ ret = LOS_TaskCreate(&g_taskLoId, &initParam); if (ret != LOS_OK) { LOS_TaskUnlock(); printf("Example_TaskLo create Failed!\r\n"); return LOS_NOK; } printf("Example_TaskLo create Success!\r\n"); /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ LOS_TaskUnlock(); return LOS_OK;}
  • 结果验证 编译运行得到的结果为: LOS_TaskLock() Success!Example_TaskHi create Success!Example_TaskLo create Success!Enter TaskHi Handler.Enter TaskLo Handler.TaskHi LOS_TaskDelay Done.TaskHi LOS_TaskSuspend Success.TaskHi LOS_TaskResume Success.TaskHi LOS_TaskDelete Success.
  • 结果验证 编译运行得到结果: Bitmap Sample!The flag is 0x10101010LOS_BitmapSet: pos : 8, the flag is 0x10101110LOS_HighBitGet:The highest one bit is 28, the flag is 0x10101110LOS_BitmapClr: pos : 28, the flag is 0x00101110LOS_LowBitGet: The lowest one bit is 4, the flag is 0x00101110
  • 编程示例 前提条件:在menuconfig菜单中完成软件定时器的配置。 代码实现如下: UINT32 g_timerCount1 = 0;UINT32 g_timerCount2 = 0;VOID Timer1_CallBack(UINT32 arg){ UINT64 lastTick; g_timerCount1++; lastTick=(UINT32)LOS_TickCountGet(); dprintf("g_timerCount1=%d\n", g_timerCount1); dprintf("tick_last1=%d\n", lastTick);}VOID Timer2_CallBack(UINT32 arg){ UINT64 lastTick; lastTick=(UINT32)LOS_TickCountGet(); g_timerCount2++; dprintf("g_timerCount2=%d\n", g_timerCount2); dprintf("tick_last2=%d\n", lastTick);}VOID Timer_example(VOID){ UINT16 id1; // Timer1 id UINT16 id2; // Timer2 id UINT32 tick; LOS_SwtmrCreate(1000, LOS_SWTMR_MODE_ONCE, Timer1_CallBack, &id1, 1); LOS_SwtmrCreate(100, LOS_SWTMR_MODE_PERIOD, Timer2_CallBack, &id2, 1); dprintf("create Timer1 success\n"); LOS_SwtmrStart(id1); dprintf("start Timer1 sucess\n"); LOS_TaskDelay(200); LOS_SwtmrTimeGet(id1, &tick); dprintf("tick =%d\n", tick); LOS_SwtmrStop(id1); dprintf("stop Timer1 sucess\n"); LOS_SwtmrStart(id1); LOS_TaskDelay(1000); LOS_SwtmrDelete(id1); dprintf("delete Timer1 sucess\n"); LOS_SwtmrStart(id2); dprintf("start Timer2\n"); LOS_TaskDelay(1000); LOS_SwtmrStop(id2); LOS_SwtmrDelete(id2); }
  • 编程示例 #include "los_bitmap.h"#include "los_printf.h"static UINT32 Bit_Sample(VOID){ UINT32 flag = 0x10101010; UINT16 pos; dprintf("\nBitmap Sample!\n"); dprintf("The flag is 0x%8x\n", flag); pos = 8; LOS_BitmapSet(&flag, pos); dprintf("LOS_BitmapSet:\t pos : %d, the flag is 0x%0+8x\n", pos, flag); pos = LOS_HighBitGet(flag); dprintf("LOS_HighBitGet:\t The highest one bit is %d, the flag is 0x%0+8x\n", pos, flag); LOS_BitmapClr(&flag, pos); dprintf("LOS_BitmapClr:\t pos : %d, the flag is 0x%0+8x\n", pos, flag); pos = LOS_LowBitGet(flag); dprintf("LOS_LowBitGet:\t The lowest one bit is %d, the flag is 0x%0+8x\n\n", pos, flag); return LOS_OK;}
  • 功能 Huawei LiteOS系统中的动态内存管理模块为用户提供下面几种功能,接口详细信息可以查看API参考。 功能分类 接口名 描述 初始化和删除内存池 LOS_MemInit 初始化一块指定的动态内存池,大小为size LOS_MemDeInit 删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效 申请、释放动态内存 LOS_MemAlloc 从指定动态内存池中申请size长度的内存 LOS_MemFree 释放已申请的内存 LOS_MemRealloc 按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块 LOS_MemAllocAlign 从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存 获取内存池信息 LOS_MemPoolSizeGet 获取指定动态内存池的总大小 LOS_MemTotalUsedGet 获取指定动态内存池的总使用量大小 LOS_MemInfoGet 获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小 LOS_MemPoolList 打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效 获取内存块信息 LOS_MemFreeBlksGet 获取指定内存池的空闲内存块数量 LOS_MemUsedBlksGet 获取指定内存池已使用的内存块数量 LOS_MemTaskIdGet 获取申请了指定内存块的任务ID LOS_MemLastUsedGet 获取内存池最后一个已使用内存块的结束地址 LOS_MemNodeSizeCheck 获取指定内存块的总大小和可用大小,仅打开LOSCFG_BASE_MEM_NODE_SIZE_CHECK时有效 LOS_MemFreeNodeShow 打印指定内存池的空闲内存块的大小及数量 检查指定内存池的完整性 LOS_MemIntegrityCheck 对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效 设置、获取内存检查级别,仅打开LOSCFG_BASE_MEM_NODE_SIZE_CHECK时有效 LOS_MemCheckLevelSet 设置内存检查级别 LOS_MemCheckLevelGet 获取内存检查级别 为指定模块申请、释放动态内存,仅打开LOSCFG_MEM_MUL_MODULE时有效 LOS_MemMalloc 从指定动态内存池分配size长度的内存给指定模块,并纳入模块统计 LOS_MemMfree 释放已经申请的内存块,并纳入模块统计 LOS_MemMallocAlign 从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存给指定模块,并纳入模块统计 LOS_MemMrealloc 按size大小重新分配内存块给指定模块,并将原内存块内容拷贝到新内存块,同时纳入模块统计。如果新内存块申请成功,则释放原内存块 获取指定模块的内存使用量 LOS_MemMusedGet 获取指定模块的内存使用量,仅打开LOSCFG_MEM_MUL_MODULE时有效 动态内存提供了内存调测功能,具体使用方法见内存调测方法。 对于bestfit_little算法,只支持多内存池机制和内存合法性检查,不支持其他内存调测功能。 上述接口中,通过宏开关控制的都是内存调测功能相关的接口。 通过LOS_MemAllocAlign/LOS_MemMallocAlign申请的内存进行LOS_MemRealloc/LOS_MemMrealloc操作后,不能保障新的内存首地址保持对齐。 对于bestfit_little算法,不支持对LOS_MemAllocAlign申请的内存进行LOS_MemRealloc操作,否则将返回失败。
  • 基本概念 队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。如果将读队列和写队列的超时时间设置为0,则不会挂起任务,接口会直接返回,这就是非阻塞模式。
  • 运作机制 软件定时器是系统资源,在模块初始化的时候已经分配了一块连续内存。 软件定时器使用了系统的一个队列和一个任务资源,软件定时器的触发遵循队列规则,先进先出。定时时间短的定时器总是比定时时间长的靠近队列头,满足优先触发的准则。 软件定时器以Tick为基本计时单位,当创建并启动一个软件定时器时,Huawei LiteOS会根据当前系统Tick时间及设置的定时时长确定该定时器的到期Tick时间,并将该定时器控制结构挂入计时全局链表。 当Tick中断到来时,在Tick中断处理函数中扫描软件定时器的计时全局链表,检查是否有定时器超时,若有则将超时的定时器记录下来。Tick中断处理函数结束后,软件定时器任务(优先级为最高)被唤醒,在该任务中调用已经记录下来的定时器的回调函数。
  • 运作机制 队列控制块 typedef enum { OS_QUEUE_READ =0, OS_QUEUE_WRITE =1, OS_QUEUE_N_RW =2} QueueReadWrite;/** * Queue information block structure */typedef struct { UINT8 *queueHandle; /* 队列指针 */ UINT8 queueState; /* 队列状态 */ UINT8 queueMemType; /* 创建队列时内存分配的方式 */ UINT16 queueLen; /* 队列中消息节点个数,即队列长度 */ UINT16 queueSize; /* 消息节点大小 */ UINT32 queueID; /* 队列ID */ UINT16 queueHead; /* 消息头节点位置(数组下标)*/ UINT16 queueTail; /* 消息尾节点位置(数组下标)*/ UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /* 数组下标0的元素表示队列中可读消息数, 数组下标1的元素表示队列中可写消息数 */ LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /* 读取或写入消息的任务等待链表, 下标0:读取链表,下标1:写入链表 */ LOS_DL_LIST memList; /* CMSIS-RTOS中的MailBox模块使用的内存块链表 */} LosQueueCB; 每个队列控制块中都含有队列状态,表示该队列的使用情况: OS_QUEUE_UNUSED:队列没有被使用。 OS_QUEUE_INUSED:队列被使用中。 每个队列控制块中都含有创建队列时的内存分配方式: OS_QUEUE_ALLOC_DYNAMIC:创建队列时所需的队列空间,由系统自行动态申请内存获取。 OS_QUEUE_ALLOC_STATIC:创建队列时所需的队列空间,由接口调用者自行申请后传入接口。 队列运作原理 创建队列时,创建队列成功会返回队列ID。 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail来,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。 写队列时,根据readWriteableCnt[1]判断队列是否可以写入,不能对已满(readWriteableCnt[1]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。 读队列时,根据readWriteableCnt[0]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt[0]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态。如果是通过系统动态申请内存方式创建的队列,还会释放队列所占内存。 图1 队列读写数据操作示意图 上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。
  • 注意事项 初始化内存池时,需保证各内存池空间无交叉,若交叉则会导致初始化失败。 malloc/free系列接口默认从OS系统内存池申请和释放内存,其它内存池的操作必须调用Huawei LiteOS内存接口(LOS_MemAlloc等),不能调用malloc/free系列接口及其相关封装接口。 内存池回收必须调用LOS_MemDeInit接口去初始化(回收前需确保池中内存块均已释放),否则二次初始化该内存池空间会失败,导致该内存池不能被重新使用。 内存池大小需根据业务实际情况合理分配。
  • 功能说明 系统内存机制中通过链表实现对多个内存池的管理。内存池需回收时可调用对应接口进行去初始化。 通过多内存池机制,可以获取系统各个内存池的信息和使用情况,也可以检测内存池空间分配交叉情况,当系统两个内存池空间交叉时,第二个内存池会初始化失败,并给出空间交叉的提示信息。 功能分类 接口名 描述 初始化内存池 LOS_MemInit 初始化一块指定的动态内存池,大小为size 删除内存池 LOS_MemDeInit 删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效 显示系统内存池 LOS_MemPoolList 打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量,仅打开LOSCFG_MEM_MUL_POOL时有效
  • 编程实例 void test(void){ UINT32 ret = 0; UINT32 size = 0x100000; VOID *poolAddr1 = LOS_MemAlloc(OS_SYS_MEM_ADDR, size); ret = LOS_MemInit(poolAddr1, size); if (ret != 0) { PRINTK("LOS_MemInit failed\n"); return; } VOID *poolAddr2 = LOS_MemAlloc(OS_SYS_MEM_ADDR, size); ret = LOS_MemInit(poolAddr2, size); if (ret != 0) { PRINTK("LOS_MemInit failed\n"); return; } PRINTK("\n********step1 list the mem poll\n"); LOS_MemPoolList(); LOS_MemDeInit(poolAddr1); if (ret != 0) { PRINTK("LOS_MemDeInit failed\n"); return; } PRINTK("\n********step2 list the mem poll\n"); LOS_MemPoolList(); LOS_MemDeInit(poolAddr2); if (ret != 0) { PRINTK("LOS_MemDeInit failed\n"); return; } PRINTK("\n********step3 list the mem poll\n"); LOS_MemPoolList(); } log: ********step1 list the mem pollpool0 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8017b2c0 0x100000 0x2e1fc 0xd1d20 0xd1d20 0x2b 0x1 pool1 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8027b2c0 0x7d84d40 0x7070c8 0x767db94 0x767db94 0x1026 0x1 pool2 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8078244c 0x100000 0x10 0xfff0c 0xfff0c 0x1 0x1 pool3 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8088245c 0x100000 0x10 0xfff0c 0xfff0c 0x1 0x1 ********step2 list the mem pollpool0 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8017b2c0 0x100000 0x2e1fc 0xd1d20 0xd1d20 0x2b 0x1 pool1 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8027b2c0 0x7d84d40 0x7070c8 0x767db94 0x767db94 0x1026 0x1 pool2 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8088245c 0x100000 0x10 0xfff0c 0xfff0c 0x1 0x1 ********step3 list the mem pollpool0 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8017b2c0 0x100000 0x2e1fc 0xd1d20 0xd1d20 0x2b 0x1 pool1 :pool addr pool size used size free size max free node size used node num free node num--------------- -------- ------- -------- -------------- ------------- ------------0x8027b2c0 0x7d84d40 0x7070c8 0x767db94 0x767db94 0x1026 0x1
  • 功能 Huawei LiteOS 的中断模块为用户提供下面几种功能,接口详细信息可以查看API参考。 功能分类 接口名 描述 创建和删除中断 LOS_HwiCreate 中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,handleIrq会调用该中断处理程序 LOS_HwiDelete 删除中断 打开和关闭所有中断 LOS_IntUnLock 打开当前处理器所有中断响应 LOS_IntLock 关闭当前处理器所有中断响应 LOS_IntRestore 恢复到使用LOS_IntLock关闭所有中断之前的状态 使能和屏蔽指定中断 LOS_HwiDisable 中断屏蔽(通过设置寄存器,禁止CPU响应该中断) LOS_HwiEnable 中断使能(通过设置寄存器,允许CPU响应该中断) 设置中断优先级 LOS_HwiSetPriority 设置中断优先级 触发中断 LOS_HwiTrigger 触发中断(通过写中断控制器的相关寄存器模拟外部中断) 清除中断寄存器状态 LOS_HwiClear 清除中断号对应的中断寄存器的状态位,此接口依赖中断控制器版本,非必需 核间中断 LOS_HwiSendIpi 向指定核发送核间中断,此接口依赖中断控制器版本和cpu架构,该函数仅在SMP模式下支持 设置中断亲和性 LOS_HwiSetAffinity 设置中断的亲和性,即设置中断在固定核响应(该函数仅在SMP模式下支持)
  • HWI错误码 对存在失败可能性的操作返回对应的错误码,以便快速定位错误原因。 序号 定义 实际数值 描述 参考解决方案 1 OS_ERRNO_HWI_NUM_INVALID 0x02000900 创建或删除中断时,传入了无效中断号 检查中断号,给定有效中断号 2 OS_ERRNO_HWI_PROC_FUNC_NULL 0x02000901 创建中断时,传入的中断处理程序指针为空 传入非空中断处理程序指针 3 OS_ERRNO_HWI_CB_UNAVAILABLE 0x02000902 无可用中断资源 暂不使用该错误码 4 OS_ERRNO_HWI_NO_MEMORY 0x02000903 创建中断时,出现内存不足的情况 增大动态内存空间,有两种方式可以实现: 设置更大的系统动态内存池,配置项为OS_SYS_MEM_SIZE 释放一部分动态内存 5 OS_ERRNO_HWI_ALREADY_CREATED 0x02000904 创建中断时,发现要注册的中断号已经创建 对于非共享中断号的情况,检查传入的中断号是否已经被创建;对于共享中断号的情况,检查传入中断号的链表中是否已经有匹配函数参数的设备ID 6 OS_ERRNO_HWI_PRIO_INVALID 0x02000905 创建中断时,传入的中断优先级无效 传入有效中断优先级。优先级有效范围依赖于硬件,外部可配 7 OS_ERRNO_HWI_MODE_INVALID 0x02000906 中断模式无效 传入有效中断模式[0,1] 8 OS_ERRNO_HWI_FASTMODE_ALREADY_CREATED 0x02000907 创建硬中断时,发现要注册的中断号,已经创建为快速中断 暂不使用该错误码 9 OS_ERRNO_HWI_INTERR 0x02000908 接口在中断中调用 暂不使用该错误码 10 OS_ERRNO_HWI_SHARED_ERROR 0x02000909 创建中断时:发现hwiMode指定创建共享中断,但是未设置设备ID;或hwiMode指定创建非共享中断,但是该中断号之前已创建为共享中断;或配置LOSCFG_NO_SHARED_IRQ为yes,但是创建中断时,入参指定创建共享中断 删除中断时:设备号创建时指定为共享中断,删除时未设置设备ID,删除错误。 检查入参,创建时参数hwiMode与irqParam保持一致,hwiMode为0,表示不共享,此时irqParam应为NULL;当hwiMode为IRQF_SHARD时表示共享,irqParam需设置设备ID;LOSCFG_NO_SHARED_IRQ为YES时,即非共享中断模式下,只能创建非共享中断。删除中断时irqParam要与创建中断时的参数一样 11 OS_ERRNO_HWI_ARG_INVALID 0x0200090a 注册中断入参有误 暂不使用该错误码 12 OS_ERRNO_HWI_HWINUM_UNCREATE 0x0200090b 中断共享情况下,删除中断时,中断号对应的链表中,无法匹配到相应的设备ID 对于共享中断号的情况,检查传入中断号的链表中是否已经有匹配函数参数的设备ID 错误码定义见错误码简介。8~15位的所属模块为中断模块,值为0x09。
  • 功能 Huawei LiteOS中的队列模块提供下面几种功能,接口详细信息可以查看API参考。 功能分类 接口名 描述 创建/删除消息队列 LOS_QueueCreate 创建一个消息队列,由系统动态申请队列空间 LOS_QueueCreateStatic 创建一个消息队列,由用户分配队列内存空间传入接口 LOS_QueueDelete 根据队列ID删除一个指定队列 读/写队列(不带拷贝) LOS_QueueRead 读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址) LOS_QueueWrite 向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址) LOS_QueueWriteHead 向指定队列头节点中写入入参bufferAddr的值(即buffer的地址) 读/写队列(带拷贝) LOS_QueueReadCopy 读取指定队列头节点中的数据 LOS_QueueWriteCopy 向指定队列尾节点中写入入参bufferAddr中保存的数据 LOS_QueueWriteHeadCopy 向指定队列头节点中写入入参bufferAddr中保存的数据 获取队列信息 LOS_QueueInfoGet 获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务、等待mail操作的任务
  • 队列错误码 对存在失败可能性的操作返回对应的错误码,以便快速定位错误原因。 序号 定义 实际数值 描述 参考解决方案 1 LOS_ERRNO_QUEUE_MAXNUM_ZERO 0x02000600 系统支持的最大队列数为0 系统支持的最大队列数应该大于0。如果不使用队列模块,则将队列模块静态裁剪开关LOSCFG_BASE_IPC_QUEUE设置为NO 2 LOS_ERRNO_QUEUE_NO_MEMORY 0x02000601 队列初始化时,从动态内存池申请内存失败 设置更大的系统动态内存池,配置项为OS_SYS_MEM_SIZE,或减少系统支持的最大队列数 3 LOS_ERRNO_QUEUE_CREATE_NO_MEMORY 0x02000602 创建队列时,从动态内存池申请内存失败 设置更大的系统动态内存池,配置项为OS_SYS_MEM_SIZE,或减少要创建队列的队列长度和消息节点大小 4 LOS_ERRNO_QUEUE_SIZE_TOO_BIG 0x02000603 创建队列时消息节点大小超过上限 更改入参消息节点大小,使之不超过上限 5 LOS_ERRNO_QUEUE_CB_UNAVAILABLE 0x02000604 创建队列时,系统中已经没有空闲队列 增加系统支持的最大队列数 6 LOS_ERRNO_QUEUE_NOT_FOUND 0x02000605 传递给删除队列接口的队列ID大于等于系统支持的最大队列数 确保队列ID是有效的 7 LOS_ERRNO_QUEUE_PEND_IN_LOCK 0x02000606 当任务被锁定时,禁止在队列中阻塞等待写消息或读消息 使用队列前解锁任务 8 LOS_ERRNO_QUEUE_TIMEOUT 0x02000607 等待处理队列超时 检查设置的超时时间是否合适 9 LOS_ERRNO_QUEUE_IN_TSKUSE 0x02000608 队列存在阻塞任务而不能被删除 使任务能够获得资源而不是在队列中被阻塞 10 LOS_ERRNO_QUEUE_WRITE_IN_INTERRUPT 0x02000609 在中断处理程序中不能以阻塞模式写队列 将写队列设为非阻塞模式,即将写队列的超时时间设置为0 11 LOS_ERRNO_QUEUE_NOT_CREATE 0x0200060a 队列未创建 创建该队列,或更换为一个已经创建的队列 12 LOS_ERRNO_QUEUE_IN_TSKWRITE 0x0200060b 队列读写不同步 同步队列的读写,即多个任务不能并发读写同一个队列 13 LOS_ERRNO_QUEUE_CREAT_PTR_NULL 0x0200060c 对于创建队列接口,保存队列ID的入参为空指针 确保传入的参数不为空指针 14 LOS_ERRNO_QUEUE_PARA_ISZERO 0x0200060d 对于创建队列接口,入参队列长度或消息节点大小为0 传入正确的队列长度和消息节点大小 15 LOS_ERRNO_QUEUE_INVALID 0x0200060e 传递给读队列或写队列或获取队列信息接口的队列ID大于等于系统支持的最大队列数 确保队列ID有效 16 LOS_ERRNO_QUEUE_READ_PTR_NULL 0x0200060f 传递给读队列接口的指针为空 确保传入的参数不为空指针 17 LOS_ERRNO_QUEUE_READSIZE_IS_INVALID 0x02000610 传递给读队列接口的缓冲区大小为0或者大于0xFFFB 传入的一个正确的缓冲区大小需要大于0且小于0xFFFC 18 LOS_ERRNO_QUEUE_WRITE_PTR_NULL 0x02000612 传递给写队列接口的缓冲区指针为空 确保传入的参数不为空指针 19 LOS_ERRNO_QUEUE_WRITESIZE_ISZERO 0x02000613 传递给写队列接口的缓冲区大小为0 传入正确的缓冲区大小 20 LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG 0x02000615 传递给写队列接口的缓冲区大小比队列的消息节点大小要大 减小缓冲区大小,或增大队列的消息节点大小 21 LOS_ERRNO_QUEUE_ISFULL 0x02000616 写队列时没有可用的空闲节点 写队列之前,确保在队列中存在可用的空闲节点,或者使用阻塞模式写队列,即设置大于0的写队列超时时间 22 LOS_ERRNO_QUEUE_PTR_NULL 0x02000617 传递给获取队列信息接口的指针为空 确保传入的参数不为空指针 23 LOS_ERRNO_QUEUE_READ_IN_INTERRUPT 0x02000618 在中断处理程序中不能以阻塞模式读队列 将读队列设为非阻塞模式,即将读队列的超时时间设置为0 24 LOS_ERRNO_QUEUE_MAIL_HANDLE_INVALID 0x02000619 CMSIS-RTOS 1.0中的mail队列,释放内存块时,发现传入的mail队列ID无效 确保传入的mail队列ID是正确的 25 LOS_ERRNO_QUEUE_MAIL_PTR_INVALID 0x0200061a CMSIS-RTOS 1.0中的mail队列,释放内存块时,发现传入的mail内存池指针为空 传入非空的mail内存池指针 26 LOS_ERRNO_QUEUE_MAIL_FREE_ERROR 0x0200061b CMSIS-RTOS 1.0中的mail队列,释放内存块失败 传入非空的mail队列内存块指针 27 LOS_ERRNO_QUEUE_ISEMPTY 0x0200061d 队列已空 读队列之前,确保队列中存在未读的消息,或者使用阻塞模式读队列,即设置大于0的读队列超时时间 28 LOS_ERRNO_QUEUE_READ_SIZE_TOO_SMALL 0x0200061f 传递给读队列接口的读缓冲区大小小于队列消息节点大小 增加缓冲区大小,或减小队列消息节点大小 错误码定义见错误码简介。8~15位的所属模块为队列模块,值为0x06。 队列模块中的错误码序号0x11、0x14未被定义,不可用。
  • 编程示例 前提条件:在menuconfig菜单中完成任务模块的配置和SMP模式使能。 UINT32 g_taskLoId;UINT32 g_taskHiId;#define TSK_PRIOR_HI 4#define TSK_PRIOR_LO 5UINT32 Example_TaskHi(VOID){ UINT32 ret; printf("[cpu%d] Enter TaskHi Handler.\r\n", ArchCurrCpuid()); /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(g_taskLoId任务) */ ret = LOS_TaskDelay(2); if (ret != LOS_OK) { printf("Delay Task Failed.\r\n"); return LOS_NOK; } /* 2个Tick后,该任务恢复,继续执行 */ printf("TaskHi LOS_TaskDelay Done.\r\n"); /* 挂起自身任务 */ ret = LOS_TaskSuspend(g_taskHiId); if (ret != LOS_OK) { printf("Suspend TaskHi Failed.\r\n"); return LOS_NOK; } printf("TaskHi LOS_TaskResume Success.\r\n"); return ret;}/* 低优先级任务入口函数 */UINT32 Example_TaskLo(VOID){ UINT32 ret; printf("[cpu%d] Enter TaskLo Handler.\r\n", ArchCurrCpuid()); /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中就高优先级的任务(背景任务) */ ret = LOS_TaskDelay(2); if (ret != LOS_OK) { printf("Delay TaskLo Failed.\r\n"); return LOS_NOK; } printf("TaskHi LOS_TaskDelete Success.\r\n"); return ret;}/* 任务测试入口函数,创建两个不同优先级的任务 */UINT32 Example_TskCaseEntry(VOID){ UINT32 ret; TSK_INIT_PARAM_S initParam = {0}; /* 锁任务调度 */ LOS_TaskLock(); printf("LOS_TaskLock() Success on cpu%d!\r\n", ArchCurrCpuid()); initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi; initParam.usTaskPrio = TSK_PRIOR_HI; initParam.pcName = "TaskHi"; initParam.uwStackSize = LOSCFG_TASK_MIN_STACK_SIZE; initParam.uwResved = LOS_TASK_STATUS_DETACHED;#ifdef LOSCFG_KERNEL_SMP /* 绑定高优先级任务到CPU1运行 */ initParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());#endif /* 创建高优先级任务,由于CPU1的调度器被锁,任务创建成功后不会马上执行 */ ret = LOS_TaskCreate(&g_taskHiId, &initParam); if (ret != LOS_OK) { LOS_TaskUnlock(); printf("Example_TaskHi create Failed!\r\n"); return LOS_NOK; } printf("Example_TaskHi create Success!\r\n"); initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo; initParam.usTaskPrio = TSK_PRIOR_LO; initParam.pcName = "TaskLo"; initParam.uwStackSize = LOSCFG_TASK_MIN_STACK_SIZE; initParam.uwResved = LOS_TASK_STATUS_DETACHED;#ifdef LOSCFG_KERNEL_SMP /* 低优先级任务不设置CPU亲和性 */ initParam.usCpuAffiMask = 0;#endif /* 创建低优先级任务,尽管锁任务调度,但是由于该任务没有绑定该处理器,任务创建成功后可以马上在其他CPU执行 */ ret = LOS_TaskCreate(&g_taskLoId, &initParam); if (ret != LOS_OK) { LOS_TaskUnlock(); printf("Example_TaskLo create Failed!\r\n"); return LOS_NOK; } printf("Example_TaskLo create Success!\r\n"); /* 解锁任务调度,此时会发生任务调度,执行就绪列表中最高优先级任务 */ LOS_TaskUnlock(); return LOS_OK;}
  • 结果验证 编译运行得到的结果为: LOS_TaskLock() success on cpu1!Example_TaskHi create Success!Example_TaskLo create Success![cpu2] Enter TaskLo Handler.[cpu1] Enter TaskHi Handler.TaskHi LOS_TaskDelete Success.TaskHi LOS_TaskDelay Done.
  • 功能 Huawei LiteOS的时间管理提供下面几种功能,接口详细信息可以查看API参考。 功能分类 接口名 描述 时间转换 LOS_MS2Tick 毫秒转换成Tick LOS_Tick2MS Tick转化为毫秒 时间统计 LOS_CyclePerTickGet 每个Tick多少Cycle数 LOS_TickCountGet 获取自系统启动以来的Tick数 LOS_GetCpuCycle 获取自系统启动以来的Cycle数 LOS_CurrNanosec 获取自系统启动以来的纳秒数 延时管理 LOS_Udelay 以us为单位的忙等,但可以被优先级更高的任务抢占 LOS_Mdelay 以ms为单位的忙等,但可以被优先级更高的任务抢占
  • 时间管理错误码 时间转换存在出错的可能性,需要返回对应的错误码,以便快速定位错误原因。 序号 定义 实际数值 描述 参考解决方案 1 LOS_ERRNO_TICK_CFG_INVALID 0x02000400 无效的系统Tick配置 在板级配置适配时配置有效的系统主时钟频率OS_SYS_CLOCK,通过make menuconfig配置有效的LOSCFG_BASE_CORE_TICK_PER_SECOND 2 LOS_ERRNO_TICK_NO_HWTIMER 0x02000401 暂不使用该错误码 - 3 LOS_ERRNO_TICK_PER_SEC_TOO_SMALL 0x02000402 暂不使用该错误码 -
  • 编程示例 代码实现如下: #include "stdio.h"#include "los_list.h"#ifdef __cplusplus#if __cplusplusextern "C" {#endif /* __cpluscplus */#endif /* __cpluscplus */static UINT32 DLlist_sample(VOID){ LOS_DL_LIST DLlist = {NULL,NULL}; LOS_DL_LIST DLlistNode01 = {NULL,NULL}; LOS_DL_LIST DLlistNode02 = {NULL,NULL}; LOS_DL_LIST DLlistNode03 = {NULL,NULL}; dprintf("Initial head\n"); LOS_ListInit(&DLlist); LOS_ListAdd(&DLlist, &DLlistNode01); if (DLlistNode01.pstNext == &DLlist && DLlistNode01.pstPrev == &DLlist) { dprintf("Add DLlistNode01 success \n"); } LOS_ListTailInsert(&DLlist, &DLlistNode02); if (DLlistNode02.pstNext == &DLlist && DLlistNode02.pstPrev == &DLlistNode01) { dprintf("Tail insert DLlistNode02 success \n"); } LOS_ListHeadInsert(&DLlistNode02, &DLlistNode03); if (DLlistNode03.pstNext == &DLlist && DLlistNode03.pstPrev == &DLlistNode02) { dprintf("Head insert DLlistNode03 success \n"); } LOS_ListDelInit(&DLlistNode03); LOS_ListDelete(&DLlistNode01); LOS_ListDelete(&DLlistNode02); if (LOS_ListEmpty(&DLlist)) { dprintf("Delete success \n"); } return LOS_OK;}#ifdef __cplusplus#if __cplusplus}#endif /* __cpluscplus */#endif /* __cpluscplus */
  • 功能 Huawei LiteOS的位操作模块为用户提供下面几种功能,接口详细信息可以查看API参考。 功能分类 接口名 描述 置1/清0标志位 LOS_BitmapSet 对状态字的某一标志位进行置1操作 LOS_BitmapClr 对状态字的某一标志位进行清0操作 获取标志位为1的bit位 LOS_HighBitGet 获取状态字中为1的最高位 LOS_LowBitGet 获取状态字中为1的最低位
  • 注意事项 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。 队列接口函数中的入参timeout是相对时间。 LOS_QueueReadCopy和LOS_QueueWriteCopy及LOS_QueueWriteHeadCopy是一组接口,LOS_QueueRead和LOS_QueueWrite及LOS_QueueWriteHead是一组接口,两组接口需要配套使用。 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 当队列使用结束后,如果存在动态申请的内存,需要及时释放这些内存。 父主题: 队列
共99492条