OS_Q.lst
上传用户:tzjinxin1
上传日期:2022-08-08
资源大小:272k
文件大小:46k
开发平台:

Visual C++

  1. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 1   
  2. C51 COMPILER V8.02, COMPILATION OF MODULE OS_Q
  3. OBJECT MODULE PLACED IN .objOS_Q.obj
  4. COMPILER INVOKED BY: C:KeilC51BINC51.EXE uCosiiOS_Q.C LARGE BROWSE DEBUG OBJECTEXTEND PRINT(.lstOS_Q.lst) OBJECT(
  5.                     -.objOS_Q.obj)
  6. line level    source
  7.    1          /*
  8.    2          *********************************************************************************************************
  9.    3          *                                                uC/OS-II
  10.    4          *                                          The Real-Time Kernel
  11.    5          *                                        MESSAGE QUEUE MANAGEMENT
  12.    6          *
  13.    7          *                          (c) Copyright 1992-2001, Jean J. Labrosse, Weston, FL
  14.    8          *                                           All Rights Reserved
  15.    9          *
  16.   10          * File : OS_Q.C
  17.   11          * By   : Jean J. Labrosse
  18.   12          *********************************************************************************************************
  19.   13          */
  20.   14          
  21.   15          #ifndef  OS_MASTER_FILE
  22.   16          #include "sourceincludes.h"
  23.   17          #endif
  24.   18          
  25.   19          #if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
  26.               /*
  27.               *********************************************************************************************************
  28.               *                                      ACCEPT MESSAGE FROM QUEUE
  29.               *
  30.               * Description: This function checks the queue to see if a message is available.  Unlike OSQPend(),
  31.               *              OSQAccept() does not suspend the calling task if a message is not available.
  32.               *
  33.               * Arguments  : pevent        is a pointer to the event control block
  34.               *
  35.               * Returns    : != (void *)0  is the message in the queue if one is available.  The message is removed
  36.               *                            from the so the next time OSQAccept() is called, the queue will contain
  37.               *                            one less entry.
  38.               *              == (void *)0  if the queue is empty or,
  39.               *                            if 'pevent' is a NULL pointer or,
  40.               *                            if you passed an invalid event type
  41.               *********************************************************************************************************
  42.               */
  43.               
  44.               #if OS_Q_ACCEPT_EN > 0
  45.               void  *OSQAccept (OS_EVENT *pevent) reentrant
  46.               {
  47.               #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  48.                   OS_CPU_SR  cpu_sr;
  49.               #endif    
  50.                   void      *msg;
  51.                   OS_Q      *pq;
  52.               
  53.               
  54.               #if OS_ARG_CHK_EN > 0
  55.                   if (pevent == (OS_EVENT *)0) {               /* Validate 'pevent'                                  */
  56.                       return ((void *)0);
  57.                   }
  58.                   if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type                          */
  59.                       return ((void *)0);
  60.                   }
  61. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 2   
  62.               #endif
  63.                   OS_ENTER_CRITICAL();
  64.                   pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */
  65.                   if (pq->OSQEntries != 0) {                   /* See if any messages in the queue                   */
  66.                       msg = *pq->OSQOut++;                     /* Yes, extract oldest message from the queue         */
  67.                       pq->OSQEntries--;                        /* Update the number of entries in the queue          */
  68.                       if (pq->OSQOut == pq->OSQEnd) {          /* Wrap OUT pointer if we are at the end of the queue */
  69.                           pq->OSQOut = pq->OSQStart;
  70.                       }
  71.                   } else {
  72.                       msg = (void *)0;                         /* Queue is empty                                     */
  73.                   }
  74.                   OS_EXIT_CRITICAL();
  75.                   return (msg);                                /* Return message received (or NULL)                  */
  76.               }
  77.               #endif
  78.               /*$PAGE*/
  79.               /*
  80.               *********************************************************************************************************
  81.               *                                        CREATE A MESSAGE QUEUE
  82.               *
  83.               * Description: This function creates a message queue if free event control blocks are available.
  84.               *
  85.               * Arguments  : start         is a pointer to the base address of the message queue storage area.  The
  86.               *                            storage area MUST be declared as an array of pointers to 'void' as follows
  87.               *
  88.               *                            void *MessageStorage[size]
  89.               *
  90.               *              size          is the number of elements in the storage area
  91.               *
  92.               * Returns    : != (OS_EVENT *)0  is a pointer to the event control clock (OS_EVENT) associated with the
  93.               *                                created queue
  94.               *              == (OS_EVENT *)0  if no event control blocks were available or an error was detected
  95.               *********************************************************************************************************
  96.               */
  97.               
  98.               OS_EVENT  *OSQCreate (void **start, INT16U size) reentrant
  99.               {
  100.               #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  101.                   OS_CPU_SR  cpu_sr;
  102.               #endif    
  103.                   OS_EVENT  *pevent;
  104.                   OS_Q      *pq;
  105.               
  106.               
  107.                   if (OSIntNesting > 0) {                      /* See if called from ISR ...                         */
  108.                       return ((OS_EVENT *)0);                  /* ... can't CREATE from an ISR                       */
  109.                   }
  110.                   OS_ENTER_CRITICAL();
  111.                   pevent = OSEventFreeList;                    /* Get next free event control block                  */
  112.                   if (OSEventFreeList != (OS_EVENT *)0) {      /* See if pool of free ECB pool was empty             */
  113.                       OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
  114.                   }
  115.                   OS_EXIT_CRITICAL();
  116.                   if (pevent != (OS_EVENT *)0) {               /* See if we have an event control block              */
  117.                       OS_ENTER_CRITICAL();                     /* Get a free queue control block                     */
  118.                       pq = OSQFreeList;
  119.                       if (OSQFreeList != (OS_Q *)0) {
  120.                           OSQFreeList = OSQFreeList->OSQPtr;
  121.                       }
  122.                       OS_EXIT_CRITICAL();
  123.                       if (pq != (OS_Q *)0) {                   /* See if we were able to get a queue control block   */
  124. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 3   
  125.                           pq->OSQStart        = start;         /* Yes, initialize the queue                          */
  126.                           pq->OSQEnd          = &start[size];
  127.                           pq->OSQIn           = start;
  128.                           pq->OSQOut          = start;
  129.                           pq->OSQSize         = size;
  130.                           pq->OSQEntries      = 0;
  131.                           pevent->OSEventType = OS_EVENT_TYPE_Q;
  132.                           pevent->OSEventPtr  = pq;
  133.                           OS_EventWaitListInit(pevent);
  134.                       } else {                                 /* No,  since we couldn't get a queue control block   */
  135.                           OS_ENTER_CRITICAL();                 /* Return event control block on error                */
  136.                           pevent->OSEventPtr = (void *)OSEventFreeList;
  137.                           OSEventFreeList    = pevent;
  138.                           OS_EXIT_CRITICAL();
  139.                           pevent = (OS_EVENT *)0;
  140.                       }
  141.                   }
  142.                   return (pevent);
  143.               }
  144.               /*$PAGE*/
  145.               /*
  146.               *********************************************************************************************************
  147.               *                                        DELETE A MESSAGE QUEUE
  148.               *
  149.               * Description: This function deletes a message queue and readies all tasks pending on the queue.
  150.               *
  151.               * Arguments  : pevent        is a pointer to the event control block associated with the desired
  152.               *                            queue.
  153.               *
  154.               *              opt           determines delete options as follows:
  155.               *                            opt == OS_DEL_NO_PEND   Delete the queue ONLY if no task pending
  156.               *                            opt == OS_DEL_ALWAYS    Deletes the queue even if tasks are waiting.
  157.               *                                                    In this case, all the tasks pending will be readied.
  158.               *
  159.               *              err           is a pointer to an error code that can contain one of the following values:
  160.               *                            OS_NO_ERR               The call was successful and the queue was deleted
  161.               *                            OS_ERR_DEL_ISR          If you tried to delete the queue from an ISR
  162.               *                            OS_ERR_INVALID_OPT      An invalid option was specified
  163.               *                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the queue
  164.               *                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a queue
  165.               *                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
  166.               *
  167.               * Returns    : pevent        upon error
  168.               *              (OS_EVENT *)0 if the queue was successfully deleted.
  169.               *
  170.               * Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
  171.               *                 the queue MUST check the return code of OSQPend().
  172.               *              2) OSQAccept() callers will not know that the intended queue has been deleted unless
  173.               *                 they check 'pevent' to see that it's a NULL pointer.
  174.               *              3) This call can potentially disable interrupts for a long time.  The interrupt disable
  175.               *                 time is directly proportional to the number of tasks waiting on the queue.
  176.               *              4) Because ALL tasks pending on the queue will be readied, you MUST be careful in
  177.               *                 applications where the queue is used for mutual exclusion because the resource(s)
  178.               *                 will no longer be guarded by the queue.
  179.               *              5) If the storage for the message queue was allocated dynamically (i.e. using a malloc()
  180.               *                 type call) then your application MUST release the memory storage by call the counterpart
  181.               *                 call of the dynamic allocation scheme used.  If the queue storage was created statically
  182.               *                 then, the storage can be reused.
  183.               *********************************************************************************************************
  184.               */
  185.               
  186.               #if OS_Q_DEL_EN > 0
  187. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 4   
  188.               OS_EVENT  *OSQDel (OS_EVENT *pevent, INT8U opt, INT8U *err) reentrant
  189.               {
  190.               #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  191.                   OS_CPU_SR  cpu_sr;
  192.               #endif    
  193.                   BOOLEAN    tasks_waiting;
  194.                   OS_Q      *pq;
  195.               
  196.               
  197.                   if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
  198.                       *err = OS_ERR_DEL_ISR;                             /* ... can't DELETE from an ISR             */
  199.                       return ((OS_EVENT *)0);
  200.                   }
  201.               #if OS_ARG_CHK_EN > 0
  202.                   if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
  203.                       *err = OS_ERR_PEVENT_NULL;
  204.                       return (pevent);
  205.                   }
  206.                   if (pevent->OSEventType != OS_EVENT_TYPE_Q) {          /* Validate event block type                */
  207.                       *err = OS_ERR_EVENT_TYPE;
  208.                       return (pevent);
  209.                   }
  210.               #endif
  211.                   OS_ENTER_CRITICAL();
  212.                   if (pevent->OSEventGrp != 0x00) {                      /* See if any tasks waiting on queue        */
  213.                       tasks_waiting = TRUE;                              /* Yes                                      */
  214.                   } else {
  215.                       tasks_waiting = FALSE;                             /* No                                       */
  216.                   }
  217.                   switch (opt) {
  218.                       case OS_DEL_NO_PEND:                               /* Delete queue only if no task waiting     */
  219.                            if (tasks_waiting == FALSE) {
  220.                                pq                  = pevent->OSEventPtr; /* Return OS_Q to free list                 */ 
  221.                                pq->OSQPtr          = OSQFreeList;
  222.                                OSQFreeList         = pq;
  223.                                pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  224.                                pevent->OSEventPtr  = OSEventFreeList;    /* Return Event Control Block to free list  */
  225.                                OSEventFreeList     = pevent;             /* Get next free event control block        */
  226.                                OS_EXIT_CRITICAL();
  227.                                *err = OS_NO_ERR;
  228.                                return ((OS_EVENT *)0);                   /* Queue has been deleted                   */
  229.                            } else {
  230.                                OS_EXIT_CRITICAL();
  231.                                *err = OS_ERR_TASK_WAITING;
  232.                                return (pevent);
  233.                            }
  234.               
  235.                       case OS_DEL_ALWAYS:                                /* Always delete the queue                  */
  236.                            while (pevent->OSEventGrp != 0x00) {          /* Ready ALL tasks waiting for queue        */
  237.                                OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q);
  238.                            }
  239.                            pq                  = pevent->OSEventPtr;     /* Return OS_Q to free list                 */ 
  240.                            pq->OSQPtr          = OSQFreeList;
  241.                            OSQFreeList         = pq;
  242.                            pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  243.                            pevent->OSEventPtr  = OSEventFreeList;        /* Return Event Control Block to free list  */
  244.                            OSEventFreeList     = pevent;                 /* Get next free event control block        */
  245.                            OS_EXIT_CRITICAL();
  246.                            if (tasks_waiting == TRUE) {                  /* Reschedule only if task(s) were waiting  */
  247.                                OS_Sched();                               /* Find highest priority task ready to run  */
  248.                            }
  249.                            *err = OS_NO_ERR;
  250. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 5   
  251.                            return ((OS_EVENT *)0);                       /* Queue has been deleted                   */
  252.               
  253.                       default:
  254.                            OS_EXIT_CRITICAL();
  255.                            *err = OS_ERR_INVALID_OPT;
  256.                            return (pevent);
  257.                   }
  258.               }
  259.               #endif
  260.               
  261.               /*$PAGE*/
  262.               /*
  263.               *********************************************************************************************************
  264.               *                                           FLUSH QUEUE
  265.               *
  266.               * Description : This function is used to flush the contents of the message queue.
  267.               *
  268.               * Arguments   : none
  269.               *
  270.               * Returns     : OS_NO_ERR           upon success
  271.               *               OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a queue
  272.               *               OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
  273.               *********************************************************************************************************
  274.               */
  275.               
  276.               #if OS_Q_FLUSH_EN > 0
  277.               INT8U  OSQFlush (OS_EVENT *pevent) reentrant
  278.               {
  279.               #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  280.                   OS_CPU_SR  cpu_sr;
  281.               #endif    
  282.                   OS_Q      *pq;
  283.               
  284.               
  285.               #if OS_ARG_CHK_EN > 0
  286.                   if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  287.                       return (OS_ERR_PEVENT_NULL);
  288.                   }
  289.                   if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* Validate event block type                     */
  290.                       return (OS_ERR_EVENT_TYPE);
  291.                   }
  292.               #endif
  293.                   OS_ENTER_CRITICAL();
  294.                   pq             = (OS_Q *)pevent->OSEventPtr;      /* Point to queue storage structure              */
  295.                   pq->OSQIn      = pq->OSQStart;
  296.                   pq->OSQOut     = pq->OSQStart;
  297.                   pq->OSQEntries = 0;
  298.                   OS_EXIT_CRITICAL();
  299.                   return (OS_NO_ERR);
  300.               }
  301.               #endif
  302.               
  303.               /*$PAGE*/
  304.               /*
  305.               *********************************************************************************************************
  306.               *                                     PEND ON A QUEUE FOR A MESSAGE
  307.               *
  308.               * Description: This function waits for a message to be sent to a queue
  309.               *
  310.               * Arguments  : pevent        is a pointer to the event control block associated with the desired queue
  311.               *
  312.               *              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
  313. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 6   
  314.               *                            wait for a message to arrive at the queue up to the amount of time
  315.               *                            specified by this argument.  If you specify 0, however, your task will wait
  316.               *                            forever at the specified queue or, until a message arrives.
  317.               *
  318.               *              err           is a pointer to where an error message will be deposited.  Possible error
  319.               *                            messages are:
  320.               *
  321.               *                            OS_NO_ERR           The call was successful and your task received a
  322.               *                                                message.
  323.               *                            OS_TIMEOUT          A message was not received within the specified timeout
  324.               *                            OS_ERR_EVENT_TYPE   You didn't pass a pointer to a queue
  325.               *                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
  326.               *                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
  327.               *                                                would lead to a suspension.
  328.               *
  329.               * Returns    : != (void *)0  is a pointer to the message received
  330.               *              == (void *)0  if no message was received or,
  331.               *                            if 'pevent' is a NULL pointer or,
  332.               *                            if you didn't pass a pointer to a queue.
  333.               *********************************************************************************************************
  334.               */
  335.               
  336.               void  *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) reentrant
  337.               {
  338.               #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  339.                   OS_CPU_SR  cpu_sr;
  340.               #endif    
  341.                   void      *msg;
  342.                   OS_Q      *pq;
  343.               
  344.               
  345.                   if (OSIntNesting > 0) {                      /* See if called from ISR ...                         */
  346.                       *err = OS_ERR_PEND_ISR;                  /* ... can't PEND from an ISR                         */
  347.                       return ((void *)0);
  348.                   }
  349.               #if OS_ARG_CHK_EN > 0
  350.                   if (pevent == (OS_EVENT *)0) {               /* Validate 'pevent'                                  */
  351.                       *err = OS_ERR_PEVENT_NULL;
  352.                       return ((void *)0);
  353.                   }
  354.                   if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type                          */
  355.                       *err = OS_ERR_EVENT_TYPE;
  356.                       return ((void *)0);
  357.                   }
  358.               #endif
  359.                   OS_ENTER_CRITICAL();
  360.                   pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */
  361.                   if (pq->OSQEntries != 0) {                   /* See if any messages in the queue                   */
  362.                       msg = *pq->OSQOut++;                     /* Yes, extract oldest message from the queue         */
  363.                       pq->OSQEntries--;                        /* Update the number of entries in the queue          */
  364.                       if (pq->OSQOut == pq->OSQEnd) {          /* Wrap OUT pointer if we are at the end of the queue */
  365.                           pq->OSQOut = pq->OSQStart;
  366.                       }
  367.                       OS_EXIT_CRITICAL();
  368.                       *err = OS_NO_ERR;
  369.                       return (msg);                            /* Return message received                            */
  370.                   }
  371.                   OSTCBCur->OSTCBStat |= OS_STAT_Q;            /* Task will have to pend for a message to be posted  */
  372.                   OSTCBCur->OSTCBDly   = timeout;              /* Load timeout into TCB                              */
  373.                   OS_EventTaskWait(pevent);                    /* Suspend task until event or timeout occurs         */
  374.                   OS_EXIT_CRITICAL();
  375.                   OS_Sched();                                  /* Find next highest priority task ready to run       */
  376. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 7   
  377.                   OS_ENTER_CRITICAL();
  378.                   msg = OSTCBCur->OSTCBMsg;
  379.                   if (msg != (void *)0) {                      /* Did we get a message?                              */
  380.                       OSTCBCur->OSTCBMsg      = (void *)0;     /* Extract message from TCB (Put there by QPost)      */
  381.                       OSTCBCur->OSTCBStat     = OS_STAT_RDY;
  382.                       OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* No longer waiting for event                        */
  383.                       OS_EXIT_CRITICAL();
  384.                       *err                    = OS_NO_ERR;
  385.                       return (msg);                            /* Return message received                            */
  386.                   }
  387.                   OS_EventTO(pevent);                          /* Timed out                                          */
  388.                   OS_EXIT_CRITICAL();
  389.                   *err = OS_TIMEOUT;                           /* Indicate a timeout occured                         */
  390.                   return ((void *)0);                          /* No message received                                */
  391.               }
  392.               /*$PAGE*/
  393.               /*
  394.               *********************************************************************************************************
  395.               *                                        POST MESSAGE TO A QUEUE
  396.               *
  397.               * Description: This function sends a message to a queue
  398.               *
  399.               * Arguments  : pevent        is a pointer to the event control block associated with the desired queue
  400.               *
  401.               *              msg           is a pointer to the message to send.  You MUST NOT send a NULL pointer.
  402.               *
  403.               * Returns    : OS_NO_ERR             The call was successful and the message was sent
  404.               *              OS_Q_FULL             If the queue cannot accept any more messages because it is full.
  405.               *              OS_ERR_EVENT_TYPE     If you didn't pass a pointer to a queue.
  406.               *              OS_ERR_PEVENT_NULL    If 'pevent' is a NULL pointer
  407.               *              OS_ERR_POST_NULL_PTR  If you are attempting to post a NULL pointer
  408.               *********************************************************************************************************
  409.               */
  410.               
  411.               #if OS_Q_POST_EN > 0
  412.               INT8U  OSQPost (OS_EVENT *pevent, void *msg) reentrant
  413.               {
  414.               #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  415.                   OS_CPU_SR  cpu_sr;
  416.               #endif    
  417.                   OS_Q      *pq;
  418.               
  419.               
  420.               #if OS_ARG_CHK_EN > 0
  421.                   if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  422.                       return (OS_ERR_PEVENT_NULL);
  423.                   }
  424.                   if (msg == (void *)0) {                           /* Make sure we are not posting a NULL pointer   */
  425.                       return (OS_ERR_POST_NULL_PTR);
  426.                   }
  427.                   if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* Validate event block type                     */
  428.                       return (OS_ERR_EVENT_TYPE);
  429.                   }
  430.               #endif
  431.                   OS_ENTER_CRITICAL();
  432.                   if (pevent->OSEventGrp != 0x00) {                 /* See if any task pending on queue              */
  433.                       OS_EventTaskRdy(pevent, msg, OS_STAT_Q);      /* Ready highest priority task waiting on event  */
  434.                       OS_EXIT_CRITICAL();
  435.                       OS_Sched();                                   /* Find highest priority task ready to run       */
  436.                       return (OS_NO_ERR);
  437.                   }
  438.                   pq = (OS_Q *)pevent->OSEventPtr;                  /* Point to queue control block                  */
  439. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 8   
  440.                   if (pq->OSQEntries >= pq->OSQSize) {              /* Make sure queue is not full                   */
  441.                       OS_EXIT_CRITICAL();
  442.                       return (OS_Q_FULL);
  443.                   }
  444.                   *pq->OSQIn++ = msg;                               /* Insert message into queue                     */
  445.                   pq->OSQEntries++;                                 /* Update the nbr of entries in the queue        */
  446.                   if (pq->OSQIn == pq->OSQEnd) {                    /* Wrap IN ptr if we are at end of queue         */
  447.                       pq->OSQIn = pq->OSQStart;
  448.                   }
  449.                   OS_EXIT_CRITICAL();
  450.                   return (OS_NO_ERR);
  451.               }
  452.               #endif
  453.               /*$PAGE*/
  454.               /*
  455.               *********************************************************************************************************
  456.               *                                   POST MESSAGE TO THE FRONT OF A QUEUE
  457.               *
  458.               * Description: This function sends a message to a queue but unlike OSQPost(), the message is posted at
  459.               *              the front instead of the end of the queue.  Using OSQPostFront() allows you to send
  460.               *              'priority' messages.
  461.               *
  462.               * Arguments  : pevent        is a pointer to the event control block associated with the desired queue
  463.               *
  464.               *              msg           is a pointer to the message to send.  You MUST NOT send a NULL pointer.
  465.               *
  466.               * Returns    : OS_NO_ERR             The call was successful and the message was sent
  467.               *              OS_Q_FULL             If the queue cannot accept any more messages because it is full.
  468.               *              OS_ERR_EVENT_TYPE     If you didn't pass a pointer to a queue.
  469.               *              OS_ERR_PEVENT_NULL    If 'pevent' is a NULL pointer
  470.               *              OS_ERR_POST_NULL_PTR  If you are attempting to post to a non queue.
  471.               *********************************************************************************************************
  472.               */
  473.               
  474.               #if OS_Q_POST_FRONT_EN > 0
  475.               INT8U  OSQPostFront (OS_EVENT *pevent, void *msg) reentrant
  476.               {
  477.               #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  478.                   OS_CPU_SR  cpu_sr;
  479.               #endif    
  480.                   OS_Q      *pq;
  481.               
  482.               
  483.               #if OS_ARG_CHK_EN > 0
  484.                   if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  485.                       return (OS_ERR_PEVENT_NULL);
  486.                   }
  487.                   if (msg == (void *)0) {                           /* Make sure we are not posting a NULL pointer   */
  488.                       return (OS_ERR_POST_NULL_PTR);
  489.                   }
  490.                   if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* Validate event block type                     */
  491.                       return (OS_ERR_EVENT_TYPE);
  492.                   }
  493.               #endif
  494.                   OS_ENTER_CRITICAL();
  495.                   if (pevent->OSEventGrp != 0x00) {                 /* See if any task pending on queue              */
  496.                       OS_EventTaskRdy(pevent, msg, OS_STAT_Q);      /* Ready highest priority task waiting on event  */
  497.                       OS_EXIT_CRITICAL();
  498.                       OS_Sched();                                   /* Find highest priority task ready to run       */
  499.                       return (OS_NO_ERR);
  500.                   }
  501.                   pq = (OS_Q *)pevent->OSEventPtr;                  /* Point to queue control block                  */
  502. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 9   
  503.                   if (pq->OSQEntries >= pq->OSQSize) {              /* Make sure queue is not full                   */
  504.                       OS_EXIT_CRITICAL();
  505.                       return (OS_Q_FULL);
  506.                   }
  507.                   if (pq->OSQOut == pq->OSQStart) {                 /* Wrap OUT ptr if we are at the 1st queue entry */
  508.                       pq->OSQOut = pq->OSQEnd;
  509.                   }
  510.                   pq->OSQOut--;
  511.                   *pq->OSQOut = msg;                                /* Insert message into queue                     */
  512.                   pq->OSQEntries++;                                 /* Update the nbr of entries in the queue        */
  513.                   OS_EXIT_CRITICAL();
  514.                   return (OS_NO_ERR);
  515.               }
  516.               #endif
  517.               /*$PAGE*/
  518.               /*
  519.               *********************************************************************************************************
  520.               *                                        POST MESSAGE TO A QUEUE
  521.               *
  522.               * Description: This function sends a message to a queue.  This call has been added to reduce code size
  523.               *              since it can replace both OSQPost() and OSQPostFront().  Also, this function adds the 
  524.               *              capability to broadcast a message to ALL tasks waiting on the message queue.
  525.               *
  526.               * Arguments  : pevent        is a pointer to the event control block associated with the desired queue
  527.               *
  528.               *              msg           is a pointer to the message to send.  You MUST NOT send a NULL pointer.
  529.               *
  530.               *              opt           determines the type of POST performed:
  531.               *                            OS_POST_OPT_NONE         POST to a single waiting task 
  532.               *                                                     (Identical to OSQPost())
  533.               *                            OS_POST_OPT_BROADCAST    POST to ALL tasks that are waiting on the queue
  534.               *                            OS_POST_OPT_FRONT        POST as LIFO (Simulates OSQPostFront())
  535.               *
  536.               *                            Below is a list of ALL the possible combination of these flags:
  537.               *
  538.               *                                 1) OS_POST_OPT_NONE
  539.               *                                    identical to OSQPost()
  540.               *
  541.               *                                 2) OS_POST_OPT_FRONT  
  542.               *                                    identical to OSQPostFront()
  543.               *
  544.               *                                 3) OS_POST_OPT_BROADCAST
  545.               *                                    identical to OSQPost() but will broadcast 'msg' to ALL waiting tasks
  546.               *
  547.               *                                 4) OS_POST_OPT_FRONT + OS_POST_OPT_BROADCAST  is identical to
  548.               *                                    OSQPostFront() except that will broadcast 'msg' to ALL waiting tasks
  549.               *
  550.               * Returns    : OS_NO_ERR             The call was successful and the message was sent
  551.               *              OS_Q_FULL             If the queue cannot accept any more messages because it is full.
  552.               *              OS_ERR_EVENT_TYPE     If you didn't pass a pointer to a queue.
  553.               *              OS_ERR_PEVENT_NULL    If 'pevent' is a NULL pointer
  554.               *              OS_ERR_POST_NULL_PTR  If you are attempting to post a NULL pointer
  555.               *
  556.               * Warning    : Interrupts can be disabled for a long time if you do a 'broadcast'.  In fact, the 
  557.               *              interrupt disable time is proportional to the number of tasks waiting on the queue.
  558.               *********************************************************************************************************
  559.               */
  560.               
  561.               #if OS_Q_POST_OPT_EN > 0
  562.               INT8U  OSQPostOpt (OS_EVENT *pevent, void *msg, INT8U opt) reentrant
  563.               {
  564.               #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  565. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 10  
  566.                   OS_CPU_SR  cpu_sr;
  567.               #endif    
  568.                   OS_Q      *pq;
  569.               
  570.               
  571.               #if OS_ARG_CHK_EN > 0
  572.                   if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  573.                       return (OS_ERR_PEVENT_NULL);
  574.                   }
  575.                   if (msg == (void *)0) {                           /* Make sure we are not posting a NULL pointer   */
  576.                       return (OS_ERR_POST_NULL_PTR);
  577.                   }
  578.                   if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* Validate event block type                     */
  579.                       return (OS_ERR_EVENT_TYPE);
  580.                   }
  581.               #endif
  582.                   OS_ENTER_CRITICAL();
  583.                   if (pevent->OSEventGrp != 0x00) {                 /* See if any task pending on queue              */
  584.                       if ((opt & OS_POST_OPT_BROADCAST) != 0x00) {  /* Do we need to post msg to ALL waiting tasks ? */
  585.                           while (pevent->OSEventGrp != 0x00) {      /* Yes, Post to ALL tasks waiting on queue       */ 
  586.              -          
  587.                               OS_EventTaskRdy(pevent, msg, OS_STAT_Q);    
  588.                           }
  589.                       } else {
  590.                           OS_EventTaskRdy(pevent, msg, OS_STAT_Q);  /* No,  Post to HPT waiting on queue             */
  591.                       }
  592.                       OS_EXIT_CRITICAL();
  593.                       OS_Sched();                                   /* Find highest priority task ready to run       */
  594.                       return (OS_NO_ERR);
  595.                   }
  596.                   pq = (OS_Q *)pevent->OSEventPtr;                  /* Point to queue control block                  */
  597.                   if (pq->OSQEntries >= pq->OSQSize) {              /* Make sure queue is not full                   */
  598.                       OS_EXIT_CRITICAL();
  599.                       return (OS_Q_FULL);
  600.                   }
  601.                   if ((opt & OS_POST_OPT_FRONT) != 0x00) {          /* Do we post to the FRONT of the queue?         */
  602.                       if (pq->OSQOut == pq->OSQStart) {             /* Yes, Post as LIFO, Wrap OUT pointer if we ... */
  603.                           pq->OSQOut = pq->OSQEnd;                  /*      ... are at the 1st queue entry           */
  604.                       }
  605.                       pq->OSQOut--;
  606.                       *pq->OSQOut = msg;                            /*      Insert message into queue                */
  607.                   } else {                                          /* No,  Post as FIFO                             */
  608.                       *pq->OSQIn++ = msg;                           /*      Insert message into queue                */
  609.                       if (pq->OSQIn == pq->OSQEnd) {                /*      Wrap IN ptr if we are at end of queue    */
  610.                           pq->OSQIn = pq->OSQStart;
  611.                       }
  612.                   }
  613.                   pq->OSQEntries++;                                 /* Update the nbr of entries in the queue        */
  614.                   OS_EXIT_CRITICAL();
  615.                   return (OS_NO_ERR);
  616.               }
  617.               #endif
  618.               /*$PAGE*/
  619.               /*
  620.               *********************************************************************************************************
  621.               *                                        QUERY A MESSAGE QUEUE
  622.               *
  623.               * Description: This function obtains information about a message queue.
  624.               *
  625.               * Arguments  : pevent        is a pointer to the event control block associated with the desired queue
  626.               *
  627.               *              ppdata         is a pointer to a structure that will contain information about the message
  628. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 11  
  629.               *                            queue.
  630.               *
  631.               * Returns    : OS_NO_ERR           The call was successful and the message was sent
  632.               *              OS_ERR_EVENT_TYPE   If you are attempting to obtain data from a non queue.
  633.               *              OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
  634.               *********************************************************************************************************
  635.               */
  636.               
  637.               #if OS_Q_QUERY_EN > 0
  638.               INT8U  OSQQuery (OS_EVENT *pevent, OS_Q_DATA *ppdata) reentrant
  639.               {
  640.               #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  641.                   OS_CPU_SR  cpu_sr;
  642.               #endif    
  643.                   OS_Q      *pq;
  644.                   INT8U     *psrc;
  645.                   INT8U     *pdest;
  646.               
  647.               
  648.               #if OS_ARG_CHK_EN > 0
  649.                   if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
  650.                       return (OS_ERR_PEVENT_NULL);
  651.                   }
  652.                   if (pevent->OSEventType != OS_EVENT_TYPE_Q) {          /* Validate event block type                */
  653.                       return (OS_ERR_EVENT_TYPE);
  654.                   }
  655.               #endif
  656.                   OS_ENTER_CRITICAL();
  657.                   ppdata->OSEventGrp = pevent->OSEventGrp;                /* Copy message queue wait list           */
  658.                   psrc              = &pevent->OSEventTbl[0];
  659.                   pdest             = &ppdata->OSEventTbl[0];
  660.               #if OS_EVENT_TBL_SIZE > 0
  661.                   *pdest++          = *psrc++;
  662.               #endif
  663.               
  664.               #if OS_EVENT_TBL_SIZE > 1
  665.                   *pdest++          = *psrc++;
  666.               #endif
  667.               
  668.               #if OS_EVENT_TBL_SIZE > 2
  669.                   *pdest++          = *psrc++;
  670.               #endif
  671.               
  672.               #if OS_EVENT_TBL_SIZE > 3
  673.                   *pdest++          = *psrc++;
  674.               #endif
  675.               
  676.               #if OS_EVENT_TBL_SIZE > 4
  677.                   *pdest++          = *psrc++;
  678.               #endif
  679.               
  680.               #if OS_EVENT_TBL_SIZE > 5
  681.                   *pdest++          = *psrc++;
  682.               #endif
  683.               
  684.               #if OS_EVENT_TBL_SIZE > 6
  685.                   *pdest++          = *psrc++;
  686.               #endif
  687.               
  688.               #if OS_EVENT_TBL_SIZE > 7
  689.                   *pdest            = *psrc;
  690.               #endif
  691. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 12  
  692.                   pq = (OS_Q *)pevent->OSEventPtr;
  693.                   if (pq->OSQEntries > 0) {
  694.                       ppdata->OSMsg = *pq->OSQOut;                         /* Get next message to return if available  *
  695.              -/
  696.                   } else {
  697.                       ppdata->OSMsg = (void *)0;
  698.                   }
  699.                   ppdata->OSNMsgs = pq->OSQEntries;
  700.                   ppdata->OSQSize = pq->OSQSize;
  701.                   OS_EXIT_CRITICAL();
  702.                   return (OS_NO_ERR);
  703.               }
  704.               #endif                                                     /* OS_Q_QUERY_EN                            */
  705.               
  706.               /*$PAGE*/
  707.               /*
  708.               *********************************************************************************************************
  709.               *                                      QUEUE MODULE INITIALIZATION
  710.               *
  711.               * Description : This function is called by uC/OS-II to initialize the message queue module.  Your
  712.               *               application MUST NOT call this function.
  713.               *
  714.               * Arguments   :  none
  715.               *
  716.               * Returns     : none
  717.               *
  718.               * Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
  719.               *********************************************************************************************************
  720.               */
  721.               
  722.               void  OS_QInit (void) reentrant
  723.               {
  724.               #if OS_MAX_QS == 1
  725.                   OSQFreeList         = &OSQTbl[0];            /* Only ONE queue!                                    */
  726.                   OSQFreeList->OSQPtr = (OS_Q *)0;
  727.               #endif
  728.               
  729.               #if OS_MAX_QS >= 2
  730.                   INT16U  i;
  731.                   OS_Q   *pq1;
  732.                   OS_Q   *pq2;
  733.               
  734.               
  735.                   pq1 = &OSQTbl[0];
  736.                   pq2 = &OSQTbl[1];
  737.                   for (i = 0; i < (OS_MAX_QS - 1); i++) {      /* Init. list of free QUEUE control blocks            */
  738.                       pq1->OSQPtr = pq2;
  739.                       pq1++;
  740.                       pq2++;
  741.                   }
  742.                   pq1->OSQPtr = (OS_Q *)0;
  743.                   OSQFreeList = &OSQTbl[0];
  744.               #endif
  745.               }
  746.               #endif                                                     /* OS_Q_EN                                  */
  747. MODULE INFORMATION:   STATIC OVERLAYABLE
  748.    CODE SIZE        =   ----    ----
  749.    CONSTANT SIZE    =   ----    ----
  750.    XDATA SIZE       =   ----    ----
  751.    PDATA SIZE       =   ----    ----
  752. C51 COMPILER V8.02   OS_Q                                                                  06/22/2006 11:44:39 PAGE 13  
  753.    DATA SIZE        =   ----    ----
  754.    IDATA SIZE       =   ----    ----
  755.    BIT SIZE         =   ----    ----
  756. END OF MODULE INFORMATION.
  757. C51 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)