uC/OS-II操作系统分析 (三)

 

 

 

1.1.1 OSSemQuery() 信号量查询

源码分析

INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)

 

  1. OS_EVENT *pevent 要查询的信号量 ECB 指针

  2. 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)

 

  1. Void *msg 携带的信息

说明:

  1. OSMboxCreate 所携带的变量是 void *msg , 而 OSSemCreate 携带的是 INT16U cnt ,邮箱没有 OSEventCnt 变量,都置为 0 ,但要 OSEventPtr 指向 msg

  2. 邮箱一旦建立,是不能被删除的

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 */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值