📄 ucos.c
字号:
psema->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;
/* Put task in waiting list */
psema->OSEventGrp |= OSTCBCur->OSTCBBitY;
}
}
if(pmail && !sema_avail)
{
OS_ENTER_CRITICAL();
if ((msg = pmail->OSEventPtr) != (void *)0)
{ /* See if there is already a message */
if(pmail->OSMailAckLink == OS_DONT_USE_ACK)
{ /* chk for using ack with sender */
pmail->OSEventPtr = (void *)0; /* Clear the mailbox */
}
if ((psema) &&
((psema->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX)==0))
{ /* Remove task because mail already received */
psema->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
}
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
mbox_avail = TRUE;
} else
{
OSTCBCur->OSTCBStat = OS_STAT_MBOX;
/* Message not available, task will pend */
OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */
OSTCBCur->OSTCBEvent2Ptr = pmail;
/* Store pointer to event control block in TCB */
if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0)
{ /* Task no longer ready */
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
if(psema)
OSTCBCur->OSTCBStat = OS_STAT_MEVNT;
pmail->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;
/* Put task in waiting list */
pmail->OSEventGrp |= OSTCBCur->OSTCBBitY;
}
OS_EXIT_CRITICAL();
}
if (!(sema_avail | mbox_avail))
{
OSSched(); /* Find next highest priority task ready to run */
OS_ENTER_CRITICAL();
if ((OSTCBCur->OSTCBStat == OS_STAT_MEVNT)||
(OSTCBCur->OSTCBStat == OS_STAT_SEM) ||
(OSTCBCur->OSTCBStat == OS_STAT_MBOX))
{ /* Must have timed out if still waiting for event */
if(pmail)
if((pmail->OSEventTbl[OSTCBCur->OSTCBY]
&= ~OSTCBCur->OSTCBBitX) == 0)
{
pmail->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
}
if((psema->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0)
{
psema->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set status to ready */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
/* Task is no longer waiting for the event */
OSTCBCur->OSTCBEvent2Ptr = (OS_EVENT *)0;
/* Task is no longer waiting for the event */
msg = (void *)0; /* Set message contents to NULL */
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT;
/* Indicate to caller that didn't get event within TO */
} else
{
if (OSTCBCur->OSTCBStat == OS_STAT_MREC) /* mail received */
{
msg = pmail->OSEventPtr; /* Message received */
if(pmail->OSMailAckLink == OS_DONT_USE_ACK)
{ /* chk for using ack with sender */
pmail->OSEventPtr = (void *)0; /* Clear the mailbox */
}
} else if (OSTCBCur->OSTCBStat == OS_STAT_SREC) /* sema received */
{
if(pmail)
pmail->OSMailAckLink = 0; /* Clear mail link with ack */
msg = (void *)0; /* No message received sema occuured */
}
if(pmail)
if((pmail->OSEventTbl[OSTCBCur->OSTCBY]
&= ~OSTCBCur->OSTCBBitX) == 0)
{ /* remove link to mailbox */
pmail->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
}
if(psema)
if((psema->OSEventTbl[OSTCBCur->OSTCBY]
&= ~OSTCBCur->OSTCBBitX) == 0)
{ /* remove link to semaphore */
psema->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set status to ready */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
/* Task is no longer waiting for the event */
OSTCBCur->OSTCBEvent2Ptr = (OS_EVENT *)0;
/* Task is no longer waiting for the event */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
}
OS_ENTER_CRITICAL();
if((pmail->OSEventPtr == (void *)0) && (pmail->OSMailFullLink))
{ /* chk for task waiting for mail to be empty */
OSMakeReady(pmail->OSMailFullLink); /* Make task ready to run */
pmail->OSMailFullLink = 0; /* Clear mail full link */
OS_EXIT_CRITICAL();
OSSched(); /* Find next highest priority task ready to run */
}
OS_EXIT_CRITICAL();
return (msg); /* Return the message received (or NULL) */
}
#endif /*USE_MULTI_EVENTS*/
/*$PAGE*/
/*
******************************************************************************
* Makes task waiting Ready
******************************************************************************
*/
static void OSMakeReady(BYTE prdy)
{
OSRdyGrp |= OSMapTbl[prdy >> 3]; /* Make task ready to run */
OSRdyTbl[prdy >> 3] |= OSMapTbl[prdy & 0x07];
}
#if USE_QUEUE
/*
******************************************************************************
* INITIALIZE MESSAGE QUEUE
******************************************************************************
*/
OS_EVENT *OSQCreate(void **start, BYTE 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);
}
/*$PAGE*/
/*
******************************************************************************
* PEND ON A QUEUE FOR A MESSAGE
******************************************************************************
*/
void *OSQPend(OS_EVENT *pevent, WORD timeout, BYTE *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);
}
/*$PAGE*/
/*
******************************************************************************
* POST MESSAGE TO A QUEUE
******************************************************************************
*/
BYTE 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,OS_STAT_QREC);
/* Yes, resume highest priority task pending on queue */
OSSched(); /* Find highest priority task ready to run */
} else
{
OS_EXIT_CRITICAL();
}
return (OS_NO_ERR);
}
}
#endif /*USE_QUEUE*/
/*$PAGE*/
/*
******************************************************************************
* MAKE TASK WAITING FOR EVENT READY TO RUN
******************************************************************************
*/
static void OSEventTaskResume(OS_EVENT *pevent, BYTE status)
{
OS_TCB *ptcb;
BYTE x;
BYTE y;
BYTE bitx;
BYTE bity;
BYTE 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 = status;/*set Task ready to run with what event happened*/
if(status == OS_STAT_MREC)
{ /* Unlink event control block from this task */
ptcb->OSTCBEvent2Ptr = (OS_EVENT *)0;
} else
{ /* Unlink event control block from this task */
ptcb->OSTCBEventPtr = (OS_EVENT *)0;
}
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 + -