📄 ucos.c
字号:
{ /* See if any task pending on semaphore */
OS_EXIT_CRITICAL();
OSEventTaskResume(pevent,OS_STAT_SREC);
/* 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);
}
}
/*$PAGE*/
#endif /*USE_SEMA*/
#if USE_SEMA
#ifndef USE_MULTI_EVENTS
/*
******************************************************************************
* PEND ON SEMAPHORE
******************************************************************************
*/
void OSSemPend(OS_EVENT *pevent, WORD timeout, BYTE *err)
{
OS_ENTER_CRITICAL();
if (pevent->OSEventCnt-- > 0)
{ /* If semaphore is positive, resource available */
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 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_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 to caller that didn't get event within TO */
} else
{
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
}
}
#endif
#endif /*USE_SEMA*/
/*$PAGE*/
#if USE_MAIL
/*
******************************************************************************
* 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;
pevent->OSMailAckLink = 0; /* Clear mail link with ack */
pevent->OSMailFullLink = 0; /* Clear mail full link */
}
return (pevent); /* Return pointer to event control block */
}
/*
******************************************************************************
* 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 : 'pmail' is a pointer to the event control block(mailbox)
* Returns : The message in the mailbox if one is available or 0 if empty.
******************************************************************************
*/
void *OSMboxAccept(OS_EVENT *pmail)
{
void *msg;
OS_ENTER_CRITICAL();
if((msg = pmail->OSEventPtr) != (void *)0) /* check for messages */
{
if(pmail->OSMailAckLink == OS_DONT_USE_ACK)
{ /* chk for using ack with sender */
pmail->OSEventPtr = (void *)0; /* clear mailbox */
if(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);
}
/*$PAGE*/
/*
******************************************************************************
* POST MESSAGE TO A MAILBOX
******************************************************************************
*/
void OSMboxPost(OS_EVENT *pmail, void *msg, BYTE p, BYTE useAck)
/* pmail is pointer to mailbox */
/* msg is pointer to message to be sent */
/* p is priority of the sender */
/* useAck is to indicate the use of acking a mail message */
{
OS_ENTER_CRITICAL();
if (pmail->OSEventPtr != (void *)0)
{ /* Make sure mailbox doesn't already contain a msg */
if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0)
{ /* Remove task from ready list to wait mail empty */
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
pmail->OSMailFullLink = p; /* save priority link for ack */
OS_EXIT_CRITICAL();
OSSched(); /* Find highest priority task ready to run */
}
OS_ENTER_CRITICAL();
pmail->OSEventPtr = msg; /* Place message in mailbox */
if (pmail->OSEventGrp)
{ /* See if any task pending on mailbox */
OS_EXIT_CRITICAL();
if(useAck)
{
OS_ENTER_CRITICAL();
pmail->OSMailAckLink = p; /* save priority link for ack */
if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0)
{ /* Remove task from ready list to wait for ack of mail */
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
}
OSEventTaskResume(pmail,OS_STAT_MREC);/* Resume highest priority
task pending on mailbox */
OSSched(); /* Find highest priority task ready to run */
} else
{
OS_EXIT_CRITICAL();
if(useAck)
{
OS_ENTER_CRITICAL();
pmail->OSMailAckLink = p; /* save priority link for ack */
if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0)
{ /* Remove task from ready list to wait for ack of mail */
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
OS_EXIT_CRITICAL();
OSSched(); /* Find highest priority task ready to run */
}
}
}
/*
******************************************************************************
* ACK MAIL
******************************************************************************
*/
void OSMailAck(OS_EVENT *pmail)
{
OS_ENTER_CRITICAL();
if(pmail->OSMailAckLink)
{ /* if no mail link then ack has not been used */
pmail->OSEventPtr = (void *)0; /* Clear the mailbox */
OSMakeReady(pmail->OSMailAckLink); /* Make task ready to run */
pmail->OSMailAckLink = 0; /* Clear mail link with ack */
if(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 highest priority task ready to run */
}
OS_EXIT_CRITICAL();
}
#endif /*USE_MAIL*/
#if USE_MAIL
#ifndef USE_MULTI_EVENTS
/*$PAGE*/
/*
******************************************************************************
* PEND ON MAILBOX FOR A MESSAGE
******************************************************************************
*/
void *OSMboxPend(OS_EVENT *pevent, WORD timeout, BYTE *err)
{
void *msg;
OS_ENTER_CRITICAL();
if ((msg = pevent->OSEventPtr) != (void *)0)
{ /* See if there is already a message */
if(pevent->OSMailAckLink == OS_DONT_USE_ACK)
{ /* chk for using ack with sender */
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->OSTCBEvent2Ptr = 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->OSTCBEvent2Ptr = (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 */
if(pevent->OSMailAckLink == OS_DONT_USE_ACK)
{ /* chk for using ack with sender */
pevent->OSEventPtr = (void *)0; /* Clear the mailbox */
}
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
}
OS_ENTER_CRITICAL();
if((pevent->OSEventPtr == (void *)0) && (pevent->OSMailFullLink))
{ /* chk for task waiting for mail to be empty */
OSMakeReady(pevent->OSMailFullLink); /* Make task ready to run */
pevent->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
#endif /*USE_MAIL*/
#if USE_MULTI_EVENTS
/*
*******************************************************************************
* PEND ON MULTI-EVENTS
*******************************************************************************
*/
void *OSEventPend(OS_EVENT *psema,OS_EVENT *pmail,WORD timeout,BYTE *err)
{
void *msg;
BYTE sema_avail;
BYTE mbox_avail;
sema_avail = FALSE;
mbox_avail = FALSE;
if(psema)
{
OS_ENTER_CRITICAL();
if (psema->OSEventCnt-- > 0)
{ /* If semaphore is positive, resource available */
msg = (void *)0; /* No message received sema occuured */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
sema_avail = TRUE;
} 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 = psema;
/* Store pointer to event control block in TCB */
if(!pmail)
if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0)
{ /* Task no longer ready */
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -