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

📄 os_mutex.c

📁 ucos_ii在S3C2410上的移植
💻 C
📖 第 1 页 / 共 2 页
字号:
*
* 函数描述: 该函数等待互斥型信号量.
*
* 输入参数  : pevent        指向带有期望的互斥型信号量的ECB的指针
*
*             timeout       选择延时时间。如果非0,则任务等待资源指定的延时时间。如果为0,则任务一直等到
*                           资源有效或事件发生为止.
*
*             err           指向下列值之一的出错代码的指针。可能值:
*                           OS_NO_ERR          调用成功,任务占有互斥型信号量
*                           OS_TIMEOUT         指定时间内,互斥型信号量无效.
*                           OS_ERR_EVENT_TYPE  没有传递指向互斥型信号量的指针
*                           OS_ERR_PEVENT_NULL 'pevent' 是一个空指针
*                           OS_ERR_PEND_ISR    从ISR中调用该函数,会导致任务挂起。
*
* 返回值  : 无
*
* 注释    : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex.
*           2) You MUST NOT change the priority of the task that owns the mutex
*********************************************************************************************************
*/
void  OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                                             /* 为CPU状态寄存器分配存储变量 */
    OS_CPU_SR  cpu_sr;
#endif    
    INT8U      pip;                                                                     /*  (PIP)      */
    INT8U      mprio;                                               /* 互斥型信号量占有者的优先级      */
    BOOLEAN    rdy;                                                          /* 任务就绪标志           */
    OS_TCB    *ptcb;


    if (OSIntNesting > 0) 
    {                                                                      /* 看是否从 ISR中调用 ...   */
        *err = OS_ERR_PEND_ISR;                            /* ... 从ISR中不能挂起一个互斥型信号量      */
        return;
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) 
    {                                                                     /* 无效的 'pevent'           */
        *err = OS_ERR_PEVENT_NULL;
        return;
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) 
    {                                                                         /* 无效的事件控制块      */
        *err = OS_ERR_EVENT_TYPE;
        return;
    }
#endif
    OS_ENTER_CRITICAL();								                /* 互斥型信号量有效吗?        */
    if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) 
    {
        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;                    /* 是, 得到资源                */
        pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;                     /*      保存任务的优先级        */
        pevent->OSEventPtr  = (void *)OSTCBCur;                        /*      指向任务的 OS_TCB       */
        OS_EXIT_CRITICAL();
        *err  = OS_NO_ERR;
        return;
    }
    pip   = (INT8U)(pevent->OSEventCnt >> 8);                     /*   无效, 从互斥型信号量中得到PIP   */
    mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);  /*   得到互斥型信号量占有者的优先级  */
    ptcb  = (OS_TCB *)(pevent->OSEventPtr);                       /*   指向互斥型信号量占有者的TCB     */
    
    if (ptcb->OSTCBPrio != pip && mprio > OSTCBCur->OSTCBPrio) /* 高优先级任务剥夺了低优先级任务的CPU了吗?..*/
                                                                      /*...需要提升占有者的优先级吗?   */
    {                                                             
        if ((OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) != 0x00) /* 需要提升优先级,看互斥型信号量占有  */
                                                                              /*   者是否准备就绪? */
        {                                                       
                                                                  
            if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00)  /*是, 从当前优先级就绪列表中...*/
             {                                                              /* ...移除占有者,可以运行 */
               OSRdyGrp &= ~ptcb->OSTCBBitY;
             }
            rdy = TRUE;
        } 
        else 
        {
            rdy = FALSE;                                          /* 没有                              */
        }
        ptcb->OSTCBPrio         = pip;                        /* 改变占有者的任务优先级到 PIP          */
        ptcb->OSTCBY            = ptcb->OSTCBPrio >> 3;
        ptcb->OSTCBBitY         = OSMapTbl[ptcb->OSTCBY];
        ptcb->OSTCBX            = ptcb->OSTCBPrio & 0x07;
        ptcb->OSTCBBitX         = OSMapTbl[ptcb->OSTCBX];
        if (rdy == TRUE) 
        {                                                           /* 如果任务在占有者的优先级就绪 ...*/
            OSRdyGrp               |= ptcb->OSTCBBitY;                /* ... 在新优先级使它就绪.       */
            OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
        }
        OSTCBPrioTbl[pip]       = (OS_TCB *)ptcb;
    }
    
    OSTCBCur->OSTCBStat |= OS_STAT_MUTEX;                        /* 互斥型信号量无效,挂起当前任务     */
    OSTCBCur->OSTCBDly   = timeout;                              /* 在当前任务的TCB中存储延时时间      */
    OS_EventTaskWait(pevent);                                    /* 挂起任务直到事件发生或延时时间到   */
    OS_EXIT_CRITICAL();
    OS_Sched();                                                      /* 寻找最高优先级就绪运行         */
    OS_ENTER_CRITICAL();
    if (OSTCBCur->OSTCBStat & OS_STAT_MUTEX) 
    {                                                                        /* 如果仍等待事件则必延时 */
        OS_EventTO(pevent);
        OS_EXIT_CRITICAL();
        *err = OS_TIMEOUT;                                     /* 显示在延时时间内未得到互斥型信号量   */
        return;
    }
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
    OS_EXIT_CRITICAL();
    *err = OS_NO_ERR;
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                  发送一个互斥型信号量
*
* 函数描述: 该函数发送一个互斥型信号量
*
* 输入参数: pevent          指向带有期望的互斥型信号量的ECB的指针
*
* 返回值 :  OS_NO_ERR               调用成功以及互斥型信号量被发送
*           OS_ERR_EVENT_TYPE       没有传递一个互斥型信号量指针
*           OS_ERR_PEVENT_NULL      'pevent' 是一个空指针
*           OS_ERR_POST_ISR         试图从ISR 中发送互斥型信号量 (对互斥型信号量来说,无效)
*           OS_ERR_NOT_MUTEX_OWNER  发送互斥型信号量的任务不是互斥型信号量的占有者
*********************************************************************************************************
*/

