📄 os_q.c
字号:
OS_EXIT_CRITICAL();
return (OS_Q_FULL);
}
if (pq->OSQOut == pq->OSQStart)
{ /* 检查边界 */
pq->OSQOut = pq->OSQEnd;
}
pq->OSQOut--;
*pq->OSQOut = msg; /* 把消息插入队列 */
pq->OSQEntries++; /* 增加队列中的消息数 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 发送消息到队列
*
* 函数描述: 该函数发送一个消息到队列。该函数减少了代码量因为它能代替OSQPost() 和 OSQPostFront()。同时,该
* 函数广播发送消息给所有等待消息队列的任务。
*
* 输入参数 : pevent 指向带有期望队列的ECB的指针
*
* msg 指向发送消息的指针. 不要发送空指针
*
* opt 发送的类型:
* OS_POST_OPT_NONE 发送给单独的等待任务 (与 OSQPost()功能一致)
* OS_POST_OPT_BROADCAST 发送给所有正等待消息队列的任务
* OS_POST_OPT_FRONT 作为 LIFO 发送 (近似 OSQPostFront())
*
* 下面是这些标志的所有可能组合的列表:
*
* 1) OS_POST_OPT_NONE
* 与 OSQPost()一致
*
* 2) OS_POST_OPT_FRONT
* 与 OSQPostFront() 一致
*
* 3) OS_POST_OPT_BROADCAST
* 与 OSQPost()一致,而且还有广播给所有等待的任务的消息。
*
* 4) OS_POST_OPT_FRONT + OS_POST_OPT_BROADCAST
* 与OSQPostFront()一致,而且还有广播给所有等待的任务的消息
*
* 返回值 : OS_NO_ERR 调用成功,消息被发送
* OS_Q_FULL 队列由于满不接收更多的消息
* OS_ERR_EVENT_TYPE 没有传递一个指向队列的指针
* OS_ERR_PEVENT_NULL 'pevent' 是一个空指针
* OS_ERR_POST_NULL_PTR 发送一个空指针
*
* 警告 : 如果广播发送,中断将禁止较长时间。事实上,中断禁止时间正比于等待消息队列的任务的数量。
*********************************************************************************************************
*/
#if OS_Q_POST_OPT_EN > 0
INT8U OSQPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0)
{ /* 无效的 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0)
{ /* 没有发送一个空指针 */
return (OS_ERR_POST_NULL_PTR);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q)
{ /* 无效的事件块类型 */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) /* 看是否任务正在等待消息队列 */
{
if ((opt & OS_POST_OPT_BROADCAST) != 0x00) /* 需要广播发送吗? */
{
while (pevent->OSEventGrp != 0x00)
{ /* 是,广播发送给所有等待消息队列的任务,在相应的TCB中放消息 */
OS_EventTaskRdy(pevent, msg, OS_STAT_Q);
}
}
else
{
OS_EventTaskRdy(pevent, msg, OS_STAT_Q); /* 不,发送给等待队列的HPT,在其TCB中放消息 */
}
OS_EXIT_CRITICAL();
OS_Sched(); /* 寻找最高优先级就绪运行 */
return (OS_NO_ERR);
}
pq = (OS_Q *)pevent->OSEventPtr; /* 指向QCB */
if (pq->OSQEntries >= pq->OSQSize)
{ /* 检查消息是否已满? */
OS_EXIT_CRITICAL();
return (OS_Q_FULL);
}
if ((opt & OS_POST_OPT_FRONT) != 0x00) /* 是否发送到队列的前端? */
{
if (pq->OSQOut == pq->OSQStart)
{ /* 是, 以后进先出发送 ... */
pq->OSQOut = pq->OSQEnd; /* 如果取队列为头,调整取队列指针为尾 */
}
pq->OSQOut--;
*pq->OSQOut = msg; /* 把消息插入队列 */
}
else
{ /* 否, 以先入先出发送 */
*pq->OSQIn++ = msg; /* 把消息插入队列 */
if (pq->OSQIn == pq->OSQEnd)
{ /* 如果插入指针为尾,调整插入指针为头 */
pq->OSQIn = pq->OSQStart;
}
}
pq->OSQEntries++; /* 增加队列中的消息数 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 查询消息队列
*
* 函数描述: 该函数得到消息队列的信息
*
* 输入参数 : pevent 指向带有期望队列的ECB的指针
*
* pdata 指向包含消息队列的数据结构的指针
*
* 返回值 : OS_NO_ERR 调用成功,消息被发送
* OS_ERR_EVENT_TYPE 从一个非消息队列中获取信息
* OS_ERR_PEVENT_NULL 'pevent' 是一个空指针
*********************************************************************************************************
*/
#if OS_Q_QUERY_EN > 0
INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_Q *pq;
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_Q)
{ /* 无效的事件块类型 */
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
pq = (OS_Q *)pevent->OSEventPtr;
if (pq->OSQEntries > 0)
{
pdata->OSMsg = *pq->OSQOut; /* 如果有效得到下一条消息返回 */
}
else
{
pdata->OSMsg = (void *)0;
}
pdata->OSNMsgs = pq->OSQEntries;
pdata->OSQSize = pq->OSQSize;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif /* OS_Q_QUERY_EN */
/*$PAGE*/
/*
*********************************************************************************************************
* 初始化队列
*
* 函数描述 : 该函数由 uC/OS-II 调用初始化消息队列。应用程序不必调用。
*
* 输入参数 : 无
*
* 返回值 : 无
*
*********************************************************************************************************
*/
void OS_QInit (void)
{
#if OS_MAX_QS == 1
OSQFreeList = &OSQTbl[0]; /* 只有一个队列 */
OSQFreeList->OSQPtr = (OS_Q *)0;
#endif
#if OS_MAX_QS >= 2
INT16U i;
OS_Q *pq1;
OS_Q *pq2;
pq1 = &OSQTbl[0];
pq2 = &OSQTbl[1];
for (i = 0; i < (OS_MAX_QS - 1); i++)
{ /* 初始化空余QCB */
pq1->OSQPtr = pq2;
pq1++;
pq2++;
}
pq1->OSQPtr = (OS_Q *)0;
OSQFreeList = &OSQTbl[0];
#endif
}
#endif /* OS_Q_EN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -