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

📄 ucos.c

📁 ucos在摩托罗拉16位微控制器68hc16上的移植
💻 C
📖 第 1 页 / 共 3 页
字号:
UBYTE OSSemPost(OS_EVENT *pevent)
{
    OS_ENTER_CRITICAL();
    if (pevent->OSEventCnt < 32766) {            /* Make sure semaphore will not overflow              */
        if (pevent->OSEventCnt++ >= 0) {
            OS_EXIT_CRITICAL();
        } else {                                 /* Negative semaphore value means task(s) pending     */
            if (pevent->OSEventGrp) {            /* See if any task pending on semaphore               */
                OS_EXIT_CRITICAL();
                OSEventTaskResume(pevent);       /* 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);
    }
}

/*
*********************************************************************************************************
*                                      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              */
}

/*
*********************************************************************************************************
*                                      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 (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->OSTCBEventPtr = (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                         */
            pevent->OSEventPtr      = (void *)0;           /* Clear the mailbox                        */
            OS_EXIT_CRITICAL();
            *err                    = OS_NO_ERR;
        }
    }
    return (msg);                                     /* Return the message received (or NULL)         */
}

/*
*********************************************************************************************************
*                                       POST MESSAGE TO A MAILBOX
*********************************************************************************************************
*/

UBYTE OSMboxPost(OS_EVENT *pevent, void *msg)
{
    OS_ENTER_CRITICAL();
    if (pevent->OSEventPtr != (void *)0) {       /* Make sure mailbox doesn't already contain a msg    */
        OS_EXIT_CRITICAL();
        return (OS_MBOX_FULL);
    } else {
        pevent->OSEventPtr = msg;                /* Place message in mailbox                           */
        if (pevent->OSEventGrp) {                /* See if any task pending on mailbox                 */
            OS_EXIT_CRITICAL();
            OSEventTaskResume(pevent);           /* Resume highest priority task pending on mailbox    */
            OSSched();                           /* Find highest priority task ready to run            */
        } else {
            OS_EXIT_CRITICAL();
        }
        return (OS_NO_ERR);
    }
}

/*
*********************************************************************************************************
*                                       INITIALIZE MESSAGE QUEUE
*********************************************************************************************************
*/

OS_EVENT *OSQCreate(void **start, UBYTE 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);
}

/*
*********************************************************************************************************
*                                     PEND ON A QUEUE FOR A MESSAGE
*********************************************************************************************************
*/

void *OSQPend(OS_EVENT *pevent, UWORD timeout, UBYTE *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);
}

/*
*********************************************************************************************************
*                                        POST MESSAGE TO A QUEUE
*********************************************************************************************************
*/

UBYTE 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);           /* Yes, resume highest priority task pending on queue */
            OSSched();                           /* Find highest priority task ready to run            */
        } else {
            OS_EXIT_CRITICAL();
        }
        return (OS_NO_ERR);
    }
}

/*
*********************************************************************************************************
*                              MAKE TASK WAITING FOR EVENT READY TO RUN
*********************************************************************************************************
*/

static void OSEventTaskResume(OS_EVENT *pevent)
{
    OS_TCB *ptcb;
    UBYTE   x;
    UBYTE   y;
    UBYTE   bitx;
    UBYTE   bity;
    UBYTE   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      =  OS_STAT_RDY;              /* Task is ready to run                          */
    ptcb->OSTCBEventPtr  = (OS_EVENT *)0;             /* Unlink event control block from this task     */
    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 + -