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

来源:互联网 发布:淘宝费用预算表 编辑:程序博客网 时间:2024/05/24 23:14

 

 

 

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可以进行相关信息的操作。

#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)

 

  1. Void*msg 携带的信息

说明:

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

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

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方式)

源码分析

  1. OS_EVENT*pevent

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

源码分析

  1. OS_EVENT*pevent

  2. 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()查询一个消息队列状态

源码分析

  1. OS_EVENT*pevent

  2. 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)置1OSRdyGrp是优先级分组的标志。它的每一位代表该优先级组是否有就绪任务,若某一组有就绪态,则相应为置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就绪表最高优先级查询方法

设计到三个变量:

  1. OSRdyGrp用于优先级存储分组情况,每位表示该组是否有就绪任务

  2. OSRdyTbl[n]表示第n组的就绪任务的具体就绪情况情况

  3. OSUnMapTbl[]就绪表查表用

  4. X用于存储所在组的数据

  5. Y用于存储在组内的位置的数据

OSRdyTbl[]里面存储了当前所有就绪的任务情况。我们要找到优先级最高的一个任务号,通常需要采用遍历的方法,而建立这个表以后则只需要查询即可。

X= OSUnMapTbl[OSRdyGrp] ;

Y= OSUnMapTbl[X];

Prio= X<<3 + Y;

2.3OSUnMapTbl[]表建立方法

也就是说通过OSRdyGrp我们就可以找到最高就绪优先级的任务。

这个表的建立是这样的:首先查找OSRdyGrp,找到有就绪任务的优先级最高的组(为1的最低位)。若OSRdyGrp0位为1,计OSRdyGrp= xxxxxxx1,则无论高7位置何如,查表后返回值都应该是0(第0组就绪任务),OSRdyGrp28个值,则建立一个256大小的数组来存储。那么这个数组的xxxxxxx1位都应该是0。而若OSRdyGrp1位为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

 

 

原创粉丝点击