uC/OS-II源码解析(os_q.c)
2017-05-17 17:00
405 查看
/* ** ver : 2.52 ** file : os_q.c ** brief : 消息队列相关操作 C 文件 */ #ifndef OS_MASTER_FILE #include "includes.h" /* 包含头文件 */ #endif #if (OS_Q_EN > 0) && (OS_MAX_QS > 0) /* ********************************************************************************************** * 无等待的请求消息队列 * * breif : 该函数用于无等待的请求消息队列中的消息. * * pevent : 指向事件控制块的指针 * * Returns : != (void *)0 队列中有可用消息 * == (void *)0 未获得消息 ********************************************************************************************** */ #if OS_Q_ACCEPT_EN > 0 void *OSQAccept (OS_EVENT *pevent) { #if OS_CRITICAL_METHOD == 3 4000 OS_CPU_SR cpu_sr; #endif void *msg; OS_Q *pq; #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */ return ((void *)0); } if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* 错误的事件类型 */ return ((void *)0); } #endif OS_ENTER_CRITICAL(); pq = (OS_Q *)pevent->OSEventPtr; /* 获得队列控制块 */ if (pq->OSQEntries > 0) { /* 判断队列中是否有消息 */ msg = *pq->OSQOut++; /* 将消息取出来返回 */ pq->OSQEntries--; /* 消息数减1 */ if (pq->OSQOut == pq->OSQEnd) { /* 调整已实现循环队列 */ pq->OSQOut = pq->OSQStart; } } else { msg = (void *)0; /* 队列为空 */ } OS_EXIT_CRITICAL(); return (msg); } #endif /*$PAGE*/ /* ***************************************************************************************** * 创建消息队列 * * brief : 该函数用于创建消息队列. * * start : 消息队列的基地址.该数组必须被声明为void类型 * * void *MessageStorage[size] * * size : 消息数组的大小 * * Returns : != (OS_EVENT *)0 消息队列创建成功 * == (OS_EVENT *)0 消息队列创建失败 ***************************************************************************************** */ OS_EVENT *OSQCreate (void **start, INT16U size) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif OS_EVENT *pevent; OS_Q *pq; if (OSIntNesting > 0) { /* 不允许中断内创建消息队列 */ return ((OS_EVENT *)0); } OS_ENTER_CRITICAL(); pevent = OSEventFreeList; /* 获取事件控制块 */ if (OSEventFreeList != (OS_EVENT *)0) { /* 调整剩余事件控制块链表 */ OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; } OS_EXIT_CRITICAL(); if (pevent != (OS_EVENT *)0) { OS_ENTER_CRITICAL(); pq = OSQFreeList; /* 获取队列控制块 */ if (pq != (OS_Q *)0) { /* 存在剩余队列控制块 */ OSQFreeList = OSQFreeList->OSQPtr;/* 调整队列控制块链表 */ OS_EXIT_CRITICAL(); pq->OSQStart = start; /* 初始化队列 */ pq->OSQEnd = &start[size]; pq->OSQIn = start; pq->OSQOut = start; pq->OSQSize = size; pq->OSQEntries = 0; pevent->OSEventType = OS_EVENT_TYPE_Q; pevent->OSEventCnt = 0; pevent->OSEventPtr = pq; OS_EventWaitListInit(pevent); /* 初始化等待任务表 */ } else { /* 无可用队列控制块 */ pevent->OSEventPtr = (void *)OSEventFreeList; /* 返还事件控制块 */ OSEventFreeList = pevent; OS_EXIT_CRITICAL(); pevent = (OS_EVENT *)0; } } return (pevent); } /*$PAGE*/ /* **************************************************************************************** * 删除消息队列 * * brief : 该函数用于删除消息队列. * * pevent : 指向事件控制块的指针 * * opt : 删除选项 * opt == OS_DEL_NO_PEND 无任务等待时删除 * opt == OS_DEL_ALWAYS 无条件删除,就绪所有等待任务 * * err : 指向错误代码的指针,可能取值: * OS_NO_ERR 成功 * OS_ERR_DEL_ISR 不允许在中断中删除队列 * OS_ERR_INVALID_OPT 无效的删除选项 * OS_ERR_TASK_WAITING 有任务正在等待队列中的消息 * OS_ERR_EVENT_TYPE 错误的时间类型 * OS_ERR_PEVENT_NULL I无效的事件控制块指针 * * Returns : pevent 删除失败 * (OS_EVENT *)0 删除成功 * ***************************************************************************************** */ #if OS_Q_DEL_EN > 0 OS_EVENT *OSQDel (OS_EVENT *pevent, INT8U opt, INT8U *err) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif BOOLEAN tasks_waiting; OS_Q *pq; if (OSIntNesting > 0) { /* 不允许中断内删除 */ *err = OS_ERR_DEL_ISR; return ((OS_EVENT *)0); } #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */ *err = OS_ERR_PEVENT_NULL; return (pevent); } if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* 错误的事件类型 */ *err = OS_ERR_EVENT_TYPE; return (pevent); } #endif OS_ENTER_CRITICAL(); if (pevent->OSEventGrp != 0x00) { /* 是否有任务等待消息 */ tasks_waiting = TRUE; /* 有任务等待 */ } else { tasks_waiting = FALSE; /* 无任务等待 */ } switch (opt) { case OS_DEL_NO_PEND: /* 无任务等待删除 */ if (tasks_waiting == FALSE) { pq = (OS_Q *)pevent->OSEventPtr; /* 返还队列控制块 */ pq->OSQPtr = OSQFreeList; OSQFreeList = pq; pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* 返还事件控制块 */ OSEventFreeList = pevent; OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return ((OS_EVENT *)0); } else { OS_EXIT_CRITICAL(); *err = OS_ERR_TASK_WAITING; return (pevent); } case OS_DEL_ALWAYS: /* 无条件删除 */ while (pevent->OSEventGrp != 0x00) { /* 就绪所有等待任务 */ OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q); } pq = (OS_Q *)pevent->OSEventPtr;/* 返还队列控制块 */ pq->OSQPtr = OSQFreeList; OSQFreeList = pq; pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* 返还事件控制块 */ OSEventFreeList = pevent; OS_EXIT_CRITICAL(); if (tasks_waiting == TRUE) { OS_Sched(); /* 任务调度 */ } *err = OS_NO_ERR; return ((OS_EVENT *)0); default: OS_EXIT_CRITICAL(); *err = OS_ERR_INVALID_OPT; return (pevent); } } #endif /*$PAGE*/ /* ******************************************************************************************* * 清空消息队列 * * brief : 该函数用于清空队列内的消息 * * pevent : 指向事件控制块的指针 * * Returns : OS_NO_ERR 成功 * OS_ERR_EVENT_TYPE 错误的事件类型 * OS_ERR_PEVENT_NULL 无效的事件控制块指针 ******************************************************************************************** */ #if OS_Q_FLUSH_EN > 0 INT8U OSQFlush (OS_EVENT *pevent) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif OS_Q *pq; #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */ return (OS_ERR_PEVENT_NULL); } if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* 错误的事件类型 */ return (OS_ERR_EVENT_TYPE); } #endif OS_ENTER_CRITICAL(); pq = (OS_Q *)pevent->OSEventPtr; /* 获取队列控制块 */ pq->OSQIn = pq->OSQStart; /* 清空队列 */ pq->OSQOut = pq->OSQStart; pq->OSQEntries = 0; OS_EXIT_CRITICAL(); return (OS_NO_ERR); } #endif /*$PAGE*/ /* ********************************************************************************************** * 请求消息 * * brief : 该函数用于从消息队列中请求一则消息 * * pevent : 指向事件控制块的指针 * * timeout : 超时时限 * * err : 指向错误代码的指针,可能取值: * * OS_NO_ERR 成功 * OS_TIMEOUT 超时 * OS_ERR_EVENT_TYPE 错误的事件类型 * OS_ERR_PEVENT_NULL 无效的事件控制块指针 * OS_ERR_PEND_ISR 不能再中断中请求 * * Returns : != (void *)0 请求成功 * == (void *)0 请求失败 *********************************************************************************************** */ void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif void *msg; OS_Q *pq; if (OSIntNesting > 0) { /* 不允许中断中请求消息 */ *err = OS_ERR_PEND_ISR; return ((void *)0); } #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块 */ *err = OS_ERR_PEVENT_NULL; return ((void *)0); } if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* 错误的事件类型 */ *err = OS_ERR_EVENT_TYPE; return ((void *)0); } #endif OS_ENTER_CRITICAL(); pq = (OS_Q *)pevent->OSEventPtr; /* 获取队列控制块 */ if (pq->OSQEntries > 0) { /* 队列中是否有消息 */ msg = *pq->OSQOut++; /* 取出消息 */ pq->OSQEntries--; /* 消息数减1 */ if (pq->OSQOut == pq->OSQEnd) { /* 调整指针实现循环队列 */ pq->OSQOut = pq->OSQStart; } OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return (msg); } OSTCBCur->OSTCBStat |= OS_STAT_Q; /* 等待消息状态 */ OSTCBCur->OSTCBDly = timeout; /* 记录超时时限 */ OS_EventTaskWait(pevent); /* 使任务进入等待状态 */ OS_EXIT_CRITICAL(); OS_Sched(); /* 任务调度 */ OS_ENTER_CRITICAL(); msg = OSTCBCur->OSTCBMsg; if (msg != (void *)0) { /* 是否收到了消息 */ OSTCBCur->OSTCBMsg = (void *)0; /* 请空消息 */ OSTCBCur->OSTCBStat = OS_STAT_RDY; /* 就绪态 */ OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* 取消关联 */ OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return (msg); } OS_EventTO(pevent); /* 超时使任务就绪 */ OS_EXIT_CRITICAL(); *err = OS_TIMEOUT; /* Indicate a timeout */ return ((void *)0); } /*$PAGE*/ /* ********************************************************************************************** * 向队列发送一则消息 * * breif : 该函数用于向队列发送一则消息,由.OSQIn插入,先进先出 * * pevent : 指向事件控制块的指针 * * msg : 指向消息的指针 * * Returns : OS_NO_ERR 成功 * OS_Q_FULL 队列已满 * OS_ERR_EVENT_TYPE 错误的事件类型 * OS_ERR_PEVENT_NULL 无效的事件控制块指针 * OS_ERR_POST_NULL_PTR 发送的消息不能为空 *********************************************************************************************** */ #if OS_Q_POST_EN > 0 INT8U OSQPost (OS_EVENT *pevent, void *msg) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif OS_Q *pq; #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */ 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) { /* 是否有任务等待 */ OS_EventTaskRdy(pevent, msg, OS_STAT_Q); /* 就绪最高优先级任务 */ OS_EXIT_CRITICAL(); OS_Sched(); /* 任务调度 */ return (OS_NO_ERR); } pq = (OS_Q *)pevent->OSEventPtr; /* 获取队列控制块 */ if (pq->OSQEntries >= pq->OSQSize) { /* 队列已满 */ OS_EXIT_CRITICAL(); return (OS_Q_FULL); } *pq->OSQIn++ = msg; /* 插入消息 */ pq->OSQEntries++; /* 消息数加1 */ if (pq->OSQIn == pq->OSQEnd) { /* 调整指针实现循环队列 */ pq->OSQIn = pq->OSQStart; } OS_EXIT_CRITICAL(); return (OS_NO_ERR); } #endif /*$PAGE*/ /* ******************************************************************************************* * 向队列发送一则消息 * * breif : 该函数用于向队列发送一则消息,由.OSQOut插入,先进后出 * * pevent : 指向事件控制块的指针 * * msg : 指向消息的指针 * * Returns : OS_NO_ERR 成功 * OS_Q_FULL 队列已满 * OS_ERR_EVENT_TYPE 错误的时间类型 * OS_ERR_PEVENT_NULL 无效的事件控制块指针 * OS_ERR_POST_NULL_PTR 发送的消息不能为空 ******************************************************************************************* */ #if OS_Q_POST_FRONT_EN > 0 INT8U OSQPostFront (OS_EVENT *pevent, void *msg) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif OS_Q *pq; #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */ 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) { /* 是否有任务在等待消息 */ OS_EventTaskRdy(pevent, msg, OS_STAT_Q); /* 就绪最高级等待任务 */ OS_EXIT_CRITICAL(); OS_Sched(); /* 任务调度 */ return (OS_NO_ERR); } pq = (OS_Q *)pevent->OSEventPtr; /* 获取队列控制块 */ if (pq->OSQEntries >= pq->OSQSize) { /* 队列已满 */ OS_EXIT_CRITICAL(); return (OS_Q_FULL); } if (pq->OSQOut == pq->OSQStart) { /* 调整指针 */ pq->OSQOut = pq->OSQEnd; } pq->OSQOut--; *pq->OSQOut = msg; /* 插入消息 */ pq->OSQEntries++; /* 消息数加1 */ OS_EXIT_CRITICAL(); return (OS_NO_ERR); } #endif /*$PAGE*/ /* ******************************************************************************************* * 向队列发送一则消息 * * breif : 该函数用于向队列发送一则消息 * * pevent : 指向事件控制块的指针 * * msg : 指向消息的指针 * * opt : 发送选项,可能取值: * OS_POST_OPT_NONE 先进先出 * OS_POST_OPT_BROADCAST 广播 * OS_POST_OPT_FRONT 先进后出 * * Returns : OS_NO_ERR 成功 * OS_Q_FULL 队列已满 * OS_ERR_EVENT_TYPE 错误的事件类型 * OS_ERR_PEVENT_NULL 无效的事件控制块指针 * 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 OS_CPU_SR cpu_sr; #endif OS_Q *pq; #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */ 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) { /* 就绪所有等待任务 */ OS_EventTaskRdy(pevent, msg, OS_STAT_Q); } } else { OS_EventTaskRdy(pevent, msg, OS_STAT_Q); /* 就绪最高优先级任务 */ } OS_EXIT_CRITICAL(); OS_Sched(); /* 任务调度 */ return (OS_NO_ERR); } pq = (OS_Q *)pevent->OSEventPtr; /* 或许队列控制块 */ 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++; /* 消息数加1 */ OS_EXIT_CRITICAL(); return (OS_NO_ERR); } #endif /*$PAGE*/ /* *********************************************************************************************** * 查询队列 * * brief : 该函数用与查询消息队列信息. * * pevent : 指向事件控制块的指针 * * pdata : 指向消息队列信息的数据结构指针 * * Returns : OS_NO_ERR 成功 * OS_ERR_EVENT_TYPE 错误的事件类型 * OS_ERR_PEVENT_NULL 无效的事件控制块指针 ************************************************************************************************ */ #if OS_Q_QUERY_EN > 0 INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif OS_Q *pq; INT8U *psrc; INT8U *pdest; #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* 无效的事件控制块指针 */ 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 /*$PAGE*/ /* *************************************************************************************** * 初始化消息队列 * * brief : 被函数 OSInit() 调用去初始化消息队列,你的应用中不应该调用该函数. * **************************************************************************************** */ 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++) { /* 初始化队列控制块为单向量表 */ pq1->OSQPtr = pq2; pq1++; pq2++; } pq1->OSQPtr = (OS_Q *)0; /* 对后一个队列控制块 */ OSQFreeList = &OSQTbl[0]; /* 空队列控制块链表表头 */ #endif } #endif
相关文章推荐
- uC/OS-II源码解析(os_mbox.c)
- uC/OS-II源码解析(os_cfg.h)
- uC/OS-II源码解析(os_sem.c)
- uC/OS-II源码解析(includes.h)
- uC/OS-II源码解析(os_mutex.c)
- uC/OS-II源码解析(ucos_ii.c)
- uC/OS-II源码解析(os_mem.c)
- uC/OS-II源码解析(os_cpu_c.c)
- uC/OS-II源码解析(os_time.c)
- uC/OS-II源码解析(os_cpu_a.asm)
- uC/OS-II源码解析(os_task.c)
- uC/OS-II源码解析(os_cpu.h)
- uC/OS-II源码解析(os_core.c)
- uC/OS-II源码分析(总体思路一)
- uC/OS-II源码分析(总体思路 二)
- 【专题】uC/OS-II内核架构解析(6)---uC/OS-II内存管理
- 【专题】uC/OS-II内核架构解析(2)---uC/OS-II基本介绍
- 【专题】uC/OS-II内核架构解析(5)---uC/OS-II通信与同步
- 【专题】uC/OS-II内核架构解析(4)---uC/OS-II任务管理
- uc/os-II 源码剖析笔记(1)——几个RTOS里面的基本概念(一)