uC/OS-II操作系统分析 (三)
来源:互联网 发布:淘宝费用预算表 编辑:程序博客网 时间:2024/05/24 23:14
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可以进行相关信息的操作。
#ifOS_SEM_EN > 0
typedefstruct {
INT16U OSCnt; /* Semaphore count */
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event tooccur */
INT8U OSEventGrp; /* Group corresponding to tasks waiting forevent to occur */
}OS_SEM_DATA;
#endif
#ifOS_SEM_QUERY_EN > 0
INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPUstatus register */
OS_CPU_SR cpu_sr;
#endif
INT8U *psrc;
INT8U *pdest;
#ifOS_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循环有什么区别?
#ifOS_EVENT_TBL_SIZE > 0
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 1
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 2
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 3
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 4
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 5
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 6
*pdest++ = *psrc++;
#endif
#ifOS_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携带的是INT16Ucnt,邮箱没有OSEventCnt变量,都置为0,但要OSEventPtr指向msg。
邮箱一旦建立,是不能被删除的
OS_EVENT *OSMboxCreate (void *msg)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPU statusregister */
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
if(OSIntNesting > 0) { /* See if called fromISR ... */
return((OS_EVENT *)0); /* ... can't CREATE from an ISR */
}
OS_ENTER_CRITICAL();
pevent= OSEventFreeList; /* Get next free event controlblock */
if(OSEventFreeList != (OS_EVENT *)0) { /* See if pool of freeECB 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 eventcontrol block */
}
1.2.2 OSMboxPend()等待一个邮箱中的信息
void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPU statusregister */
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);
}
#ifOS_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 eventblock type */
*err= OS_ERR_EVENT_TYPE;
return((void *)0);
}
#endif
OS_ENTER_CRITICAL();
msg =pevent->OSEventPtr;
if (msg!= (void *)0) { /* See if there is alreadya message */
pevent->OSEventPtr= (void *)0; /* Clear the mailbox */
OS_EXIT_CRITICAL();
*err= OS_NO_ERR;
return(msg); /* Return the message received (orNULL) */
}
OSTCBCur->OSTCBStat|= OS_STAT_MBOX; /* Message not available, task will pend */
OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout ccurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority taskready to run */
OS_ENTER_CRITICAL();
msg =OSTCBCur->OSTCBMsg;
if (msg!= (void *)0) { /* See if we were given themessage */
OSTCBCur->OSTCBMsg = (void *)0; /* Yes, clear message received */
OSTCBCur->OSTCBStat = OS_STAT_RDY;
OSTCBCur->OSTCBEventPtr= (OS_EVENT *)0; /* No longer waiting for event */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return(msg); /* Return the message received */
}
OS_EventTO(pevent); /* Timed out, Make task ready */
OS_EXIT_CRITICAL();
*err =OS_TIMEOUT; /* Indicate that a timeoutoccured */
return((void *)0); /* Return a NULL message */
}
1.2.3 OSMboxPost()发送一个信息到邮箱
INT8U OSMboxPost (OS_EVENT *pevent, void *msg)
#ifOS_MBOX_POST_EN > 0
INT8U OSMboxPost (OS_EVENT *pevent, void *msg)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPU statusregister */
OS_CPU_SR cpu_sr;
#endif
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return(OS_ERR_PEVENT_NULL);
}
if (msg== (void *)0) { /* Make sure we are not posting aNULL pointer */
return(OS_ERR_POST_NULL_PTR);
}
if(pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate eventblock type */
return(OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if(pevent->OSEventGrp != 0x00) { /* See if any taskpending on mailbox */
OS_EventTaskRdy(pevent,msg, OS_STAT_MBOX);
/* Readyhighest priority task waiting on event */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return(OS_NO_ERR);
}
if(pevent->OSEventPtr != (void *)0) { /* Make sure mailboxdoesn't already have a msg */
OS_EXIT_CRITICAL();
return(OS_MBOX_FULL);
}
pevent->OSEventPtr= msg; /* Place message in mailbox */
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
#endif
1.2.4 OSMboxAccept()无等待的从邮箱得到一个信息
#ifOS_MBOX_ACCEPT_EN > 0
void *OSMboxAccept (OS_EVENT *pevent)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPUstatus register */
OS_CPU_SR cpu_sr;
#endif
void *msg;
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /* Validate'pevent' */
return((void *)0);
}
if(pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validateevent block type */
return((void *)0);
}
#endif
OS_ENTER_CRITICAL();
msg = pevent->OSEventPtr;
pevent->OSEventPtr= (void *)0; /* Clear the mailbox */
OS_EXIT_CRITICAL();
return(msg); /* Return the message received(or NULL) */
}
#endif
1.2.5 OSMailQuary()查询邮箱实验
#ifOS_MBOX_QUERY_EN > 0
INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPU statusregister */
OS_CPU_SR cpu_sr;
#endif
INT8U *psrc;
INT8U *pdest;
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return(OS_ERR_PEVENT_NULL);
}
if(pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate eventblock type */
return(OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pdata->OSEventGrp= pevent->OSEventGrp; /* Copy message mailbox wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &pdata->OSEventTbl[0];
#ifOS_EVENT_TBL_SIZE > 0
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 1
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 2
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 3
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 4
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 5
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 6
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 7
*pdest = *psrc;
#endif
pdata->OSMsg= pevent->OSEventPtr; /* Get message from mailbox */
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
#endif /* OS_MBOX_QUERY_EN */
1.3消息队列
typedefstruct os_q { /* 队列控制块 */
structos_q *OSQPtr; /* 指向队列控制块中的下一个块*/
void **OSQStart; /*指向消息队列的指针数组的起始地址的指针*/
void **OSQEnd; /*指向消息队列结束单元的下一个地址的指针*/
void **OSQIn; /*指向消息队列中插入下一条消息的位置的指针*/
void **OSQOut; /*指向消息队列中下一个取出消息的位置的指针 */
INT16U OSQSize; /*是消息队列中总的单元数,最大65535 */
INT16U OSQEntries; /* 当前队列入口点,是消息队列中当前的消息数量*/
} OS_Q;
1.3.1 OSQCreate()建立一个消息队列
OS_EVENT *OSQCreate (void **start, INT16U size)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPU statusregister */
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
OS_Q *pq;
if(OSIntNesting > 0) { /* 看是否从中断服务程序中执行函数 */
return((OS_EVENT *)0); /* 返回空 */
}
OS_ENTER_CRITICAL();
pevent= OSEventFreeList; /* 从空闲列表中获得ECB */
if(OSEventFreeList != (OS_EVENT *)0) { /* 看是否到了事件空闲列表的尾端 */
OSEventFreeList= (OS_EVENT *)OSEventFreeList->OSEventPtr; /* 该ECB指向下一个空闲*/
}
OS_EXIT_CRITICAL();
if(pevent != (OS_EVENT *)0) { /* 看是否得到ECB */
OS_ENTER_CRITICAL();
pq= OSQFreeList; /* 得到一个空闲队列控制块 */
if(pq != (OS_Q *)0) { /* 该队列控制块可用?*/
OSQFreeList = OSQFreeList->OSQPtr; /* 是则调整空闲队列控制块指针*/
OS_EXIT_CRITICAL();
pq->OSQStart = start; /* 初始化队列信息 */
pq->OSQEnd = &start[size];
pq->OSQIn = start;
pq->OSQOut = start;
pq->OSQSize = size;
pq->OSQEntries = 0;
pevent->OSEventType= OS_EVENT_TYPE_Q;
pevent->OSEventCnt = 0;
pevent->OSEventPtr = pq;
OS_EventWaitListInit(pevent); /* 初始化等待列表 */
}else {
pevent->OSEventPtr= (void *)OSEventFreeList; /* Nn error */
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
/////////********
pevent= (OS_EVENT *)0;
*******///////
}
}
return(pevent);
}
流程图
图1 OSQCreate()流程图就绪表Ready List
1.3.2 OSQpend()等待一个消息队列中的消息
源码分析
void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPU statusregister */
OS_CPU_SR cpu_sr;
#endif
void *msg;
OS_Q *pq;
if(OSIntNesting > 0) { /* See if called fromISR ... */
*err= OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return((void *)0);
}
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /* 查看ECB是否可用 */
*err= OS_ERR_PEVENT_NULL;
return((void *)0);
}
if(pevent->OSEventType != OS_EVENT_TYPE_Q) { / * 查看ECB的类型是否为队列 */
*err= OS_ERR_EVENT_TYPE;
return((void *)0);
}
#endif
OS_ENTER_CRITICAL();
pq =(OS_Q *)pevent->OSEventPtr; /* 该ECB指向消息队列 */
if(pq->OSQEntries > 0) { /* 查看是否有消息在队列中*/
msg= *pq->OSQOut++; /* 是则最后进的消息出队列*/
pq->OSQEntries--; /* 消息数减1 */
if(pq->OSQOut == pq->OSQEnd) { /* 如果出队列指针在队尾则将其指向队头*/
pq->OSQOut= pq->OSQStart;
}
OS_EXIT_CRITICAL();
*err= OS_NO_ERR;
return(msg); /* 返回收到的消息 */
}
OSTCBCur->OSTCBStat|= OS_STAT_Q; /* 任务需要等待一个消息 */
OSTCBCur->OSTCBDly = timeout; /* 设置超时时间 */
OS_EventTaskWait(pevent); /* 挂起任务直到超时或消息到来 */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready torun */
OS_ENTER_CRITICAL();
msg =OSTCBCur->OSTCBMsg;
if (msg!= (void *)0) { /* 如果得到消息 */
OSTCBCur->OSTCBMsg = (void *)0; /* 从TCB中获取msg */
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* 设置状态为ready*/
OSTCBCur->OSTCBEventPtr= (OS_EVENT *)0; /* 不再等待事件发生 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return(msg); /* Return message received */
}
OS_EventTO(pevent); /* 超时处理 */
OS_EXIT_CRITICAL();
*err =OS_TIMEOUT; /* Indicate a timeout occured */
return((void *)0); /* No message received */
}
1.3.3 OSQPost()向消息队列发送一个信息(FIFO方式)
源码分析
OS_EVENT*pevent
void*msg
#ifOS_Q_POST_EN > 0
INT8U OSQPost (OS_EVENT *pevent, void *msg)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPU statusregister */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return(OS_ERR_PEVENT_NULL);
}
if (msg== (void *)0) { /* 确保我们不是在发送无效消息 */
return(OS_ERR_POST_NULL_PTR);
}
if(pevent->OSEventType != OS_EVENT_TYPE_Q) { /* 查看事件类型是否为队列 */
return(OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if(pevent->OSEventGrp != 0x00) { /* 查看是否有任务在等待 */
OS_EventTaskRdy(pevent,msg, OS_STAT_Q); /* 令高优先级等待任务就绪*/
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return(OS_NO_ERR);
}
pq =(OS_Q *)pevent->OSEventPtr; /* Point to queue controlblock */
if(pq->OSQEntries >= pq->OSQSize) { /* Make surequeue is not full */
OS_EXIT_CRITICAL();
return(OS_Q_FULL);
}
*pq->OSQIn++= msg; /* Insert message into queue */
pq->OSQEntries++; /* Update the nbr of entries in the queue */
if(pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we areat end of queue */
pq->OSQIn= pq->OSQStart;
}
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
#endif
1.3.4 OSQPostFront()向消息队列发送一个消息(后进先出LIFO)
源码分析
OS_EVENT*pevent
void*msg
#ifOS_Q_POST_FRONT_EN > 0
INT8U OSQPostFront (OS_EVENT *pevent, void *msg)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPUstatus register */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /*查看ECB是否可用*/
return(OS_ERR_PEVENT_NULL);
}
if (msg== (void *)0) { /* 确定消息可用*/
return(OS_ERR_POST_NULL_PTR);
}
if(pevent->OSEventType != OS_EVENT_TYPE_Q) { /*查看事件类型 */
return(OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if(pevent->OSEventGrp != 0x00) { /* See if any taskpending on queue */
OS_EventTaskRdy(pevent,msg, OS_STAT_Q); /* Ready highest priority task waiting on event*/
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return(OS_NO_ERR);
}
pq =(OS_Q *)pevent->OSEventPtr; /* Point to queuecontrol block */
if(pq->OSQEntries >= pq->OSQSize) { /* Make surequeue is not full */
OS_EXIT_CRITICAL();
return(OS_Q_FULL);
}
if(pq->OSQOut == pq->OSQStart) { /* 如果out指针指向开头*/
pq->OSQOut= pq->OSQEnd; /* 令其指向队尾,保证LIFO*/
}
pq->OSQOut--; /* 注意后进先出的out指针是减减*/
*pq->OSQOut= msg; /* Insert message into queue */
pq->OSQEntries++; /* Update the nbr of entries in the queue */
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
#endif
1.3.5OSQAccept()无等待地从一个消息队列中取得消息
#ifOS_Q_ACCEPT_EN > 0
void *OSQAccept (OS_EVENT *pevent)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPUstatus register */
OS_CPU_SR cpu_sr;
#endif
void *msg;
OS_Q *pq;
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /* 查看ECB是否有效 */
return((void *)0);
}
if(pevent->OSEventType != OS_EVENT_TYPE_Q) { /* 查看类型是否有效 */
return((void *)0);
}
#endif
OS_ENTER_CRITICAL();
pq =(OS_Q *)pevent->OSEventPtr; /* Point at queue controlblock */
if(pq->OSQEntries > 0) { /* See if anymessages in the queue */
msg= *pq->OSQOut++; /* Yes, extract oldest message fromthe queue */
pq->OSQEntries--; /* Update the number of entries in the queue */
if(pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we areat the end of the queue */
pq->OSQOut= pq->OSQStart;
}
} else{
msg= (void *)0; /* Queue is empty */
}
OS_EXIT_CRITICAL();
return(msg); /* Return message received (orNULL) */
}
#endif
1.3.6 OSQQuery()查询一个消息队列状态
源码分析
OS_EVENT*pevent
OS_Q_DATA*pdata
typedefstruct {
void *OSMsg; /* Pointer to next message to be extracted fromqueue */
INT16U OSNMsgs; /* Number of messages in message queue */
INT16U OSQSize; /* Size of message queue */
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting forevent to occur */
INT8U OSEventGrp; /* Group corresponding to tasks waiting forevent to occur */
}OS_Q_DATA;
#ifOS_Q_QUERY_EN > 0
INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPUstatus register */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
INT8U *psrc;
INT8U *pdest;
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return(OS_ERR_PEVENT_NULL);
}
if(pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validateevent block type */
return(OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pdata->OSEventGrp= pevent->OSEventGrp; /* Copy message queue wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &pdata->OSEventTbl[0];
#ifOS_EVENT_TBL_SIZE > 0
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 1
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 2
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 3
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 4
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 5
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 6
*pdest++ = *psrc++;
#endif
#ifOS_EVENT_TBL_SIZE > 7
*pdest = *psrc;
#endif
pq =(OS_Q *)pevent->OSEventPtr;
if(pq->OSQEntries > 0) {
pdata->OSMsg= *pq->OSQOut; /* Get next message to return ifavailable */
} else{
pdata->OSMsg= (void *)0;
}
pdata->OSNMsgs= pq->OSQEntries;
pdata->OSQSize= pq->OSQSize;
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
#endif
1.3.7OSQFlush()清空一个队列
#ifOS_Q_FLUSH_EN > 0
INT8U OSQFlush (OS_EVENT *pevent)
{
#ifOS_CRITICAL_METHOD == 3 /* Allocate storage for CPUstatus register */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
#ifOS_ARG_CHK_EN > 0
if(pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return(OS_ERR_PEVENT_NULL);
}
if(pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate eventblock type */
return(OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pq = (OS_Q *)pevent->OSEventPtr; /* 指向队列 */
pq->OSQIn = pq->OSQStart; /* 不一定要从队头开始*/
pq->OSQOut = pq->OSQStart;
pq->OSQEntries= 0;
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
#endif
2.就绪表Ready List
整个uCOS-II的任务就绪管理用一个8位数组OSRdyTbl[8]存储。他存储了对应的64个优先级
2.1 就绪表示意图
其中若某一优先级就绪,则相应位(0-63)置1。OSRdyGrp是优先级分组的标志。它的每一位代表该优先级组是否有就绪任务,若某一组有就绪态,则相应为置1,否则为0。
另外有两个用于查询的表
这个表分别记录了8位数据的每一位为1的情况。如果我要对Data= 0x1F的第5位置1,则可以用Data|= OSMapTbl[3] .
INT8U const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,0x80};
这个表利用了空间换时间的方法提供最高优先级任务的查询工作。它可以让我们不用去遍历就绪表而直接用查表的方法进行查询。
INT8U const OSUnMapTbl[] = {
0, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00 to 0x0F */
4, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x10 to 0x1F */
5, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x20 to 0x2F */
4, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x30 to 0x3F */
6, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x40 to 0x4F */
4, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5F */
5, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x60 to 0x6F */
4, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x70 to 0x7F */
7, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x80 to 0x8F */
4, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x90 to 0x9F */
5, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xA0 to 0xAF */
4, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xB0 to 0xBF */
6, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xC0 to 0xCF */
4, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xD0 to 0xDF */
5, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xE0 to 0xEF */
4, 0,1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 0xF0 to 0xFF */
};
2.2就绪表最高优先级查询方法
设计到三个变量:
OSRdyGrp用于优先级存储分组情况,每位表示该组是否有就绪任务
OSRdyTbl[n]表示第n组的就绪任务的具体就绪情况情况
OSUnMapTbl[]就绪表查表用
X用于存储所在组的数据
Y用于存储在组内的位置的数据
OSRdyTbl[]里面存储了当前所有就绪的任务情况。我们要找到优先级最高的一个任务号,通常需要采用遍历的方法,而建立这个表以后则只需要查询即可。
X= OSUnMapTbl[OSRdyGrp] ;
Y= OSUnMapTbl[X];
Prio= X<<3 + Y;
2.3OSUnMapTbl[]表建立方法
也就是说通过OSRdyGrp我们就可以找到最高就绪优先级的任务。
这个表的建立是这样的:首先查找OSRdyGrp,找到有就绪任务的优先级最高的组(为1的最低位)。若OSRdyGrp第0位为1,计OSRdyGrp= xxxxxxx1,则无论高7位置何如,查表后返回值都应该是0(第0组就绪任务),OSRdyGrp共28个值,则建立一个256大小的数组来存储。那么这个数组的xxxxxxx1位都应该是0。而若OSRdyGrp第1位为1,第0位为0,即xxxxxx10,则无论高6位置何值,查表返回值都应该是1(第1组就绪任务),这个数组的xxxxxx10个值都应该是1。以此类推,可以完成整个表的建立。
通过该表进行查询后即可得到相应的优先级值。
/////////////////****************
注意当OSRdyGrp= 0x00时,即没有任务就绪时,查找到的优先级为0.
*****************/////////////////
2.4从就绪表中去除某优先级
从就绪表中去除某优先级(即将对应优先级号的位置0)
OSRdyTbl[prio>>3] &= ~OSMapTbl[Prio&0x07];
由于这种操作可能导致某优先级组全为0的情况,会影响OSRdyGrp,所以还要对其进行判断。
If ( (OSRdyTbl[prio>>3] &= ~OSMapTbl[Prio&0x07]) & OSMapTbl[prio&0x07] == 0)
{
OSRdyGrp &= ~ OSMapTbl[prio>>3] ;
}
以上程序完成了从就绪列表去除优先级和更新OSRdyGrp两件事。
3.任务状态
#define OS_STAT_RDY 0x00 /* Ready to run */
#define OS_STAT_SEM 0x01 /* Pending on semaphore */
#define OS_STAT_MBOX 0x02 /* Pending on mailbox */
#define OS_STAT_Q 0x04 /* Pending on queue */
#define OS_STAT_SUSPEND 0x08 /* Task is suspended */
#define OS_STAT_MUTEX 0x10 /* Pending on mutual exclusionsemaphore */
#define OS_STAT_FLAG 0x20 /* Pending on event flag group */
4.
#if(OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0)
typedefstruct {
INT8U OSEventType; /* Type of event control block (seeOS_EVENT_TYPE_???) */
INT8U OSEventGrp; /* Group corresponding to tasks waiting forevent to occur */
INT16U OSEventCnt; /* Semaphore Count (not used if other EVENTtype) */
void *OSEventPtr; /* Pointer to message or queue structure */
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for eventto occur */
} OS_EVENT;
#endif
- uC/OS-II操作系统分析 (三)
- uC/OS-II操作系统分析 (一)
- uC/OS-II操作系统分析 (二)
- uC/OS-II源码分析(三)
- uC/OS-II源码分析(三)
- UC/OS-II 操作系统移植
- 研究uc/os-ii操作系统
- UC/OS-II 操作系统移植
- uc/os-ii操作系统笔记
- UC/OS-II操作系统结构
- UC/OS-II中的任务(三)
- uC/OS-II源码分析(一)
- uC/OS-II源码分析(二)
- uC/OS-II源码分析(六)
- uC/OS-II源码分析(五)
- uC/OS-II源码分析(四)
- uC/OS-II源码分析(二)
- uC/OS-II源码分析(一)
- UITableViewCell中的自视图放在哪里
- java类
- smtp.class.php
- uC/OS-II操作系统分析 (二)
- 关于堆栈
- uC/OS-II操作系统分析 (三)
- VECTOR-BUG
- vmlinuz文件
- 多条件查询的程序
- 开通咯~
- 经典智力题
- Apache源代码解析之自动索引目录
- .NET GC
- 为某一目录创建Internet来宾账户