📄 ucos.c
字号:
OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return(msg); /* return mailbox content */ } /* ELSE */ /* message not available, task will pend (sleep on mailbox) */ OSTCBCur->OSTCBStat = OS_STAT_MBOX; OSTCBCur->OSTCBDly = timeout; /* suspend task */ if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { OSRdyGrp &= ~OSTCBCur->OSTCBBitY; } pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; OS_EXIT_CRITICAL(); OSSched(); /* find next task ready to run */ OS_ENTER_CRITICAL(); if (OSTCBCur->OSTCBStat == OS_STAT_MBOX) { /* still pending on mailbox: timeout */ if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY; } OSTCBCur->OSTCBStat = OS_STAT_RDY; /* set status to ready */ OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* no longer waiting for event */ msg = (void *)0; /* set message content to null */ OS_EXIT_CRITICAL(); *err = OS_TIMEOUT; /* signal time'ed out */ } else { msg = pevent->OSEventPtr; /* message received */ pevent->OSEventPtr = (void *)0; /* clear the mailbox */ OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } return(msg);}/* * O S M b o x P o s t * * post mbox message */uint OSMboxPost(OS_EVENT *pevent, void *msg){ OS_ENTER_CRITICAL(); /* make sure mailbox doesn't contain a message */ if (pevent->OSEventPtr != (void *)0) { OS_EXIT_CRITICAL(); return(OS_MBOX_FULL); } /* ELSE */ pevent->OSEventPtr = msg; /* place message in mailbox */ if (pevent->OSEventGrp) /* see if any task is pending on the mailbox */ { OS_EXIT_CRITICAL(); /* resume highest priority task pending on mailbox */ OSEventTaskResume(pevent); OSSched(); /* Find highest priority task ready to run */ } else { OS_EXIT_CRITICAL(); } return(OS_NO_ERR);}/* * I R Q M b o x P o s t * * post mbox message */uint IRQMboxPost(OS_EVENT *pevent, void *msg){ OS_TCB *ptcb; uint x; uint y; uint bitx; uint bity; uint p; if (pevent->OSEventPtr != (void *)0) { return(OS_MBOX_FULL); } /* ELSE */ pevent->OSEventPtr = msg; /* place message in mailbox */ if (pevent->OSEventGrp) /* see if any task is pending on the mailbox */ { y = OSUnMapTbl[pevent->OSEventGrp]; /* find highest priority task pending on event */ bity = OSMapTbl[y]; x = OSUnMapTbl[pevent->OSEventTbl[y]]; bitx = OSMapTbl[x]; p = (y << 3) + x; if ((pevent->OSEventTbl[y] &= ~bitx) == 0) /* remove this task from waiting list */ { pevent->OSEventGrp &= ~bity; } ptcb = OSTCBPrioTbl[p]; /* pointer to new task */ ptcb->OSTCBDly = 0; /* reset timeout */ ptcb->OSTCBStat = OS_STAT_RDY; /* task is ready to run */ ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* unlink control block */ OSRdyGrp |= bity; /* put task in ready to run list */ OSRdyTbl[y] |= bitx; } return(OS_NO_ERR);}/* * O S Q C r e a t e * * create a queue */OS_EVENT *OSQCreate(void **start, uint size){ OS_EVENT *pevent; OS_Q *pq; OS_ENTER_CRITICAL(); pevent = OSEventFreeList; /* get next free event control block */ if (OSEventFreeList) /* update free list */ { OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; } if (pevent == (OS_EVENT *)0) { OS_EXIT_CRITICAL(); /* ran out of event CB */ return(pevent); } /* ELSE */ pq = OSQFreeList; /* get a free queue control block */ if (OSQFreeList != (OS_Q *)0) { OSQFreeList = OSQFreeList->OSQPtr; } if (pq == (OS_Q *)0) /* was there a free block ? */ { pevent->OSEventPtr = (void *)OSEventFreeList; /* NO */ OSEventFreeList = pevent; /* ran out of queue CB return event CB to free list */ OS_EXIT_CRITICAL(); return((OS_EVENT *)0); } /* ELSE */ OS_EXIT_CRITICAL(); pq->OSQStart = start; /* initialize the queue */ pq->OSQEnd = &start[size]; pq->OSQIn = start; pq->OSQOut = start; pq->OSQSize = size; pq->OSQEntries = 0; pevent->OSEventPtr = pq; pevent->OSEventGrp = 0; pevent->OSEventTbl[0] = 0; pevent->OSEventTbl[1] = 0; pevent->OSEventTbl[2] = 0; pevent->OSEventTbl[3] = 0; pevent->OSEventTbl[4] = 0; pevent->OSEventTbl[5] = 0; pevent->OSEventTbl[6] = 0; pevent->OSEventTbl[7] = 0; return(pevent);}/* * O S Q P e n d * * pend for message from a queue */void *OSQPend(OS_EVENT *pevent, uint timeout, uint *err){ void *msg; OS_Q *pq; OS_ENTER_CRITICAL(); pq = (OS_Q *)pevent->OSEventPtr; if (pq->OSQEntries != 0) /* check if the queue already has a message */ { msg = *pq->OSQOut++; /* extract the message */ pq->OSQEntries--; /* update message counter */ if (pq->OSQOut == pq->OSQEnd) /* wrap around Out pointer if reached end */ { pq->OSQOut = pq->OSQStart; } OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return(msg); } /* ELSE */ /* no messages available, sleep on the queue */ OSTCBCur->OSTCBStat = OS_STAT_Q; OSTCBCur->OSTCBDly = timeout; /* suspend task */ if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { OSRdyGrp &= ~OSTCBCur->OSTCBBitY; } pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; /* put task in waiting list */ pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; OS_EXIT_CRITICAL(); OSSched(); /* find next highest priority task ready to run */ OS_ENTER_CRITICAL(); if (OSTCBCur->OSTCBStat == OS_STAT_Q) /* still pending on queue: timeout */ { if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY; } OSTCBCur->OSTCBStat = OS_STAT_RDY; /* set status to ready */ OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* no longer waiting for event */ msg = (void *)0; /* set message content to null */ OS_EXIT_CRITICAL(); *err = OS_TIMEOUT; /* signal time'ed out */ } else { msg = *pq->OSQOut++; /* message received */ pq->OSQEntries--; /* update message counter */ if (pq->OSQOut == pq->OSQEnd) /* wrap around Out pointer if reached end */ { pq->OSQOut = pq->OSQStart; } OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } return(msg);}/* * O S Q P o s t * * post a message to a queue */uint OSQPost(OS_EVENT *pevent, void *msg){ OS_Q *pq; OS_ENTER_CRITICAL(); pq = (OS_Q *)pevent->OSEventPtr; /* point to queue control block */ if (pq->OSQEntries >= pq->OSQSize) /* make sure the queue is not full */ { OS_EXIT_CRITICAL(); return(OS_Q_FULL); } /* ELSE */ *pq->OSQIn++ = msg; /* insert message into queue */ pq->OSQEntries++; /* update number of entries in queue */ if (pq->OSQIn == pq->OSQEnd) { pq->OSQIn = pq->OSQStart; /* wrap around In pointer if reached end */ } if (pevent->OSEventGrp) /* see if any task is pending on the mailbox */ { OS_EXIT_CRITICAL(); OSEventTaskResume(pevent); /* resume highest priority task pending on mailbox */ OSSched(); /* find highest priority task pending on queue */ } else { OS_EXIT_CRITICAL(); } return(OS_NO_ERR);}/* * O S E v e n t T a s k R e s u m e */void OSEventTaskResume(OS_EVENT *pevent){ OS_TCB *ptcb; uint x; uint y; uint bitx; uint bity; uint p; OS_ENTER_CRITICAL(); y = OSUnMapTbl[pevent->OSEventGrp]; /* find highest priority task pending on event */ bity = OSMapTbl[y]; x = OSUnMapTbl[pevent->OSEventTbl[y]]; bitx = OSMapTbl[x]; p = (y << 3) + x; if ((pevent->OSEventTbl[y] &= ~bitx) == 0) /* remove this task from waiting list */ { pevent->OSEventGrp &= ~bity; } ptcb = OSTCBPrioTbl[p]; /* pointer to new task */ ptcb->OSTCBDly = 0; /* reset timeout */ ptcb->OSTCBStat = OS_STAT_RDY; /* task is ready to run */ ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* unlink control block */ OSRdyGrp |= bity; /* put task in ready to run list */ OSRdyTbl[y] |= bitx; OS_EXIT_CRITICAL(); }/* * O S T a s k C r e a t e * * create a task * * This differs from the code in manual because the 1st four parameters are * passed in a1-a4 respectively. Therefore pdata is NOT passed on the stack * but in register a1. * Also TASK's are created so that the LR contains the "return" location, * which allows the context switch to do the same for starting a new task as * well as continuing with a preempted one. */int OSTaskCreate(PTV task, void *pdata, void *ptsk, uint prio){ void *stk; int err; OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[prio] != (OS_TCB *)0) { OS_EXIT_CRITICAL(); return(OS_PRIO_EXIST); /* only one task allowed at its priority */ } /* ELSE build a context for the new task */ OS_EXIT_CRITICAL(); stk = InitTask(ptsk, pdata, task); /* initialise the task at pstk */ err = OSTCBInit(prio, (void *)stk); if ((err == OS_NO_ERR) && OSRunning) { OSSched(); } return(err);}/* * A R M I n s t a l l I R Q H a n d l e r * * This routine allows a uC/OS IRQ source bit ISR to be installed in * the handler vector table. NOTE: The vector table is *TOTALLY* * seperate from the C-Demon IRQ vector table, and is a uC/OS * resource. */IRQHandlerFn ARMInstallIRQHandler(int slot,IRQHandlerFn newfn){ IRQHandlerFn old = NULL ; if ((slot >= 0) && (slot < NUMIRQS)) { old = IRQvectors[slot] ; IRQvectors[slot] = newfn ; } return(old) ;}/* * A R M I n s t a l l F I Q H a n d l e r * * This routine allows a uC/OS FIQ source bit ISR to be installed in * the handler vector table. NOTE: The vector table is *TOTALLY* * seperate from the C-Demon FIQ vector table, and is a uC/OS * resource. */FIQHandlerFn ARMInstallFIQHandler(int slot,FIQHandlerFn newfn){ FIQHandlerFn old = NULL ; if ((slot >= 0) && (slot < NUMFIQS)) { old = FIQvectors[slot] ; FIQvectors[slot] = newfn ; } return(old) ;}/*> EOF ucos.c <*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -