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

📄 ucos.c

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