liteos中sem的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tiantao2012/article/details/86651426
sem就是信号量,其使用如下所示:
在使用sem之前先要创建sem
LOS_SemCreate(0, &g_usSemID);
创建后,就可以调用LOS_SemPend 来得到一个信号量,调用LOS_SemPost 释放一个信号量

static VOID Example_SemTask1(VOID)
{
    UINT32 uwRet;

    dprintf("Example_SemTask1 try get sem g_usSemID ,timeout 10 ticks.\n");
    /* get sem, timeout is 10 ticks */
#获取信号量
    uwRet = LOS_SemPend(g_usSemID, 10);

    /* get sem ok */
    if (LOS_OK == uwRet)
    {
#成功获取后释放信号量
        LOS_SemPost(g_usSemID);
        return;
    }
}
下来我们具体看看如何获取信号量
LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 uwSemHandle, UINT32 uwTimeout)
{
    UINT32      uwIntSave;
    SEM_CB_S    *pstSemPended;
    UINT32      uwRetErr;
    LOS_TASK_CB *pstRunTsk;

    pstSemPended = GET_SEM(uwSemHandle);
  #得到正在运行的task
    pstRunTsk = (LOS_TASK_CB *)g_stLosTask.pstRunTask;
#将要得到的信号量赋值给当前进程
    pstRunTsk->pTaskSem = (VOID *)pstSemPended;
#将这个进程插入到pendlist中,并建立一个timer来唤醒这个进程得到信号量
    osTaskWait(&pstSemPended->stSemList, OS_TASK_STATUS_PEND, uwTimeout);
    (VOID)LOS_IntRestore(uwIntSave);
#释放cpu
    LOS_Schedule();

    if (pstRunTsk->usTaskStatus & OS_TASK_STATUS_TIMEOUT)
    {
        uwIntSave = LOS_IntLock();
        pstRunTsk->usTaskStatus &= (~OS_TASK_STATUS_TIMEOUT);
        uwRetErr = LOS_ERRNO_SEM_TIMEOUT;
        goto errre_uniSemPend;
    }
#规定的时间内信号量被唤醒,没有timeout则返回成功
    return LOS_OK;
#否则返回失败,获取信号量失败
errre_uniSemPend:
    (VOID)LOS_IntRestore(uwIntSave);
    OS_RETURN_ERROR(uwRetErr);
}

LITE_OS_SEC_TEXT VOID osTaskWait(LOS_DL_LIST *pstList, UINT32 uwTaskStatus, UINT32 uwTimeOut)
{
    LOS_TASK_CB *pstRunTsk;
    LOS_DL_LIST *pstPendObj;

    pstRunTsk = g_stLosTask.pstRunTask;
    osPriqueueDequeue(&pstRunTsk->stPendList);
    pstRunTsk->usTaskStatus &= (~OS_TASK_STATUS_READY);
    pstPendObj = &pstRunTsk->stPendList;
    pstRunTsk->usTaskStatus |= uwTaskStatus;
#将这个进程插入到pendlist中
    LOS_ListTailInsert(pstList,pstPendObj);
    if (uwTimeOut != LOS_WAIT_FOREVER)
    {
        pstRunTsk->usTaskStatus |= OS_TASK_STATUS_TIMEOUT;
#建立一个timer在规定时间内唤醒这个进程
        osTaskAdd2TimerList((LOS_TASK_CB *)pstRunTsk, uwTimeOut);
    }
}
释放信号量的函数分析如下:

LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 uwSemHandle)
{
    UINT32      uwIntSave;
    SEM_CB_S    *pstSemPosted = GET_SEM(uwSemHandle);
    LOS_TASK_CB *pstResumedTask;
#需要释放的信号量不为null的话
     if (!LOS_ListEmpty(&pstSemPosted->stSemList))
    {
#从需要释放信号量的list中找到第一个task
        pstResumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(pstSemPosted->stSemList))); /*lint !e413*/
#将要唤醒的task的sem置空
        pstResumedTask->pTaskSem = NULL;
#开始唤醒task
        osTaskWake(pstResumedTask, OS_TASK_STATUS_PEND);
#恢复中断
        (VOID)LOS_IntRestore(uwIntSave);
#启动调度
        LOS_Schedule();
    }
    else
    {
#从这里可以知道信号量可以分别获取和释放多次
        pstSemPosted->usSemCount++;
        (VOID)LOS_IntRestore(uwIntSave);
    }

    return LOS_OK;
}

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/86651426
sem
今日推荐