📄 ucos.c
字号:
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) { /* Get an event control block */
pevent->OSEventCnt = cnt; /* Set semaphore value */
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);
} else {
return ((OS_EVENT *)0);
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* ACCEPT SEMAPHORE
*
* Description: This function checks the semaphore to see if the resource is available or if an event
* occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
* resource is not available or the event did not occur.
* Arguments : 'pevent' is a pointer to the event control block
* Returns : > 0 if the resource is available or the event did not occur
* the semaphore is decremented so the next time OSSemAccept() is called, the
* resource will no longer be available.
* == 0 if the resource is not available or the event did not occur
*********************************************************************************************************
*/
UWORD OSSemAccept(OS_EVENT *pevent)
{
UWORD cnt;
OS_ENTER_CRITICAL();
cnt = pevent->OSEventCnt;
if (cnt > 0) { /* See if resource is available */
pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */
}
OS_EXIT_CRITICAL();
return (cnt); /* Return semaphore count */
}
/*$PAGE*/
/*
*********************************************************************************************************
* PEND ON SEMAPHORE
*********************************************************************************************************
*/
void OSSemPend(OS_EVENT *pevent, UWORD timeout, UBYTE *err)
{
OS_ENTER_CRITICAL();
if (pevent->OSEventCnt > 0) { /* If sem. is positive, resource available ... */
pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
} else { /* Otherwise, must wait until event occurs */
OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */
OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */
OSTCBCur->OSTCBEventPtr = pevent; /* Store pointer to ECB 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 */
OS_ENTER_CRITICAL();
if (OSTCBCur->OSTCBStat & OS_STAT_SEM) { /* Must have timed out if still waiting for event*/
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; /* Task is no longer waiting for the event */
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; /* Indicate that didn't get event within TO */
} else {
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* POST TO A SEMAPHORE
*********************************************************************************************************
*/
UBYTE OSSemPost(OS_EVENT *pevent)
{
OS_TCB *ptcb;
UBYTE x;
UBYTE y;
UBYTE bitx;
UBYTE bity;
UBYTE p;
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp) { /* See if any task waiting for semaphore */
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->OSTCBEventPtr = (OS_EVENT *)0; /* Unlink event control block from this task */
ptcb->OSTCBStat &= ~OS_STAT_SEM; /* Clear bit associated with event type */
if (ptcb->OSTCBStat == OS_STAT_RDY) { /* See if task is ready (could be suspended) */
OSRdyGrp |= bity; /* Put task in the ready to run list */
OSRdyTbl[y] |= bitx;
}
OS_EXIT_CRITICAL();
OSSched(); /* Find highest priority task ready to run */
return (OS_NO_ERR);
} else {
if (pevent->OSEventCnt < 65535) { /* Make sure semaphore will not overflow */
pevent->OSEventCnt++; /* Increment semaphore count to register event */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
} else { /* Semaphore value has reached its maximum */
OS_EXIT_CRITICAL();
return (OS_SEM_OVF);
}
}
}
#endif
/*$PAGE*/
#if OS_MBOX_EN
/*
*********************************************************************************************************
* 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 */
}
/*$PAGE*/
/*
*********************************************************************************************************
* ACCEPT MESSAGE FROM MAILBOX
*
* Description: This function checks the mailbox to see if a message is available. Unlike OSMboxPend(),
* OSMboxAccept() does not suspend the calling task if a message is not available.
* Arguments : 'pevent' is a pointer to the event control block
* Returns : != (void *)0 is the message in the mailbox if one is available. The mailbox is cleared
* so the next time OSMboxAccept() is called, the mailbox will be empty.
* == (void *)0 if the mailbox is empty
*********************************************************************************************************
*/
void *OSMboxAccept(OS_EVENT *pevent)
{
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();
return (msg); /* Return the message received (or NULL) */
}
/*$PAGE*/
/*
*********************************************************************************************************
* 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 ((msg = OSTCBCur->OSTCBMsg) != (void *)0) { /* See if we were given the message */
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;
} else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) { /* If status is not OS_STAT_RDY, timed out */
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;
OS_EXIT_CRITICAL();
msg = (void *)0; /* Set message contents to NULL */
*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) */
}
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO A MAILBOX
*********************************************************************************************************
*/
UBYTE OSMboxPost(OS_EVENT *pevent, void *msg)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -