Chinaunix首页 | 论坛 | 博客
  • 博客访问: 431585
  • 博文数量: 103
  • 博客积分: 1455
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-15 22:17
文章分类

全部博文(103)

文章存档

2013年(4)

2012年(99)

我的朋友

分类: LINUX

2012-11-08 10:21:32

 
在内存管理初始化函数之后是消息队列初始化函数;这个函数也有一个开关叫做
OS_Q_EN
能够控制当前的操作系统是否使用消息队列功能

点击(此处)折叠或打开

  1. /*
  2. *********************************************************************************************************
  3. * QUEUE MODULE INITIALIZATION
  4. *
  5. * Description : This function is called by uC/OS-II to initialize the message queue module. Your
  6. * application MUST NOT call this function.
  7. *
  8. * Arguments : none
  9. *
  10. * Returns : none
  11. *
  12. * Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it.
  13. *********************************************************************************************************
  14. */

  15. void OS_QInit (void)
  16. {
  17. #if OS_MAX_QS == 1
  18.     OSQFreeList = &OSQTbl[0]; /* Only ONE */
  19.     OSQFreeList->OSQPtr = (OS_Q *)0;
  20. #endif

  21. #if OS_MAX_QS >= 2
  22.     INT16U i;
  23.     OS_Q *pq1;
  24.     OS_Q *pq2;



  25.     OS_MemClr((INT8U *)&OSQTbl[0], sizeof(OSQTbl)); /* Clear the queue table */
  26.     pq1 = &OSQTbl[0];
  27.     pq2 = &OSQTbl[1];
  28.     for (i = 0; i < (OS_MAX_QS - 1); i++) { /* Init. list of free QUEUE control blocks */
  29.         pq1->OSQPtr = pq2;
  30.         pq1++;
  31.         pq2++;
  32.     }
  33.     pq1->OSQPtr = (OS_Q *)0;
  34.     OSQFreeList = &OSQTbl[0];
  35. #endif
  36. }

其结构与前面的双链表结构初始化相同,核心数据结构为
OS_Q和OS_Q_DATA

点击(此处)折叠或打开

  1. /*
  2. *********************************************************************************************************
  3. * MESSAGE QUEUE DATA
  4. *********************************************************************************************************
  5. */

  6. #if OS_Q_EN > 0
  7. typedef struct os_q { /* QUEUE CONTROL BLOCK */
  8.     struct os_q *OSQPtr; /* Link to next queue control block in list of free blocks */
  9.     void **OSQStart; /* Pointer to start of queue data */
  10.     void **OSQEnd; /* Pointer to end of queue data */
  11.     void **OSQIn; /* Pointer to where next message will be inserted in the Q */
  12.     void **OSQOut; /* Pointer to where next message will be extracted from the Q */
  13.     INT16U OSQSize; /* Size of queue (maximum number of entries) */
  14.     INT16U OSQEntries; /* Current number of entries in the queue */
  15. } OS_Q;


  16. typedef struct os_q_data {
  17.     void *OSMsg; /* Pointer to next message to be extracted from queue */
  18.     INT16U OSNMsgs; /* Number of messages in message queue */
  19.     INT16U OSQSize; /* Size of message queue */
  20. #if OS_LOWEST_PRIO <= 63
  21.     INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
  22.     INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
  23. #else
  24.     INT16U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
  25.     INT16U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
  26. #endif
  27. } OS_Q_DATA;
  28. #endif
这个数据结构有如下的内容:
struct os_q   *OSQPtr;指向下一个OS_Q的指针
void         **OSQStart;指向消息队列数据链表开始的指针
void         **OSQEnd;指向消息队列数据链表结束的指针
void         **OSQIn; 指向消息队列放入消息数据的入口
void         **OSQOut;指向消息队列取出消息数据的出口
OSQSize;最多可以放进多少个消息
OSQEntries;现在有多少个数据存放在当前消息队列里面
 
