• Liteos信号量的使用


    Liteos信号量和其他的OS一样,分为二值信号量和计数信号量。

    创建信号量

    创建二值信号量和计数信号量时提供了两个函数:

    //创建二值信号量
    LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate (UINT16 usCount, UINT32 *puwSemHandle)
    //创建计数信号量
    LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate (UINT16 usCount, UINT32 *puwSemHandle)
    //实际创建信号量
    LITE_OS_SEC_TEXT_INIT UINT32 osSemCreate (UINT16 usCount, UINT16 usMaxCount, UINT32 *puwSemHandle)
    

    这两个函数都是通过调用osSemCreate()函数来实现创建信号量,唯一的区别就是传入的usMaxCount值不同。二值信号量传入的宏定义是OS_SEM_BINARY_MAX_COUNT,也就是说最大可用信号量是1,而计数信号量传入的是OS_SEM_COUNTING_MAX_COUNT,这个值为0xFFFF。
    二值信号量的使用方式很简单,通过创建时传入的usCount来指定信号量创建后的初始可用信号量值,如果设置为1,那么任务就可以直接获取到信号量。计数信号量的用法也是一样,但是可以一直Post,直到最大值OS_SEM_COUNTING_MAX_COUNT。

    计数信号量测试

    在创建信号量之前需要先仿照消息队列的LOS_QueueInfoGet()函数来写一个用来获取信号量控制块的具体内容函数,主要看一下可用信号量个数和最大可用信号量个数:

    LITE_OS_SEC_TEXT UINT32 LOS_SemInfoGet(UINT32 uwSemHandle,SEM_CB_S  *pstSemInfo)
    {
        UINT32 uvIntSave;
        UINT32 uwRet = LOS_OK;
    	SEM_CB_S  *pstSem;
        LOS_TASK_CB *pstTskCB;
    
        if (uwSemHandle >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT)
        {
            OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
        }
    
        pstSem = GET_SEM(uwSemHandle);
        uvIntSave = LOS_IntLock();
        if (OS_SEM_UNUSED == pstSem->usSemStat)
        {
            LOS_IntRestore(uvIntSave);
            OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
        }
    
        (VOID)memset((VOID *)pstSemInfo, 0, sizeof(SEM_CB_S));
    	pstSemInfo->usSemID = pstSem->usSemID;
    	pstSemInfo->usSemStat = pstSem->usSemStat;
    	pstSemInfo->usSemCount = pstSem->usSemCount;
    	pstSemInfo->usMaxSemCount = pstSem->usMaxSemCount;
    	(VOID)LOS_IntRestore(uvIntSave);
    	return LOS_OK;
    }
    

    直接用LOS_SemCreate()函数创建一个计数信号量,初始可用信号量个数为5,创建后立刻Post5次,并在Post前后将可用信号量个数和最大可用信号量个数打印出来:

    UINT32	test_countsem_handle;
    SEM_CB_S pstSemInfo;
    uwRet = LOS_SemCreate(5,&test_countsem_handle);
    if(uwRet != LOS_OK)
    {
    	PRINT_ERR("Sem Error Code:0x%X\n",uwRet);
    	return uwRet;
    }	
    uwRet = LOS_SemInfoGet(test_countsem_handle,&pstSemInfo);
    if(uwRet == LOS_OK)
    {
    	PRINT_INFO("Sem Count:%d\r\n",pstSemInfo.usSemCount);
    	PRINT_INFO("Sem CountMax:%d\r\n",pstSemInfo.usMaxSemCount);
    }
    uwRet = LOS_SemPost(test_countsem_handle);
    if(uwRet != LOS_OK)
    {
    	PRINT_ERR("Post Sem Error:0x%X\n",uwRet);
    }
    uwRet = LOS_SemPost(test_countsem_handle);
    if(uwRet != LOS_OK)
    {
    	PRINT_ERR("Post Sem Error:0x%X\n",uwRet);
    }
    uwRet = LOS_SemPost(test_countsem_handle);
    if(uwRet != LOS_OK)
    {
    	PRINT_ERR("Post Sem Error:0x%X\n",uwRet);
    }
    uwRet = LOS_SemPost(test_countsem_handle);
    if(uwRet != LOS_OK)
    {
    	PRINT_ERR("Post Sem Error:0x%X\n",uwRet);
    }
    uwRet = LOS_SemPost(test_countsem_handle);
    if(uwRet != LOS_OK)
    {
    	PRINT_ERR("Post Sem Error:0x%X\n",uwRet);
    }
    uwRet = LOS_SemInfoGet(test_countsem_handle,&pstSemInfo);
    if(uwRet == LOS_OK)
    {
    	PRINT_INFO("Sem Count:%d\r\n",pstSemInfo.usSemCount);
    	PRINT_INFO("Sem CountMax:%d\r\n",pstSemInfo.usMaxSemCount);
    }
    

    创建一个任务,这个任务只获取信号量,最大只能获取5次,任务主要内容:

    UINT32 uwRet = LOS_OK;
    UINT32 count = 0;
    LOS_TaskDelay(400);//2s
    uwRet = LOS_SemPend(test_countsem_handle,LOS_NO_WAIT);
    if(uwRet != LOS_OK)
    {
    	PRINT_ERR("Pend Sem Error:0x%X\n",uwRet);
    }
    else
    {
    	PRINT_INFO("Pend Sem Ok = %d\r\n",(++count));
    }
    

    按照期望来说,Pend信号量只能成功5次,但是实际运行结果却是10次,通过日志也可以看出来Post5次之后,可用信号量个数增加了5;Pend10次之后,下一次就不能成功了,因为没有可用信号量,错误码0x2000704,7表示是信号量产生的错误,4表示没有可用信号量,宏定义为LOS_ERRNO_SEM_UNAVAILABLE。
    在这里插入图片描述
    原因就是LOS_SemPost()函数中会有pstSemPosted->usMaxSemCount == pstSemPosted->usSemCount这个判断,就是比较可用信号量个数和最大可用信号量个数是否相等,如果相等的话就直接返回,无需Post,但是OS_SEM_COUNTING_MAX_COUNT这个值为0xFFFF,因此可以一直Post直到最大值。使用LOS_BinarySemCreate()函数创建二值信号量时就没有这个问题。

    创建计数信号量时直接调用osSemCreate()函数或者更改OS_SEM_COUNTING_MAX_COUNT的值为5时,运行结果就和期望结果一致:

    uwRet = osSemCreate(5,5,&test_countsem_handle);
    

    在这里插入图片描述
    由于可用信号量个数和最大可用信号量个数相等,在创建信号量之后Post时返回了错误码0x2000708,8表示溢出,宏定义为LOS_ERRNO_SEM_OVERFLOW;在Pend5次之后由于没有可用信号量,返回错误LOS_ERRNO_SEM_UNAVAILABLE。

  • 相关阅读:
    mac电脑解决无法打开软件
    elementui中table嵌套input并且当input输入一个数值后,其他input中的值根据计算公式相应改变
    JavaEE大作业之班级通讯录系统(前端HTML+后端JavaEE实现)PS:也可选网络留言板、图书借阅系统、寝室管理系统
    (电脑软件启动无法验证)win10专业版如何解决无法验证发布者
    1、Mybatis搭建流程
    2023.10.8 基本 Thread 线程详解
    【不规范bug注意】2023.9.26
    Typora自定义主题
    【JavaSE】内部类
    Spark3 AQE (Adaptive Query Execution) 一文搞懂 新特性
  • 原文地址:https://blog.csdn.net/sinat_42731525/article/details/127108839