📄 os_sem.c
字号:
default:
OS_EXIT_CRITICAL();
*err = OS_ERR_INVALID_OPT;
return (pevent);
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 挂起信号量
*
* 函数描述: 该函数用于等待一个信号量
*
* 输入参数: pevent 指向已建有期望的信号量的ECB的指针
*
* timeout 选择延时时间。如果非0,则任务等待资源指定的延时时间。如果为0,则任务一直等到
* 资源有效或事件发生为止。
*
* err 指向下列值之一的出错代码的指针。可能值:
*
* OS_NO_ERR 调用成功,任务占有资源。或正等待事件发生。
* OS_TIMEOUT 在指定的延时时间内,没有收到信号量。
* OS_ERR_EVENT_TYPE 传递的不是信号量的指针
* OS_ERR_PEND_ISR 从ISR中调用该函数,不能挂起。
* OS_ERR_PEVENT_NULL 'pevent' 是空指针。
*
* 返回值 : 无
*********************************************************************************************************
*/
void OSSemPend(OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
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_SEM)
{ /* 无效的事件类型 */
*err = OS_ERR_EVENT_TYPE;
return;
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventCnt > 0) /* 如果信号量是正,则有效 ... */
{
pevent->OSEventCnt--; /* ... 只有为正,信号量减1. */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return;
}
/* 否则等,直到事件发生 */
OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* 资源无效, 挂起 */
OSTCBCur->OSTCBDly = timeout; /* 在TCB中写入,延时时间 */
OS_EventTaskWait(pevent); /* 挂起任务直到事件发生或延时时间到 */
OS_EXIT_CRITICAL();
OS_Sched(); /* 寻找最高优先级任务,就绪运行它 */
OS_ENTER_CRITICAL();
if (OSTCBCur->OSTCBStat & OS_STAT_SEM)
{ /* 如果仍等待事件发生,就绪任务*/
OS_EventTO(pevent);
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; /* 显示在延时时间内没有等到事件 */
return;
}
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* 将指向信号量ECB的指针从该任务的TCB中删除 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
/*$PAGE*/
/*
*********************************************************************************************************
* 发送一个信号量
*
* 函数描述: 该函数发送一个信号量
*
* 输入参数 : pevent 指向已建有期望的信号量的ECB的指针
*
* 返回值 : OS_NO_ERR 调用成功信号量被发送
* OS_SEM_OVF 信号量计数器超过限值.换句话说,信号量的发送数超过OSSemAccept()或OSSemPend()
* 等待的数目。
* OS_ERR_EVENT_TYPE 传递的不是信号量的指针
* OS_ERR_PEVENT_NULL 'pevent' 是空指针.
*********************************************************************************************************
*/
INT8U OSSemPost (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0)
{ /* 无效的 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_SEM)
{ /* 无效的事件控制块型 */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00)
{ /* 看是否有任务在等待信号量? */
OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM); /* 就绪等待事件中的最高优先级任务 */
OS_EXIT_CRITICAL();
OS_Sched(); /* 任务切换,找最高优先级任务就绪运行 */
return (OS_NO_ERR);
}
if (pevent->OSEventCnt < 65535)
{ /* 确信信号量没有溢出 */
pevent->OSEventCnt++; /* 加信号量计数器以注册事件 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL(); /* 信号量达到最大值 */
return (OS_SEM_OVF);
}
/*$PAGE*/
/*
*********************************************************************************************************
* 得到一个信号量的信息
*
* 函数描述: 该函数得到信号量的信息
*
* 输入参数 : pevent 指向已建有期望的信号量的ECB的指针
*
* pdata 包含信号量信息的指针结构
*
* 返回值 : OS_NO_ERR 调用成功信息发送
* OS_ERR_EVENT_TYPE 传递的不是信号量的指针
* OS_ERR_PEVENT_NULL 'pevent' 是空指针.
*********************************************************************************************************
*/
#if OS_SEM_QUERY_EN > 0
INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
INT8U *psrc;
INT8U *pdest;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* 无效的 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* 无效的事件控制块型 */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
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
pdata->OSCnt = pevent->OSEventCnt; /* 得到信号量计数器 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif /* OS_SEM_QUERY_EN */
#endif /* OS_SEM_EN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -