μC/OS-II--信号量SEM

本文详细介绍了μC/OS-II操作系统中信号量的数据结构、建立、删除、等待、无等待请求、停止等待、发送及查询状态等操作。信号量作为一种重要的同步和资源管理工具,其初始值的设定以及在不同场景下的应用被详细阐述,同时讨论了删除信号量时的策略选择,如OS_DEL_NO_PEND和OS_DEL_ALWAYS。
摘要由CSDN通过智能技术生成

信号量由2部分组成,一部分是16位的无符号整形信号量的计数值,另一部分是由等待该信号量的任务组成的等待任务表。信号量建立在事件的基础之上。

信号量数据结构

信号量使用事件结构,查询信号量状态时使用如下结构,包括信号量值,以及等待列表。

/*
*********************************************************************************************************
*                                           SEMAPHORE DATA
*********************************************************************************************************
*/

#if OS_SEM_EN > 0
typedef struct os_sem_data {
    INT16U  OSCnt;                        //信号量值
#if OS_LOWEST_PRIO <= 63
    INT8U   OSEventTbl[OS_EVENT_TBL_SIZE];  //等待列表组
    INT8U   OSEventGrp;                     //等待列表
#else
    INT16U  OSEventTbl[OS_EVENT_TBL_SIZE];  
    INT16U  OSEventGrp;                     
#endif
} OS_SEM_DATA;
#endif

建立一个信号量

调用OSSemCreate函数建立信号量,并对信号量赋予初始计数值。该初始值为0-65535的一个数,如果信号量用来表示一个或多个事件的发生,那么信号量的初始值赋值为0。如果信号量用于对共享资源的访问,那么信号量的初始值应赋1。如果信号量用于允许任务同时访问n个相同的资源,那么信号量的初始值赋值为n。

OS_EVENT  *OSSemCreate (INT16U cnt)
{
    OS_EVENT  *pevent;
#if OS_CRITICAL_METHOD == 3                                 //为CPU状态寄存器分配内存
    OS_CPU_SR  cpu_sr = 0;
#endif



    if (OSIntNesting > 0) {                                //检查是否进入中断
        return ((OS_EVENT *)0);                           
    }
    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;                              //获取一个空闲块
    if (OSEventFreeList != (OS_EVENT *)0) {                //OSEventFreeList指向下一个空闲块
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
    }
    OS_EXIT_CRITICAL();
    if (pevent != (OS_EVENT *)0) {                        //空闲块是否为空
        pevent->OSEventType    = OS_EVENT_TYPE_SEM;       //设置事件为信号量类型
        pevent->OSEventCnt     = cnt;                     //设置信号量
        pevent->OSEventPtr     = (void *)0;               //信号量该指针不使用
#if OS_EVENT_NAME_SIZE > 1
        pevent->OSEventName[0] = '?';                      //设置事件名为未知
        pevent->OSEventName[1] = OS_ASCII_NUL;
#endif
        OS_EventWaitListInit(pevent);                      //初始化事件为无任务等待状态
    }
    return (pevent);
}

删除一个信号量

首先进行各项检查,然后判断是否还有任务在等待该信号量。有两种删除信号量的方法, OS_DEL_NO_PEND,等没有任务等待时删除,如果有任务等待,返回错误,没有任务等待的话,将事件块释放。OS_DEL_ALWAYS,无论有没有事件等待都删除,直接将事件块释放,如果之前有任务等待,进行一次任务调度。

#if OS_SEM_DEL_EN > 0
OS_EVENT  *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *perr)
{
    BOOLEAN    tasks_waiting;
    OS_EVENT  *pevent_return;
#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr = 0;
#endif



#if OS_ARG_CHK_EN > 0
    if (perr == (INT8U *)0) {                             //检查错误指针
        return (pevent);
  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值