INT8U  OSMutexPost (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3                                        /* 为CPU状态寄存器分配存储变量      */
    OS_CPU_SR  cpu_sr;
#endif    
    INT8U      pip;                                                                          /* PIP    */
    INT8U      prio;


    if (OSIntNesting > 0) 
    {                                                                     /* 看是否从 ISR中调用 ...    */
        return (OS_ERR_POST_ISR);                                 /* 从ISR中不能发送一个互斥型信号量   */
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0)
     {                                                                            /* 无效的 'pevent'   */
        return (OS_ERR_PEVENT_NULL);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) 
    {                                                                             /* 无效的事件控制块  */
        return (OS_ERR_EVENT_TYPE);
    }                                                 
#endif
    OS_ENTER_CRITICAL();
    pip  = (INT8U)(pevent->OSEventCnt >> 8);                               /* 得到互斥型信号量的PIP    */
    prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);          /* 得到占有者的原始优先级     */
    if (OSTCBCur->OSTCBPrio != pip && 
        OSTCBCur->OSTCBPrio != prio) 
        {                                                        /* 看是否正发送的任务占有互斥型信号量 */
        OS_EXIT_CRITICAL();
        return (OS_ERR_NOT_MUTEX_OWNER);
        }
    if (OSTCBCur->OSTCBPrio == pip)                                   /* 是提升的任务的优先级吗? */
     {                                                                 
         if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) /* 是,返回到原始的优先级         */
        {
            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;                         /*   从就绪表中移除PIP的占有者    */
        }
        OSTCBCur->OSTCBPrio         = prio;
        OSTCBCur->OSTCBY            = prio >> 3;
        OSTCBCur->OSTCBBitY         = OSMapTbl[OSTCBCur->OSTCBY];
        OSTCBCur->OSTCBX            = prio & 0x07;
        OSTCBCur->OSTCBBitX         = OSMapTbl[OSTCBCur->OSTCBX];
        OSRdyGrp                   |= OSTCBCur->OSTCBBitY;
        OSRdyTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;
        OSTCBPrioTbl[prio]          = (OS_TCB *)OSTCBCur;
    }
    OSTCBPrioTbl[pip] = (OS_TCB *)1;                                                   /* 保留优先级   */
    if (pevent->OSEventGrp != 0x00)
    {                                                                 /* 任务正在等待互斥型信号量吗?  */
                                                          /* 是,使等待互斥型信号量的最高优先级任务就绪 */
        prio                = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX);
        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;     /*      保存互斥型信号量的新的占有者的优先级  */
        pevent->OSEventCnt |= prio;
        pevent->OSEventPtr  = OSTCBPrioTbl[prio];              /*   链接互斥型信号量占有者的 OS_TCB    */
        OS_EXIT_CRITICAL();
        OS_Sched();                                                   /*   寻找最高优先级任务就绪运行  */
        return (OS_NO_ERR);
    }
    pevent->OSEventCnt |= OS_MUTEX_AVAILABLE;                      /* 没有,  互斥型信号量现在是可用的  */ 
    pevent->OSEventPtr  = (void *)0;
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                     查询互斥型信号量
*
* 函数描述: 该函数获得互斥型信号量信息。
*
* 输入参数  : pevent       指向带有期望的互斥型信号量的ECB的指针
*
*              pdata       指向包含互斥型信号量信息的指针
*
* 返回值    : OS_NO_ERR            成功调用以及消息发送
*             OS_ERR_QUERY_ISR     如果从 ISR中调用
*             OS_ERR_PEVENT_NULL   'pevent' 是空指针
*             OS_ERR_EVENT_TYPE    如果试图从非互斥型信号量中获得信息
*********************************************************************************************************
*/

#if OS_MUTEX_QUERY_EN > 0
INT8U  OSMutexQuery (OS_EVENT *pevent, OS_MUTEX_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3                                   /* 为CPU状态寄存器分配存储变量           */ 
    OS_CPU_SR  cpu_sr;
#endif    
    INT8U     *psrc;
    INT8U     *pdest;


    if (OSIntNesting > 0) 
    {                                                                       /* 看是否从 ISR中调用 ...  */
        return (OS_ERR_QUERY_ISR);                                  /* ... 不能从 ISR中查询信息        */
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) 
    {                                                                              /* 无效的 'pevent'  */
        return (OS_ERR_PEVENT_NULL);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) 
    {                                                                              /* 无效的事件控制块 */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    pdata->OSMutexPIP  = (INT8U)(pevent->OSEventCnt >> 8);
    pdata->OSOwnerPrio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);
    if (pdata->OSOwnerPrio == 0xFF) 
    {
        pdata->OSValue = 1;
    } 
    else 
    {
        pdata->OSValue = 0;
    }
    pdata->OSEventGrp  = pevent->OSEventGrp;                                       /* 复制等待列表     */
    psrc               = &pevent->OSEventTbl[0];
    pdest              = &pdata->OSEventTbl[0];
#if OS_EVENT_TBL_SIZE > 0
    *pdest++           = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 1
    *pdest++           = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 2
    *pdest++           = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 3
    *pdest++           = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 4
    *pdest++           = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 5
    *pdest++           = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 6
    *pdest++           = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 7
    *pdest             = *psrc;
#endif
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif                                                     /* OS_MUTEX_QUERY_EN                        */
#endif                                                     /* OS_MUTEX_EN                              */

⌨️ 快捷键说明

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