将所有的空消息队列串联起来构成一个单链表,然后将表头返回给OSQFreeList
将表尾节点指向NULL就行了
 
建立一个消息队列的函数为

点击(此处)折叠或打开

  1. /*
  2. *********************************************************************************************************
  3. * CREATE A MESSAGE QUEUE
  4. *
  5. * Description: This function creates a message queue if free event control blocks are available.
  6. *
  7. * Arguments : start is a pointer to the base address of the message queue storage area. The
  8. * storage area MUST be declared as an array of pointers to 'void' as follows
  9. *
  10. * void *MessageStorage[size]
  11. *
  12. * size is the number of elements in the storage area
  13. *
  14. * Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the
  15. * created queue
  16. * == (OS_EVENT *)0 if no event control blocks were available or an error was detected
  17. *********************************************************************************************************
  18. */

  19. OS_EVENT *OSQCreate (void **start, INT16U size)
  20. {
  21.     OS_EVENT *pevent;
  22.     OS_Q *pq;
  23. #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
  24.     OS_CPU_SR cpu_sr = 0;
  25. #endif



  26.     if (OSIntNesting > 0) { /* See if called from ISR ... */
  27.         return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
  28.     }
  29.     OS_ENTER_CRITICAL();
  30.     pevent = OSEventFreeList; /* Get next free event control block */
  31.     if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
  32.         OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
  33.     }
  34.     OS_EXIT_CRITICAL();
  35.     if (pevent != (OS_EVENT *)0) { /* See if we have an event control block */
  36.         OS_ENTER_CRITICAL();
  37.         pq = OSQFreeList; /* Get a free queue control block */
  38.         if (pq != (OS_Q *)0) { /* Were we able to get a queue control block ? */
  39.             OSQFreeList = OSQFreeList->OSQPtr; /* Yes, Adjust free list pointer to next free*/
  40.             OS_EXIT_CRITICAL();
  41.             pq->OSQStart = start; /* Initialize the queue */
  42.             pq->OSQEnd = &start[size];
  43.             pq->OSQIn = start;
  44.             pq->OSQOut = start;
  45.             pq->OSQSize = size;
  46.             pq->OSQEntries = 0;
  47.             pevent->OSEventType = OS_EVENT_TYPE_Q;
  48.             pevent->OSEventCnt = 0;
  49.             pevent->OSEventPtr = pq;
  50. #if OS_EVENT_NAME_SIZE > 1
  51.             pevent->OSEventName[0] = '?'; /* Unknown name */
  52.             pevent->OSEventName[1] = OS_ASCII_NUL;
  53. #endif
  54.             OS_EventWaitListInit(pevent); /* Initalize the wait list */
  55.         } else {
  56.             pevent->OSEventPtr = (void *)OSEventFreeList; /* No, Return event control block on error */
  57.             OSEventFreeList = pevent;
  58.             OS_EXIT_CRITICAL();
  59.             pevent = (OS_EVENT *)0;
  60.         }
  61.     }
  62.     return (pevent);
  63. }


关中断,取得一个事件控制块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;
然后初始化事件控制块
 OS_EventWaitListInit(pevent); 
如果成功,返回事件控制块的指针pevent
消息队列是一个循环链表,元素中的核心数据是指向msg类型的指针,每当OSQIn/OSQOut到达数组结尾OSQEnd
就会自动跳转到OSQStart,在创建一个消息队列之前,要创建一个size大小跟消息队列大小一样的指针数组,这个数组是消息队列存放指向msg的指针的实体
 
 
阅读(2184) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

张利军31172014-11-20 10:17:37

.OSQFreeList = &OSQTbl[0]; 这条语句中,数组OSQTbl[OS_MAX_QS]只在ucos_ii.h中进行过声明(OS_EXT  OS_Q    OSQTbl[OS_MAX_QS];),没有地方对该数组进行过定义。怎么可以对OSQTbl[0]进行取地址运算。

希望能抽时间回答一下我的这个问题。谢谢。我的邮箱:565273892@qq.com