1.1.1 OSSemQuery() 信号量查询
源码分析
INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
-
OS_EVENT *pevent 要查询的信号量 ECB 指针
-
OS_SEM_DATA * pdata 用于存储查询信号量副本的指针 ,下面是 OS_SEM_DATA 的具体实现,它用于存储 ECB 的三个内容,计数值,等待列表信息,可以说是一个简易的 ECB 。在调用之前仍然需要先建立一个全局的 OS_SEM_DATA 来存储。直接使用 pdata 可以进行相关信息的操作。
#if OS_SEM_EN > 0
typedef struct {
INT16U OSCnt; /* Semaphore count */
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
} OS_SEM_DATA;
#endif
#if OS_SEM_QUERY_EN > 0
INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
INT8U *psrc;
INT8U *pdest;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* 查看 ECB 是否有效 */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* 查看 ECB 类型 */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pdata->OSEventGrp = pevent->OSEventGrp; /* 复制等待列表组信息 */
psrc = &pevent->OSEventTbl[0];
pdest = &pdata->OSEventTbl[0];
///******** 这种定义是否更高效,源码用 for 循环有什么区别?
#if OS_EVENT_TBL_SIZE > 0
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 1
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 2
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 3
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 4
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 5
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 6
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 7
*pdest = *psrc;
#endif
pdata->OSCnt = pevent->OSEventCnt; /* 获得信号量计数值 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif /* OS_SEM_QUERY_EN */
1.2邮箱
1.2.1 OSMboxCreate() 邮箱信号量创建
OS_EVENT *OSMboxCreate (void *msg)
-
Void *msg 携带的信息
说明:
-
OSMboxCreate 所携带的变量是 void *msg , 而 OSSemCreate 携带的是 INT16U cnt ,邮箱没有 OSEventCnt 变量,都置为 0 ,但要 OSEventPtr 指向 msg 。
-
邮箱一旦建立,是不能被删除的
OS_EVENT *OSMboxCreate (void *msg)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
if (OSIntNesting > 0) { /* See if called from ISR ... */
return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
}
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; /* Get next free event control block */
if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0) {
pevent->OSEventType = OS_EVENT_TYPE_MBOX;
pevent->OSEventCnt = 0;
pevent->OSEventPtr = msg; /* Deposit message in event control block */
OS_EventWaitListInit(pevent);
}
return (pevent); /* Return pointer to event control block */
}
1.2.2 OSMboxPend () 等待一个邮箱中的信息
void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
void *msg;
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return ((void *)0);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
msg = pevent->OSEventPtr;
if (msg != (void *)0) { /* See if there is already a message */
pevent->OSEventPtr = (void *)0; /* Clear the mailbox */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (msg); /* Return the message received (or NULL) */
}
OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */