📄 ucos.c
字号:
UBYTE OSSemPost(OS_EVENT *pevent)
{
OS_ENTER_CRITICAL();
if (pevent->OSEventCnt < 32766) { /* Make sure semaphore will not overflow */
if (pevent->OSEventCnt++ >= 0) {
OS_EXIT_CRITICAL();
} else { /* Negative semaphore value means task(s) pending */
if (pevent->OSEventGrp) { /* See if any task pending on semaphore */
OS_EXIT_CRITICAL();
OSEventTaskResume(pevent); /* Resume highest priority task pending on semaphore */
OSSched(); /* Find highest priority task ready to run */
} else {
OS_EXIT_CRITICAL();
}
}
return (OS_NO_ERR);
} else {
OS_EXIT_CRITICAL();
return (OS_SEM_OVF);
}
}
/*
*********************************************************************************************************
* INITIALIZE MESSAGE MAILBOX
*********************************************************************************************************
*/
OS_EVENT *OSMboxCreate(void *msg)
{
OS_EVENT *pevent;
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->OSEventPtr = msg; /* Deposit message in event control block */
pevent->OSEventGrp = 0x00; /* Initialize rest of event control block */
pevent->OSEventTbl[0] = 0x00;
pevent->OSEventTbl[1] = 0x00;
pevent->OSEventTbl[2] = 0x00;
pevent->OSEventTbl[3] = 0x00;
pevent->OSEventTbl[4] = 0x00;
pevent->OSEventTbl[5] = 0x00;
pevent->OSEventTbl[6] = 0x00;
pevent->OSEventTbl[7] = 0x00;
}
return (pevent); /* Return pointer to event control block */
}
/*
*********************************************************************************************************
* PEND ON MAILBOX FOR A MESSAGE
*********************************************************************************************************
*/
void *OSMboxPend(OS_EVENT *pevent, UWORD timeout, UBYTE *err)
{
void *msg;
OS_ENTER_CRITICAL();
if ((msg = pevent->OSEventPtr) != (void *)0) { /* See if there is already a message */
pevent->OSEventPtr = (void *)0; /* Clear the mailbox */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
} else {
OSTCBCur->OSTCBStat = OS_STAT_MBOX; /* Message not available, task will pend */
OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */
OSTCBCur->OSTCBEventPtr = pevent; /* Store pointer to event control block in TCB */
if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { /* Task no longer ready */
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_MBOX) { /* If status is not OS_STAT_RDY, timeout occured */
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;
msg = (void *)0; /* Set message contents to NULL */
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; /* Indicate that a timeout occured */
} else {
msg = pevent->OSEventPtr; /* Message received */
pevent->OSEventPtr = (void *)0; /* Clear the mailbox */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
}
return (msg); /* Return the message received (or NULL) */
}
/*
*********************************************************************************************************
* POST MESSAGE TO A MAILBOX
*********************************************************************************************************
*/
UBYTE OSMboxPost(OS_EVENT *pevent, void *msg)
{
OS_ENTER_CRITICAL();
if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already contain a msg */
OS_EXIT_CRITICAL();
return (OS_MBOX_FULL);
} else {
pevent->OSEventPtr = msg; /* Place message in mailbox */
if (pevent->OSEventGrp) { /* See if any task pending on mailbox */
OS_EXIT_CRITICAL();
OSEventTaskResume(pevent); /* Resume highest priority task pending on mailbox */
OSSched(); /* Find highest priority task ready to run */
} else {
OS_EXIT_CRITICAL();
}
return (OS_NO_ERR);
}
}
/*
*********************************************************************************************************
* INITIALIZE MESSAGE QUEUE
*********************************************************************************************************
*/
OS_EVENT *OSQCreate(void **start, UBYTE size)
{
OS_EVENT *pevent;
OS_Q *pq;
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) { /* See if we have an event control block */
OS_ENTER_CRITICAL(); /* Get a free queue control block */
pq = OSQFreeList;
if (OSQFreeList != (OS_Q *)0) {
OSQFreeList = OSQFreeList->OSQPtr;
}
OS_EXIT_CRITICAL();
if (pq != (OS_Q *)0) { /* See if we were able to get a queue control block */
pq->OSQStart = start; /* Yes, initialize the queue */
pq->OSQEnd = &start[size];
pq->OSQIn = start;
pq->OSQOut = start;
pq->OSQSize = size;
pq->OSQEntries = 0;
pevent->OSEventPtr = pq;
pevent->OSEventGrp = 0x00; /* Initialize rest of event control block */
pevent->OSEventTbl[0] = 0x00;
pevent->OSEventTbl[1] = 0x00;
pevent->OSEventTbl[2] = 0x00;
pevent->OSEventTbl[3] = 0x00;
pevent->OSEventTbl[4] = 0x00;
pevent->OSEventTbl[5] = 0x00;
pevent->OSEventTbl[6] = 0x00;
pevent->OSEventTbl[7] = 0x00;
} else { /* No, since we couldn't get a queue control block */
OS_ENTER_CRITICAL(); /* Return event control block on error */
pevent->OSEventPtr = (void *)OSEventFreeList;
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
pevent = (OS_EVENT *)0;
}
}
return (pevent);
}
/*
*********************************************************************************************************
* PEND ON A QUEUE FOR A MESSAGE
*********************************************************************************************************
*/
void *OSQPend(OS_EVENT *pevent, UWORD timeout, UBYTE *err)
{
void *msg;
OS_Q *pq;
OS_ENTER_CRITICAL();
pq = pevent->OSEventPtr; /* Point at queue control block */
if (pq->OSQEntries != 0) { /* See if any messages in the queue */
msg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */
pq->OSQEntries--; /* Update the number of entries in the queue */
if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */
pq->OSQOut = pq->OSQStart;
}
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
} else {
OSTCBCur->OSTCBStat = OS_STAT_Q; /* Task will have to pend for a message to be posted */
OSTCBCur->OSTCBDly = timeout; /* Load timeout into TCB */
OSTCBCur->OSTCBEventPtr = pevent; /* Store pointer to event control block in TCB */
if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { /* Task no longer ready */
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) { /* Timeout occured if status indicates pending on Q */
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; /* No message received */
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; /* Indicate a timeout occured */
} else {
msg = *pq->OSQOut++; /* Message received, extract from queue */
pq->OSQEntries--; /* Update the number of entries in the queue */
if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */
pq->OSQOut = pq->OSQStart;
}
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
} /* Return message received (or NULL) */
return (msg);
}
/*
*********************************************************************************************************
* POST MESSAGE TO A QUEUE
*********************************************************************************************************
*/
UBYTE OSQPost(OS_EVENT *pevent, void *msg)
{
OS_Q *pq;
OS_ENTER_CRITICAL();
pq = pevent->OSEventPtr; /* Point to queue control block */
if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */
OS_EXIT_CRITICAL();
return (OS_Q_FULL);
} else {
*pq->OSQIn++ = msg; /* Insert message into queue */
pq->OSQEntries++; /* Update the number of entries in the queue */
if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN pointer if we are at the end of the queue */
pq->OSQIn = pq->OSQStart;
}
if (pevent->OSEventGrp) { /* See if any task pending on queue */
OS_EXIT_CRITICAL();
OSEventTaskResume(pevent); /* Yes, resume highest priority task pending on queue */
OSSched(); /* Find highest priority task ready to run */
} else {
OS_EXIT_CRITICAL();
}
return (OS_NO_ERR);
}
}
/*
*********************************************************************************************************
* MAKE TASK WAITING FOR EVENT READY TO RUN
*********************************************************************************************************
*/
static void OSEventTaskResume(OS_EVENT *pevent)
{
OS_TCB *ptcb;
UBYTE x;
UBYTE y;
UBYTE bitx;
UBYTE bity;
UBYTE 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 the waiting list */
pevent->OSEventGrp &= ~bity;
}
ptcb = OSTCBPrioTbl[p]; /* Point to this task's OS_TCB */
ptcb->OSTCBDly = 0; /* Prevent OSTimeTick() from readying this task */
ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */
ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Unlink event control block from this task */
OSRdyGrp |= bity; /* Put task in the ready to run list */
OSRdyTbl[y] |= bitx;
OS_EXIT_CRITICAL();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -