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

📄 ucos.c

📁 ppc860平台上移植uc OS的实例
💻 C
📖 第 1 页 / 共 5 页
字号:
    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) {                         /* Get an event control block               */
        pevent->OSEventCnt    = cnt;                       /* Set semaphore value                      */
        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);
    } else {
        return ((OS_EVENT *)0);
    }
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                           ACCEPT SEMAPHORE
*
* Description: This function checks the semaphore to see if the resource is available or if an event
*              occurred.  Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
*              resource is not available or the event did not occur.
* Arguments  : 'pevent'   is a pointer to the event control block
* Returns    : >  0       if the resource is available or the event did not occur
*                         the semaphore is decremented so the next time OSSemAccept() is called, the
*                         resource will no longer be available.
*              == 0       if the resource is not available or the event did not occur
*********************************************************************************************************
*/

UWORD OSSemAccept(OS_EVENT *pevent)
{
    UWORD cnt;


    OS_ENTER_CRITICAL();
    cnt = pevent->OSEventCnt;
    if (cnt > 0) {                               /* See if resource is available                       */
        pevent->OSEventCnt--;                    /* Yes, decrement semaphore and notify caller         */
    }
    OS_EXIT_CRITICAL();
    return (cnt);                                /* Return semaphore count                             */
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                           PEND ON SEMAPHORE
*********************************************************************************************************
*/

void OSSemPend(OS_EVENT *pevent, UWORD timeout, UBYTE *err)
{
    OS_ENTER_CRITICAL();
    if (pevent->OSEventCnt > 0) {                     /* If sem. is positive, resource available ...   */
        pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
        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 ECB 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         */
        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 that didn't get event within TO      */
        } else {
            OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
            OS_EXIT_CRITICAL();
            *err = OS_NO_ERR;
        }
    }
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                         POST TO A SEMAPHORE
*********************************************************************************************************
*/

UBYTE OSSemPost(OS_EVENT *pevent)
{
    OS_TCB *ptcb;
    UBYTE   x;
    UBYTE   y;
    UBYTE   bitx;
    UBYTE   bity;
    UBYTE   p;


    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp) {                         /* See if any task waiting for semaphore         */
        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->OSTCBEventPtr  = (OS_EVENT *)0;         /* Unlink event control block from this task     */
        ptcb->OSTCBStat     &= ~OS_STAT_SEM;          /* 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->OSEventCnt < 65535) {             /* Make sure semaphore will not overflow         */
            pevent->OSEventCnt++;                     /* Increment semaphore count to register event   */
            OS_EXIT_CRITICAL();
            return (OS_NO_ERR);
        } else {                                      /* Semaphore value has reached its maximum       */
            OS_EXIT_CRITICAL();
            return (OS_SEM_OVF);
        }
    }
}
#endif
/*$PAGE*/
#if OS_MBOX_EN
/*
*********************************************************************************************************
*                                      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              */
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                     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  : 'pevent'      is a pointer to the event control block
* Returns    : != (void *)0  is the message in the mailbox if one is available.  The mailbox is cleared
*                            so the next time OSMboxAccept() is called, the mailbox will be empty.
*              == (void *)0  if the mailbox is empty
*********************************************************************************************************
*/

void *OSMboxAccept(OS_EVENT *pevent)
{
    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();
    return (msg);                                     /* Return the message received (or NULL)         */
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                      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 ((msg = OSTCBCur->OSTCBMsg) != (void *)0) {     /* See if we were given the message         */
            OSTCBCur->OSTCBMsg      = (void *)0;           /* Yes, clear message received              */
            OSTCBCur->OSTCBStat     = OS_STAT_RDY;
            OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;       /* No longer waiting for event              */
            OS_EXIT_CRITICAL();
            *err                    = OS_NO_ERR;
        } else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) {   /* If status is not OS_STAT_RDY, timed out  */
            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;
            OS_EXIT_CRITICAL();
            msg                     = (void *)0;           /* Set message contents to NULL             */
            *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)    */
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                       POST MESSAGE TO A MAILBOX
*********************************************************************************************************
*/

UBYTE OSMboxPost(OS_EVENT *pevent, void *msg)
{

⌨️ 快捷键说明

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