liteos中sem的使用

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值