在内存管理初始化函数之后是消息队列初始化函数;这个函数也有一个开关叫做
OS_Q_EN
能够控制当前的操作系统是否使用消息队列功能
点击(此处)折叠或打开
- /*
- *********************************************************************************************************
- * QUEUE MODULE INITIALIZATION
- *
- * Description : This function is called by uC/OS-II to initialize the message queue module. Your
- * application MUST NOT call this function.
- *
- * Arguments : none
- *
- * Returns : none
- *
- * Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it.
- *********************************************************************************************************
- */
- void OS_QInit (void)
- {
- #if OS_MAX_QS == 1
- OSQFreeList = &OSQTbl[0]; /* Only ONE */
- OSQFreeList->OSQPtr = (OS_Q *)0;
- #endif
- #if OS_MAX_QS >= 2
- INT16U i;
- OS_Q *pq1;
- OS_Q *pq2;
- OS_MemClr((INT8U *)&OSQTbl[0], sizeof(OSQTbl)); /* Clear the queue table */
- pq1 = &OSQTbl[0];
- pq2 = &OSQTbl[1];
- for (i = 0; i < (OS_MAX_QS - 1); i++) { /* Init. list of free QUEUE control blocks */
- pq1->OSQPtr = pq2;
- pq1++;
- pq2++;
- }
- pq1->OSQPtr = (OS_Q *)0;
- OSQFreeList = &OSQTbl[0];
- #endif
- }
其结构与前面的双链表结构初始化相同,核心数据结构为
OS_Q和OS_Q_DATA
点击(此处)折叠或打开
- /*
- *********************************************************************************************************
- * MESSAGE QUEUE DATA
- *********************************************************************************************************
- */
- #if OS_Q_EN > 0
- typedef struct os_q { /* QUEUE CONTROL BLOCK */
- struct os_q *OSQPtr; /* Link to next queue control block in list of free blocks */
- void **OSQStart; /* Pointer to start of queue data */
- void **OSQEnd; /* Pointer to end of queue data */
- void **OSQIn; /* Pointer to where next message will be inserted in the Q */
- void **OSQOut; /* Pointer to where next message will be extracted from the Q */
- INT16U OSQSize; /* Size of queue (maximum number of entries) */
- INT16U OSQEntries; /* Current number of entries in the queue */
- } OS_Q;
- typedef struct os_q_data {
- void *OSMsg; /* Pointer to next message to be extracted from queue */
- INT16U OSNMsgs; /* Number of messages in message queue */
- INT16U OSQSize; /* Size of message queue */
- #if OS_LOWEST_PRIO <= 63
- INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
- INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
- #else
- INT16U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
- INT16U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
- #endif
- } OS_Q_DATA;
- #endif
这个数据结构有如下的内容:
struct os_q *OSQPtr;指向下一个OS_Q的指针
void **OSQStart;指向消息队列数据链表开始的指针
void **OSQEnd;指向消息队列数据链表结束的指针
void **OSQIn; 指向消息队列放入消息数据的入口
void **OSQOut;指向消息队列取出消息数据的出口
OSQSize;最多可以放进多少个消息
OSQEntries;现在有多少个数据存放在当前消息队列里面
将所有的空消息队列串联起来构成一个单链表,然后将表头返回给OSQFreeList
将表尾节点指向NULL就行了
建立一个消息队列的函数为
关中断,取得一个事件控制块ECB,将空事件控制链表的表头后移一个数据结构
点击(此处)折叠或打开
- /*
- *********************************************************************************************************
- * CREATE A MESSAGE QUEUE
- *
- * Description: This function creates a message queue if free event control blocks are available.
- *
- * Arguments : start is a pointer to the base address of the message queue storage area. The
- * storage area MUST be declared as an array of pointers to 'void' as follows
- *
- * void *MessageStorage[size]
- *
- * size is the number of elements in the storage area
- *
- * Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the
- * created queue
- * == (OS_EVENT *)0 if no event control blocks were available or an error was detected
- *********************************************************************************************************
- */
- OS_EVENT *OSQCreate (void **start, INT16U size)
- {
- OS_EVENT *pevent;
- OS_Q *pq;
- #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
- OS_CPU_SR cpu_sr = 0;
- #endif
- if (OSIntNesting > 0) { /* See if called from ISR ... */
- return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
- }
- OS_ENTER_CRITICAL();
- pevent = OSEventFreeList; /* Get next free event control block */
- if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
- OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
- }
- OS_EXIT_CRITICAL();
- if (pevent != (OS_EVENT *)0) { /* See if we have an event control block */
- OS_ENTER_CRITICAL();
- pq = OSQFreeList; /* Get a free queue control block */
- if (pq != (OS_Q *)0) { /* Were we able to get a queue control block ? */
- OSQFreeList = OSQFreeList->OSQPtr; /* Yes, Adjust free list pointer to next free*/
- OS_EXIT_CRITICAL();
- pq->OSQStart = start; /* Initialize the queue */
- 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;
- #if OS_EVENT_NAME_SIZE > 1
- pevent->OSEventName[0] = '?'; /* Unknown name */
- pevent->OSEventName[1] = OS_ASCII_NUL;
- #endif
- OS_EventWaitListInit(pevent); /* Initalize the wait list */
- } else {
- pevent->OSEventPtr = (void *)OSEventFreeList; /* No, Return event control block on error */
- OSEventFreeList = pevent;
- OS_EXIT_CRITICAL();
- pevent = (OS_EVENT *)0;
- }
- }
- return (pevent);
- }
关中断,取得一个事件控制块ECB,将空事件控制链表的表头后移一个数据结构
取得一个空消息队列块,向消息队列块和事件控制块中写入如下的信息
pq->OSQStart = start; /* Initialize the queue */
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;
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);
如果成功,返回事件控制块的指针pevent
消息队列是一个循环链表,元素中的核心数据是指向msg类型的指针,每当OSQIn/OSQOut到达数组结尾OSQEnd
就会自动跳转到OSQStart,在创建一个消息队列之前,要创建一个size大小跟消息队列大小一样的指针数组,这个数组是消息队列存放指向msg的指针的实体