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

📄 ucos_cl.c

📁 uCOS的源码例子
💻 C
📖 第 1 页 / 共 5 页
字号:
        UBYTE   bity;
        UBYTE   p;


    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp) {                         /* See if any task pending on mailbox            */
        y    = OSUnMapTbl[pevent->OSEventGrp];        /* Find highest prio. task waiting for message   */
        bity = OSMapTbl[y];
        x    = OSUnMapTbl[pevent->OSEventTbl[y]];
        bitx = OSMapTbl[x];
        p    = (y << 3) + x;                          /* Find the priority of the task                 */
        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 task       */
        ptcb->OSTCBEventPtr  = (far OS_EVENT *)0;     /* Unlink ECB from this task                     */
        ptcb->OSTCBMsg       =  msg;                  /* Send message directly to waiting task         */
        ptcb->OSTCBStat     &= ~OS_STAT_MBOX;         /* 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->OSEventPtr != (far void *)0) {    /* Make sure mailbox doesn't already have a msg  */
            OS_EXIT_CRITICAL();
            return (OS_MBOX_FULL);
        } else {
            pevent->OSEventPtr = (far void *)msg;     /* Place message in mailbox                      */
            OS_EXIT_CRITICAL();
            return (OS_NO_ERR);
        }
    }
}
#endif
/*$PAGE*/
#if OS_Q_EN
/*
*********************************************************************************************************
*                                       INITIALIZE MESSAGE QUEUE
*********************************************************************************************************
*/

far OS_EVENT *OSQCreate(far void **start, UBYTE size)
{
    far OS_EVENT *pevent;
    far OS_Q     *pq;


    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;                    /* Get next free event control block                  */
    if (OSEventFreeList != (far OS_EVENT *)0) {  /* See if pool of free ECB pool was empty             */
        OSEventFreeList = (far OS_EVENT *)OSEventFreeList->OSEventPtr;
    }
    OS_EXIT_CRITICAL();
    if (pevent != (far OS_EVENT *)0) {           /* See if we have an event control block              */
        OS_ENTER_CRITICAL();                     /* Get a free queue control block                     */
        pq = (far OS_Q *)OSQFreeList;
        if (OSQFreeList != (far OS_Q *)0) {
            OSQFreeList = (far OS_Q *)OSQFreeList->OSQPtr;
        }
        OS_EXIT_CRITICAL();
        if (pq != (far OS_Q *)0) {               /* See if we were able to get a queue control block   */
            pq->OSQStart          = start;       /* Yes, initialize the queue                          */
            pq->OSQEnd            = (far void **)&start[size];
            pq->OSQIn             = start;
            pq->OSQOut            = start;
            pq->OSQSize           = size;
            pq->OSQEntries        = 0;
            pevent->OSEventPtr    = (far void *)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    = (far void *)OSEventFreeList;
            OSEventFreeList       = pevent;
            OS_EXIT_CRITICAL();
            pevent                = (far OS_EVENT *)0;
        }
    }
    return (pevent);
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                      ACCEPT MESSAGE FROM QUEUE
*
* Description: This function checks the queue to see if a message is available.  Unlike OSQPend(),
*              OSQAccept() does not suspend the calling task if a message is not available.
* Arguments  : 'pevent'          is a pointer to the event control block
* Returns    : != (far void *)0  is the message in the queue if one is available.  The message is removed
*                                from the so the next time OSQAccept() is called, the queue will contain
*                                one less entry.
*              == (far void *)0  if the queue is empty
*********************************************************************************************************
*/

far void *OSQAccept(far OS_EVENT *pevent)
{
    far void  *msg;
    far OS_Q  *pq;


    OS_ENTER_CRITICAL();
    pq = (far OS_Q *)pevent->OSEventPtr;         /* Point at queue control block                       */
    if (pq->OSQEntries != 0) {                   /* See if any messages in the queue                   */
        msg = (far void *)*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;
        }
    } else {
        msg = (far void *)0;                     /* Queue is empty                                     */
    }
    OS_EXIT_CRITICAL();
    return (msg);                                /* Return message received (or NULL)                  */
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                     PEND ON A QUEUE FOR A MESSAGE
*********************************************************************************************************
*/

far void *OSQPend(far OS_EVENT *pevent, UWORD timeout, UBYTE *err)
{
    far void  *msg;
    far OS_Q  *pq;


    OS_ENTER_CRITICAL();
    pq = (far OS_Q *)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 ((msg = OSTCBCur->OSTCBMsg) != (far void *)0) {
            OSTCBCur->OSTCBMsg      = (far void *)0;       /* Extract msg from TCB (Put there by QPost)*/
            OSTCBCur->OSTCBStat     = OS_STAT_RDY;         /* Set status to ready                      */
            OSTCBCur->OSTCBEventPtr = (far OS_EVENT *)0;   /* No longer waiting for event              */
            OS_EXIT_CRITICAL();
            *err                    = OS_NO_ERR;
        } else if (OSTCBCur->OSTCBStat & OS_STAT_Q) {      /* Timeout occured if 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 = (far OS_EVENT *)0;   /* No longer waiting for event              */
            OS_EXIT_CRITICAL();
            msg                     = (far void *)0;       /* No message received                      */
            *err                    = OS_TIMEOUT;          /* Indicate a timeout occured               */
        } else {
            msg = *pq->OSQOut++;                      /* Extract message 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 Q*/
                pq->OSQOut = pq->OSQStart;
            }
            OS_EXIT_CRITICAL();
            *err = OS_NO_ERR;
        }
    }
    return (msg);                                /* Return message received (or NULL)                  */
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                        POST MESSAGE TO A QUEUE
*********************************************************************************************************
*/

UBYTE OSQPost(far OS_EVENT *pevent, far void *msg)
{
    far OS_Q   *pq;
    far OS_TCB *ptcb;
        UBYTE   x;
        UBYTE   y;
        UBYTE   bitx;
        UBYTE   bity;
        UBYTE   p;


    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp) {                         /* See if any task pending on queue              */
        y    = OSUnMapTbl[pevent->OSEventGrp];        /* Find highest prio. task waiting for message   */
        bity = OSMapTbl[y];
        x    = OSUnMapTbl[pevent->OSEventTbl[y]];
        bitx = OSMapTbl[x];
        p    = (y << 3) + x;                          /* Find priority of task getting the msg         */
        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 task       */
        ptcb->OSTCBEventPtr  = (far OS_EVENT *)0;     /* Unlink ECB from this task                     */
        ptcb->OSTCBMsg       = msg;                   /* Send message directly to waiting task         */
        ptcb->OSTCBStat     &= ~OS_STAT_Q;            /* Clear bit associated with event type          */
        if (ptcb->OSTCBStat == OS_STAT_RDY) {         /* See if task is ready (could be susp'd)        */
            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 {
        pq = (far OS_Q *)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 nbr of entries in the queue        */
            if (pq->OSQIn == pq->OSQEnd) {            /* Wrap IN ptr if we are at end of queue         */
                pq->OSQIn = pq->OSQStart;
            }
            OS_EXIT_CRITICAL();
        }
        return (OS_NO_ERR);
    }
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
*                                            DUMMY FUNCTION
*********************************************************************************************************
*/
static void  OSDummy(void)
{
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -