📄 os_mutex.c
字号:
*
* 函数描述: 该函数等待互斥型信号量.
*
* 输入参数 : 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 + -