⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ucos.c

📁 ucos 在 Intel 196 单片机上的移植
💻 C
📖 第 1 页 / 共 4 页
字号:
            {                        /* 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 + -