发布于2021-07-24 20:46 阅读(892) 评论(0) 点赞(28) 收藏(4)
近期在阅读鸿蒙liteOS_a,由于是初次探索内核的奥秘。将一些阅读的心得进行分享。希望能在作为笔记的同时,也能帮助更多人学习。
感谢图灵大佬的注释项目,使我能够更加快速的理解。
https://weharmony.github.io/
核心模块位于:kernel -> base -> core
其中包括:
los_bitmap.c 用于位操作,改变标志位。
los_process.c 用于控制并发、并行、单核多进程、多核多线程的管理
los_sortlik.c 用于排序
los_swtmr.c 用于定时器
los_sys.c 用于时间管理,转换秒与毫秒,了解当前系统运行时间
los_task.c 用于任务状态管理,一个任务代表一个线程,管理其运行状态。
los_tick.c 用于系统时钟、节拍器。
系统定时器个人理解为用来控制系统中断或者定时触发回调函数。
定时器分为三种状态:
1、 OS_SWTMR_STATUS_UNUSED(定时器未使用)
系统在定时器模块初始化时,会将系统中所有定时器资源初始化成该状态。
2、 OS_SWTMR_STATUS_TICKING(定时器处于计数状态)
在定时器创建后调用LOS_SwtmrStart接口启动,定时器将变成该状态,是定时器运行时的状态。
3、 OS_SWTMR_STATUS_CREATED(定时器创建后未启动,或已停止)
定时器创建后,不处于计数状态时,定时器将变成该状态。
软件定时器提供三种模式:
1、单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动删除。
2、周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动停止定时器,否则将永远持续执行下去。
3、单次触发定时器,但这类定时器超时触发后不会自动删除,需要调用定时器删除接口删除定时器。
LITE_OS_SEC_BSS SWTMR_CTRL_S *g_swtmrCBArray = NULL;
/*
swtmr = software timer 软件定时器。
CBArray是阵列。
合起来叫做:定时器池。
*/
LITE_OS_SEC_BSS UINT8 *g_swtmrHandlerPool = NULL;
/*
赋值上软时钟的回调函数,软时钟结束会调用它。
*/
LITE_OS_SEC_BSS LOS_DL_LIST g_swtmrFreeList;
/*
LOS_DL_LIST 这是双向链表,主要使用承上启下。
定时器通常至少要包含两个成员:一个超时时间(相对时间或者绝对时间)和一个任务回调函数。
有的时候还可能包含回调函数被执行时需要传入的参数,以及是否重启定时器等信息。
链表是双向的,则每个定时器包含指向前一个定时器的指针成员。(有点像某区块链)
*/
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_swtmrSpin);
/*
初始化软时钟自旋锁,只有SMP情况才需要,只要是自旋锁都是用于CPU多核的同步。
自旋锁是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
我简单理解自旋锁为控制多处理器并发,控制竞争。
*/
#define SWTMR_LOCK(state) LOS_SpinLockSave(&g_swtmrSpin, &(state))
/*
持有软时钟自旋锁
这里定义个SWTMR_LOCK常量,用于锁定软时钟的自旋锁。
*/
#define SWTMR_UNLOCK(state) LOS_SpinUnlockRestore(&g_swtmrSpin, (state))
/*
释放软时钟自旋锁
这里定义个SWTMR_LOCK常量,用于解除锁定软时钟的自旋锁。
*/
LITE_OS_SEC_TEXT VOID OsSwtmrTask(VOID)
/*
函数作为软时钟的入口。
*/
{
SwtmrHandlerItemPtr swtmrHandlePtr = NULL;
/*
在kernel/base/include/los_swtmr_pri.h
typedef SwtmrHandlerItem *SwtmrHandlerItemPtr;
指向处理软件计时器超时的回调函数结构的指针的类型。
个人理解用于定位。
*/
SwtmrHandlerItem swtmrHandle;
/*
SwtmrHandlerItem是定时器响应函数。
*/
UINT32 ret, swtmrHandlerQueue;
/*
swtmrHandlerQueue是定时器处理队列。
*/
swtmrHandlerQueue = OsPercpuGet()->swtmrHandlerQueue;
/*
OsPercpuGet 获取CPU GET之中的定时器超时队列。
*/
for (;;) {
// 死循环获取队列item,一直读干净为止 遍历队列!
ret = LOS_QueueRead(swtmrHandlerQueue, &swtmrHandlePtr, sizeof(CHAR *), LOS_WAIT_FOREVER);
// 一个一个读队列
if ((ret == LOS_OK) && (swtmrHandlePtr != NULL)) {
/*
判断队列未 LOS_OK,以及定位指针被移动不为初始值NULL。
主要判断队列是否为空和是否完成。
*/
swtmrHandle.handler = swtmrHandlePtr->handler;
//超时中断处理函数,也称回调函数
swtmrHandle.arg = swtmrHandlePtr->arg;
//回调函数的参数
(VOID)LOS_MemboxFree(g_swtmrHandlerPool, swtmrHandlePtr);
//静态释放内存,注意在鸿蒙内核只有软时钟注册用到了静态内存
if (swtmrHandle.handler != NULL) {
// 确认回调函数存在,然后执行回调函数。
swtmrHandle.handler(swtmrHandle.arg);
// 回调函数处理函数
}
}
}
}
//创建软时钟任务,每个cpu core都可以拥有自己的软时钟任务
LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrTaskCreate(VOID)
{
UINT32 ret, swtmrTaskID;
TSK_INIT_PARAM_S swtmrTask;
UINT32 cpuid = ArchCurrCpuid();//获取当前CPU id
/*
创建变量 ret 和 swtmrTaskID 以及swtmrTask,之后获取当前CPU ID。
操作和当前执行的CPU有关系。
*/
(VOID)memset_s(&swtmrTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));//清0
/*
memset_s为初始化函数。
*/
swtmrTask.pfnTaskEntry = (TSK_ENTRY_FUNC)OsSwtmrTask;//入口函数
swtmrTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;//16K默认内核任务栈
swtmrTask.pcName = "Swt_Task";//任务名称
swtmrTask.usTaskPrio = 0;//哇塞! 逮到一个最高优先级的任务 @note_thinking 这里应该用 OS_TASK_PRIORITY_HIGHEST 表示
swtmrTask.uwResved = LOS_TASK_STATUS_DETACHED;//分离模式
/*
首先获取入口函数,然后LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE获取默认任务栈的大小,紧接着指定任务名称,设置任务优先级为0(最高优先级),LOS_TASK_STATUS_DETACHED设置任务为自删除状态。
*/
#if (LOSCFG_KERNEL_SMP == YES)
swtmrTask.usCpuAffiMask = CPUID_TO_AFFI_MASK(cpuid);//交给当前CPU执行这个任务
#endif
ret = LOS_TaskCreate(&swtmrTaskID, &swtmrTask);//创建任务并申请调度
if (ret == LOS_OK) {
g_percpu[cpuid].swtmrTaskID = swtmrTaskID;//全局变量记录 软时钟任务ID
OS_TCB_FROM_TID(swtmrTaskID)->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK;//告知这是一个系统任务
}
/*
调度软时钟任务,执行、申请、记录等几个方面。
*/
return ret;
}
//回收指定进程的软时钟
LITE_OS_SEC_TEXT_INIT VOID OsSwtmrRecycle(UINT32 processID)
{
for (UINT16 index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++) {//一个进程往往会有多个定时器
if (g_swtmrCBArray[index].uwOwnerPid == processID) {//找到一个
LOS_SwtmrDelete(index);//删除定时器
}
}
/*
删除某进程的软时钟,传入进程ID,然后利用进程ID遍历数组。
*/
}
//软时钟初始化 ,注意函数在多CPU情况下会执行多次
LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrInit(VOID)
{
UINT32 size;
UINT16 index;
UINT32 ret;
SWTMR_CTRL_S *swtmr = NULL;
UINT32 swtmrHandlePoolSize;
UINT32 cpuid = ArchCurrCpuid();
/*
软时钟初始化变量
size 大小
index 索引
ret 中转变量(应该是临时变量)
*swtmr 用于定位
swtmrHandlePoolSize 时钟句柄池大小
ArchCurrCpuid 当前CUPID
*/
if (cpuid == 0) {//确保以下代码块由一个CPU执行,g_swtmrCBArray和g_swtmrHandlerPool 是所有CPU共用的
size = sizeof(SWTMR_CTRL_S) * LOSCFG_BASE_CORE_SWTMR_LIMIT;//申请软时钟内存大小
swtmr = (SWTMR_CTRL_S *)LOS_MemAlloc(m_aucSysMem0, size); /* system resident resource */ //常驻内存
if (swtmr == NULL) {
ret = LOS_ERRNO_SWTMR_NO_MEMORY;
goto ERROR;
}
/*
在申请软时钟之后判断时钟是否结束,如果结束则抛出异常。
*/
(VOID)memset_s(swtmr, size, 0, size);//清0
g_swtmrCBArray = swtmr;//软时钟
LOS_ListInit(&g_swtmrFreeList);//初始化空闲链表
/*
上篇文章有笔记,时钟是链表。
*/
for (index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr++) {
swtmr->usTimerID = index;//按顺序赋值
LOS_ListTailInsert(&g_swtmrFreeList, &swtmr->stSortList.sortLinkNode);//通过sortLinkNode将节点挂到空闲链表
}
/*
将所有的软时钟挂在链表之上,可能是方便执行吧。
*/
//想要用静态内存池管理,就必须要使用LOS_MEMBOX_SIZE来计算申请的内存大小,因为需要点前缀内存承载头部信息.
swtmrHandlePoolSize = LOS_MEMBOX_SIZE(sizeof(SwtmrHandlerItem), OS_SWTMR_HANDLE_QUEUE_SIZE);//计算所有注册函数内存大小
//规划一片内存区域作为软时钟处理函数的静态内存池。
g_swtmrHandlerPool = (UINT8 *)LOS_MemAlloc(m_aucSysMem1, swtmrHandlePoolSize); /* system resident resource *///常驻内存
if (g_swtmrHandlerPool == NULL) {
ret = LOS_ERRNO_SWTMR_NO_MEMORY;
goto ERROR;
}
/*
通过计算所需内存大小,然后申请内存大小,最后常驻内存。紧接着判断g_swtmrHandlerPool是否存在如果不存在则抛出异常。
*/
ret = LOS_MemboxInit(g_swtmrHandlerPool, swtmrHandlePoolSize, sizeof(SwtmrHandlerItem));//初始化软时钟注册池
if (ret != LOS_OK) {
ret = LOS_ERRNO_SWTMR_HANDLER_POOL_NO_MEM;
goto ERROR;
}
ret = OsSchedSwtmrScanRegister((SchedScan)OsSwtmrScan);
if (ret != LOS_OK) {
goto ERROR;
}
/*
LOS_MemboxInit进行静态内存初始化。返回值ret,先判断初始化是否成功,然后再执行注册扫描并且判断是否成功。
*/
}
//每个CPU都会创建一个属于自己的 OS_SWTMR_HANDLE_QUEUE_SIZE 的队列
ret = LOS_QueueCreate(NULL, OS_SWTMR_HANDLE_QUEUE_SIZE, &g_percpu[cpuid].swtmrHandlerQueue, 0, sizeof(CHAR *));//为当前CPU core 创建软时钟队列 maxMsgSize:sizeof(CHAR *)
if (ret != LOS_OK) {
ret = LOS_ERRNO_SWTMR_QUEUE_CREATE_FAILED;
goto ERROR;
}
/*
创建当前CPU的时钟队列,以及异常判断。
*/
ret = OsSwtmrTaskCreate();//每个CPU独自创建属于自己的软时钟任务,统一处理队列
if (ret != LOS_OK) {
ret = LOS_ERRNO_SWTMR_TASK_CREATE_FAILED;
goto ERROR;
}
ret = OsSortLinkInit(&g_percpu[cpuid].swtmrSortLink);//每个CPU独自对自己软时钟链表排序初始化,为啥要排序因为每个定时器的时间不一样,鸿蒙把用时短的排在前面
if (ret != LOS_OK) {
ret = LOS_ERRNO_SWTMR_SORTLINK_CREATE_FAILED;
goto ERROR;
}
return LOS_OK;
ERROR:
PRINT_ERR("OsSwtmrInit error! ret = %u\n", ret);
return ret;
}
/*
* Description: Start Software Timer
* Input : swtmr --- Need to start software timer
*/ //开始定时器
LITE_OS_SEC_TEXT VOID OsSwtmrStart(SWTMR_CTRL_S *swtmr)
{
UINT32 ticks;
UINT64 currTime = OsGerCurrSchedTimeCycle();
/*
ticks 用于计时器存储
OsGerCurrSchedTimeCycle 获取调度经过多少周期
*/
if ((swtmr->uwOverrun == 0) && ((swtmr->ucMode == LOS_SWTMR_MODE_ONCE) ||
(swtmr->ucMode == LOS_SWTMR_MODE_OPP) ||
(swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE))) {
ticks = swtmr->uwExpiry;
} else {
ticks = swtmr->uwInterval;
}
/*
在if里面条件情况下 计时器进行存储。
*/
swtmr->ucState = OS_SWTMR_STATUS_TICKING;
OsAdd2SortLink(&swtmr->stSortList, currTime, ticks, OS_SORT_LINK_SWTMR);
if (OS_SCHEDULER_ACTIVE) {
OsSchedUpdateExpireTime(currTime);
}
/*
OsAdd2SortLink排序链表插入
*/
return;
}
/*
* Description: Delete Software Timer
* Input : swtmr --- Need to delete software timer, When using, Ensure that it can't be NULL.
*/
STATIC INLINE VOID OsSwtmrDelete(SWTMR_CTRL_S *swtmr)
{
/* insert to free list */
LOS_ListTailInsert(&g_swtmrFreeList, &swtmr->stSortList.sortLinkNode);//直接插入空闲链表中,回收再利用
swtmr->ucState = OS_SWTMR_STATUS_UNUSED;//又干净着呢
swtmr->uwOwnerPid = 0;//谁拥有这个定时器? 是 0号进程, 0号进程出来了,竟然是虚拟的一个进程.用于这类缓冲使用.
}
STATIC INLINE VOID OsWakePendTimeSwtmr(Percpu *cpu, SWTMR_CTRL_S *swtmr)
{
LOS_SpinLock(&g_swtmrSpin);
SwtmrHandlerItemPtr swtmrHandler = (SwtmrHandlerItemPtr)LOS_MemboxAlloc(g_swtmrHandlerPool);
if (swtmrHandler != NULL) {
swtmrHandler->handler = swtmr->pfnHandler;
swtmrHandler->arg = swtmr->uwArg;
if (LOS_QueueWrite(cpu->swtmrHandlerQueue, swtmrHandler, sizeof(CHAR *), LOS_NO_WAIT)) {
(VOID)LOS_MemboxFree(g_swtmrHandlerPool, swtmrHandler);
}
}
/*
自旋锁控制
*/
if (swtmr->ucMode == LOS_SWTMR_MODE_ONCE) {
OsSwtmrDelete(swtmr);
if (swtmr->usTimerID < (OS_SWTMR_MAX_TIMERID - LOSCFG_BASE_CORE_SWTMR_LIMIT)) {
swtmr->usTimerID += LOSCFG_BASE_CORE_SWTMR_LIMIT;
} else {
swtmr->usTimerID %= LOSCFG_BASE_CORE_SWTMR_LIMIT;
}
} else if (swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE) {
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
} else {
swtmr->uwOverrun++;
OsSwtmrStart(swtmr);
}
LOS_SpinUnlock(&g_swtmrSpin);
}
/*
* Description: Tick interrupt interface module of software timer
* Return : LOS_OK on success or error code on failure
*///OsSwtmrScan 由系统时钟中断处理函数调用
LITE_OS_SEC_TEXT VOID OsSwtmrScan(VOID)//扫描定时器,如果碰到超时的,就放入超时队
{
Percpu *cpu = OsPercpuGet();
SortLinkAttribute* swtmrSortLink = &OsPercpuGet()->swtmrSortLink;
LOS_DL_LIST *listObject = &swtmrSortLink->sortLink;
/*
OsPercpuGet 用来获取当前CPU信息
swtmrSortLink CPU需要处理的定时器链表
*listObject 指向其链表位置
*/
/*
* it needs to be carefully coped with, since the swtmr is in specific sortlink
* while other cores still has the chance to process it, like stop the timer.
*/
LOS_SpinLock(&cpu->swtmrSortLinkSpin);
if (LOS_ListEmpty(listObject)) {
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
return;
}
/*
LOS_SpinLock和LOS_SpinUnlock是自旋锁控制
*/
SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
/*
LOS_DL_LIST_ENTRY获取双向链表节点所在的业务结构体的内存地址。
*/
UINT64 currTime = OsGerCurrSchedTimeCycle();
while (sortList->responseTime <= currTime) {
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
OsDeleteNodeSortLink(swtmrSortLink, sortList);
SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
/*
自旋锁控制。
*/
OsWakePendTimeSwtmr(cpu, swtmr);
LOS_SpinLock(&cpu->swtmrSortLinkSpin);
if (LOS_ListEmpty(listObject)) {
break;
}
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
/*
创建链表
*/
}
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
/*
currTime 获得当前的时间周期
循环中判断如果响应时间小于当前的时间周期,然后获取全部双向链表LOS_DL_LIST_ENTRY,删除节点OsDeleteNodeSortLink。
*/
}
/*
* Description: Get next timeout
* Return : Count of the Timer list
*/
LITE_OS_SEC_TEXT UINT32 OsSwtmrGetNextTimeout(VOID)//获取下一个timeout
{
return OsSortLinkGetNextExpireTime(&OsPercpuGet()->swtmrSortLink);
}
/*
* Description: Stop of Software Timer interface
* Input : swtmr --- the software timer contrl handler
*/
LITE_OS_SEC_TEXT STATIC VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr)
{
OsDeleteSortLink(&swtmr->stSortList, OS_SORT_LINK_SWTMR);
/*
删除节点的链接。
*/
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
swtmr->uwOverrun = 0;
if (OS_SCHEDULER_ACTIVE) {
OsSchedUpdateExpireTime(OsGerCurrSchedTimeCycle());
/*
更新过期时间。
*/
}
}
/*
* Description: Get next software timer expiretime
* Input : swtmr --- the software timer contrl handler
*/
LITE_OS_SEC_TEXT STATIC UINT32 OsSwtmrTimeGet(const SWTMR_CTRL_S *swtmr)
{
return OsSortLinkGetTargetExpireTime(&swtmr->stSortList);
}
//创建定时器,设置定时器的定时时长、定时器模式、回调函数,并返回定时器ID
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval,
UINT8 mode,
SWTMR_PROC_FUNC handler,
UINT16 *swtmrID,
UINTPTR arg)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
SortLinkList *sortList = NULL;
if (interval == 0) {
return LOS_ERRNO_SWTMR_INTERVAL_NOT_SUITED;
/*
软件定时器回调函数。
*/
}
if ((mode != LOS_SWTMR_MODE_ONCE) && (mode != LOS_SWTMR_MODE_PERIOD) &&
/*
好像是判断单次时钟和周期时钟
*/
(mode != LOS_SWTMR_MODE_NO_SELFDELETE)) {
return LOS_ERRNO_SWTMR_MODE_INVALID;
}
if (handler == NULL) {
return LOS_ERRNO_SWTMR_PTR_NULL;
/*
软件时钟回调函数为空。
*/
}
if (swtmrID == NULL) {
return LOS_ERRNO_SWTMR_RET_PTR_NULL;
/*
入参的软件定时器ID指针为NULL。
*/
}
SWTMR_LOCK(intSave);
if (LOS_ListEmpty(&g_swtmrFreeList)) {//空闲链表不能为空
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_MAXSIZE;
/*
软件定时器个数超过最大值
*/
}
sortList = LOS_DL_LIST_ENTRY(g_swtmrFreeList.pstNext, SortLinkList, sortLinkNode);
swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
LOS_ListDelete(LOS_DL_LIST_FIRST(&g_swtmrFreeList));
/*删除指定节点*/
SWTMR_UNLOCK(intSave);
swtmr->uwOwnerPid = OsCurrProcessGet()->processID;//定时器进程归属设定
swtmr->pfnHandler = handler;//时间到了的回调函数
swtmr->ucMode = mode; //定时器模式
swtmr->uwOverrun = 0;
swtmr->uwInterval = interval; //周期性超时间隔
swtmr->uwExpiry = interval; //一次性超时间隔
swtmr->uwArg = arg; //回调函数的参数
swtmr->ucState = OS_SWTMR_STATUS_CREATED; //已创建状态
SET_SORTLIST_VALUE(&swtmr->stSortList, OS_SORT_LINK_INVALID_TIME);
*swtmrID = swtmr->usTimerID;
return LOS_OK;
}
//接口函数 启动定时器 参数定时任务ID
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT16 swtmrID)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
UINT32 ret = LOS_OK;
UINT16 swtmrCBID;
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return LOS_ERRNO_SWTMR_ID_INVALID; /*入参的软件定时器ID不正确*/
}
swtmrCBID = swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;//取模
swtmr = g_swtmrCBArray + swtmrCBID;//获取定时器控制结构体
SWTMR_LOCK(intSave);
if (swtmr->usTimerID != swtmrID) {//ID必须一样
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_ID_INVALID;
}
switch (swtmr->ucState) {//判断定时器状态
case OS_SWTMR_STATUS_UNUSED:
ret = LOS_ERRNO_SWTMR_NOT_CREATED;
break;
/* 如果定时器的状态为启动中,应先停止定时器再重新启动
* If the status of swtmr is timing, it should stop the swtmr first,
* then start the swtmr again.
*/
case OS_SWTMR_STATUS_TICKING://正在计数的定时器
OsSwtmrStop(swtmr);//先停止定时器,注意这里没有break;,在OsSwtmrStop中状态将会回到了OS_SWTMR_STATUS_CREATED 接下来就是执行启动了
/* fall-through */
case OS_SWTMR_STATUS_CREATED://已经创建好了
OsSwtmrStart(swtmr);//启动定时器
break;
default:
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
break;
}
SWTMR_UNLOCK(intSave);
return ret;
}
//接口函数 停止定时器 参数定时任务ID
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStop(UINT16 swtmrID)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
UINT32 ret = LOS_OK;
UINT16 swtmrCBID;
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return LOS_ERRNO_SWTMR_ID_INVALID;
/*
判断编号如果到达或者超多最大值,然后返回传入参数失败。 后面的方式和前面的相差不大。
*/
}
swtmrCBID = swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;//取模
swtmr = g_swtmrCBArray + swtmrCBID;//获取定时器控制结构体
SWTMR_LOCK(intSave);
if (swtmr->usTimerID != swtmrID) {//ID必须一样
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_ID_INVALID;
}
switch (swtmr->ucState) {//判断定时器状态
case OS_SWTMR_STATUS_UNUSED:
ret = LOS_ERRNO_SWTMR_NOT_CREATED;//返回没有创建
break;
case OS_SWTMR_STATUS_CREATED:
ret = LOS_ERRNO_SWTMR_NOT_STARTED;//返回没有开始
break;
case OS_SWTMR_STATUS_TICKING://正在计数
OsSwtmrStop(swtmr);//执行正在停止定时器操作
break;
default:
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
break;
}
SWTMR_UNLOCK(intSave);
return ret;
}
//接口函数 获得软件定时器剩余Tick数 通过 *tick 带走
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrTimeGet(UINT16 swtmrID, UINT32 *tick)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
UINT32 ret = LOS_OK;
UINT16 swtmrCBID;
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return LOS_ERRNO_SWTMR_ID_INVALID;
}
if (tick == NULL) {
return LOS_ERRNO_SWTMR_TICK_PTR_NULL;
}
swtmrCBID = swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;//取模
swtmr = g_swtmrCBArray + swtmrCBID;//获取定时器控制结构体
SWTMR_LOCK(intSave);
if (swtmr->usTimerID != swtmrID) {//ID必须一样
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_ID_INVALID;
}
switch (swtmr->ucState) {
case OS_SWTMR_STATUS_UNUSED:
ret = LOS_ERRNO_SWTMR_NOT_CREATED;
break;
case OS_SWTMR_STATUS_CREATED:
ret = LOS_ERRNO_SWTMR_NOT_STARTED;
break;
case OS_SWTMR_STATUS_TICKING://正在计数的定时器
*tick = OsSwtmrTimeGet(swtmr);//获取
break;
default:
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
break;
}
SWTMR_UNLOCK(intSave);
return ret;
}
//接口函数 删除定时器
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrDelete(UINT16 swtmrID)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
UINT32 ret = LOS_OK;
UINT16 swtmrCBID;
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return LOS_ERRNO_SWTMR_ID_INVALID;
}
swtmrCBID = swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;//取模
swtmr = g_swtmrCBArray + swtmrCBID;//获取定时器控制结构体
SWTMR_LOCK(intSave);
if (swtmr->usTimerID != swtmrID) {//ID必须一样
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_ID_INVALID;
}
switch (swtmr->ucState) {
case OS_SWTMR_STATUS_UNUSED:
ret = LOS_ERRNO_SWTMR_NOT_CREATED;
break;
case OS_SWTMR_STATUS_TICKING://正在计数就先停止再删除,这里没有break;
OsSwtmrStop(swtmr);
/* fall-through */
case OS_SWTMR_STATUS_CREATED://再删除定时器
OsSwtmrDelete(swtmr);
break;
default:
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
break;
}
SWTMR_UNLOCK(intSave);
return ret;
}
#endif /* (LOSCFG_BASE_CORE_SWTMR == YES) */
原文链接:https://blog.csdn.net/qq_35476650/article/details/118185244
作者:天使是怎样炼成的
链接:http://www.pythonpdf.com/blog/article/397/dc73209a056696bd21e9/
来源:编程知识网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!