Răsfoiți Sursa

Basic queue operations (#11)

* Basic queue operations

* Fix queue dynamic create

* Update FreeRTOS/queue.c

* Remove rt_mq_wrapper

Co-authored-by: Man, Jianting (Meco) <920369182@qq.com>
tangzz98 3 ani în urmă
părinte
comite
2c0a9ebe61

+ 1 - 1
FreeRTOS/include/FreeRTOS.h

@@ -1134,7 +1134,7 @@ typedef struct xSTATIC_TCB
 typedef struct
 {
     struct rt_ipc_object *rt_ipc;
-    struct rt_mailbox ipc_obj;
+    struct rt_messagequeue ipc_obj;
 } StaticQueue_t;
 
 typedef struct

+ 501 - 0
FreeRTOS/include/queue.h

@@ -57,6 +57,413 @@ typedef struct QueueDefinition   * QueueHandle_t;
 #define queueQUEUE_TYPE_BINARY_SEMAPHORE      ( ( uint8_t ) 3U )
 #define queueQUEUE_TYPE_RECURSIVE_MUTEX       ( ( uint8_t ) 4U )
 
+/**
+ * queue. h
+ * @code{c}
+ * QueueHandle_t xQueueCreate(
+ *                            UBaseType_t uxQueueLength,
+ *                            UBaseType_t uxItemSize
+ *                        );
+ * @endcode
+ *
+ * Creates a new queue instance, and returns a handle by which the new queue
+ * can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, queues use two blocks of
+ * memory.  The first block is used to hold the queue's data structures.  The
+ * second block is used to hold items placed into the queue.  If a queue is
+ * created using xQueueCreate() then both blocks of memory are automatically
+ * dynamically allocated inside the xQueueCreate() function.  (see
+ * https://www.FreeRTOS.org/a00111.html).  If a queue is created using
+ * xQueueCreateStatic() then the application writer must provide the memory that
+ * will get used by the queue.  xQueueCreateStatic() therefore allows a queue to
+ * be created without using any dynamic memory allocation.
+ *
+ * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html
+ *
+ * @param uxQueueLength The maximum number of items that the queue can contain.
+ *
+ * @param uxItemSize The number of bytes each item in the queue will require.
+ * Items are queued by copy, not by reference, so this is the number of bytes
+ * that will be copied for each posted item.  Each item on the queue must be
+ * the same size.
+ *
+ * @return If the queue is successfully create then a handle to the newly
+ * created queue is returned.  If the queue cannot be created then 0 is
+ * returned.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ *  char ucMessageID;
+ *  char ucData[ 20 ];
+ * };
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ *
+ *  // Create a queue capable of containing 10 uint32_t values.
+ *  xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ *  if( xQueue1 == 0 )
+ *  {
+ *      // Queue was not created and must not be used.
+ *  }
+ *
+ *  // Create a queue capable of containing 10 pointers to AMessage structures.
+ *  // These should be passed by pointer as they contain a lot of data.
+ *  xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *  if( xQueue2 == 0 )
+ *  {
+ *      // Queue was not created and must not be used.
+ *  }
+ *
+ *  // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueCreate xQueueCreate
+ * \ingroup QueueManagement
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+    #define xQueueCreate( uxQueueLength, uxItemSize )    xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
+#endif
+
+/**
+ * queue. h
+ * @code{c}
+ * QueueHandle_t xQueueCreateStatic(
+ *                            UBaseType_t uxQueueLength,
+ *                            UBaseType_t uxItemSize,
+ *                            uint8_t *pucQueueStorage,
+ *                            StaticQueue_t *pxQueueBuffer
+ *                        );
+ * @endcode
+ *
+ * Creates a new queue instance, and returns a handle by which the new queue
+ * can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, queues use two blocks of
+ * memory.  The first block is used to hold the queue's data structures.  The
+ * second block is used to hold items placed into the queue.  If a queue is
+ * created using xQueueCreate() then both blocks of memory are automatically
+ * dynamically allocated inside the xQueueCreate() function.  (see
+ * https://www.FreeRTOS.org/a00111.html).  If a queue is created using
+ * xQueueCreateStatic() then the application writer must provide the memory that
+ * will get used by the queue.  xQueueCreateStatic() therefore allows a queue to
+ * be created without using any dynamic memory allocation.
+ *
+ * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html
+ *
+ * @param uxQueueLength The maximum number of items that the queue can contain.
+ *
+ * @param uxItemSize The number of bytes each item in the queue will require.
+ * Items are queued by copy, not by reference, so this is the number of bytes
+ * that will be copied for each posted item.  Each item on the queue must be
+ * the same size.
+ *
+ * @param pucQueueStorage If uxItemSize is not zero then
+ * pucQueueStorage must point to a uint8_t array that is at least large
+ * enough to hold the maximum number of items that can be in the queue at any
+ * one time - which is ( uxQueueLength * uxItemsSize ) bytes.  If uxItemSize is
+ * zero then pucQueueStorage can be NULL.
+ *
+ * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which
+ * will be used to hold the queue's data structure.
+ *
+ * @return If the queue is created then a handle to the created queue is
+ * returned.  If pxQueueBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ *  char ucMessageID;
+ *  char ucData[ 20 ];
+ * };
+ *
+ #define QUEUE_LENGTH 10
+ #define ITEM_SIZE sizeof( uint32_t )
+ *
+ * // xQueueBuffer will hold the queue structure.
+ * StaticQueue_t xQueueBuffer;
+ *
+ * // ucQueueStorage will hold the items posted to the queue.  Must be at least
+ * // [(queue length) * ( queue item size)] bytes long.
+ * uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
+ *
+ * void vATask( void *pvParameters )
+ * {
+ *  QueueHandle_t xQueue1;
+ *
+ *  // Create a queue capable of containing 10 uint32_t values.
+ *  xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
+ *                          ITEM_SIZE     // The size of each item in the queue
+ *                          &( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
+ *                          &xQueueBuffer ); // The buffer that will hold the queue structure.
+ *
+ *  // The queue is guaranteed to be created successfully as no dynamic memory
+ *  // allocation is used.  Therefore xQueue1 is now a handle to a valid queue.
+ *
+ *  // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueCreateStatic xQueueCreateStatic
+ * \ingroup QueueManagement
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+    #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer )    xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSendToToFront(
+ *                                 QueueHandle_t    xQueue,
+ *                                 const void       *pvItemToQueue,
+ *                                 TickType_t       xTicksToWait
+ *                             );
+ * @endcode
+ *
+ * Post an item to the front of a queue.  The item is queued by copy, not by
+ * reference.  This function must not be called from an interrupt service
+ * routine.  See xQueueSendFromISR () for an alternative which may be used
+ * in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue.  The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full.  The call will return immediately if this is set to 0 and the
+ * queue is full.  The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ *  char ucMessageID;
+ *  char ucData[ 20 ];
+ * } xMessage;
+ *
+ * uint32_t ulVar = 10UL;
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ * struct AMessage *pxMessage;
+ *
+ *  // Create a queue capable of containing 10 uint32_t values.
+ *  xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ *
+ *  // Create a queue capable of containing 10 pointers to AMessage structures.
+ *  // These should be passed by pointer as they contain a lot of data.
+ *  xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *
+ *  // ...
+ *
+ *  if( xQueue1 != 0 )
+ *  {
+ *      // Send an uint32_t.  Wait for 10 ticks for space to become
+ *      // available if necessary.
+ *      if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+ *      {
+ *          // Failed to post the message, even after 10 ticks.
+ *      }
+ *  }
+ *
+ *  if( xQueue2 != 0 )
+ *  {
+ *      // Send a pointer to a struct AMessage object.  Don't block if the
+ *      // queue is already full.
+ *      pxMessage = & xMessage;
+ *      xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ *  }
+ *
+ *  // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueSend xQueueSend
+ * \ingroup QueueManagement
+ */
+#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) \
+    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSendToBack(
+ *                                 QueueHandle_t    xQueue,
+ *                                 const void       *pvItemToQueue,
+ *                                 TickType_t       xTicksToWait
+ *                             );
+ * @endcode
+ *
+ * This is a macro that calls xQueueGenericSend().
+ *
+ * Post an item to the back of a queue.  The item is queued by copy, not by
+ * reference.  This function must not be called from an interrupt service
+ * routine.  See xQueueSendFromISR () for an alternative which may be used
+ * in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue.  The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full.  The call will return immediately if this is set to 0 and the queue
+ * is full.  The  time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ *  char ucMessageID;
+ *  char ucData[ 20 ];
+ * } xMessage;
+ *
+ * uint32_t ulVar = 10UL;
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ * struct AMessage *pxMessage;
+ *
+ *  // Create a queue capable of containing 10 uint32_t values.
+ *  xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ *
+ *  // Create a queue capable of containing 10 pointers to AMessage structures.
+ *  // These should be passed by pointer as they contain a lot of data.
+ *  xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *
+ *  // ...
+ *
+ *  if( xQueue1 != 0 )
+ *  {
+ *      // Send an uint32_t.  Wait for 10 ticks for space to become
+ *      // available if necessary.
+ *      if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+ *      {
+ *          // Failed to post the message, even after 10 ticks.
+ *      }
+ *  }
+ *
+ *  if( xQueue2 != 0 )
+ *  {
+ *      // Send a pointer to a struct AMessage object.  Don't block if the
+ *      // queue is already full.
+ *      pxMessage = & xMessage;
+ *      xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ *  }
+ *
+ *  // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueSend xQueueSend
+ * \ingroup QueueManagement
+ */
+#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
+    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSend(
+ *                            QueueHandle_t xQueue,
+ *                            const void * pvItemToQueue,
+ *                            TickType_t xTicksToWait
+ *                       );
+ * @endcode
+ *
+ * This is a macro that calls xQueueGenericSend().  It is included for
+ * backward compatibility with versions of FreeRTOS.org that did not
+ * include the xQueueSendToFront() and xQueueSendToBack() macros.  It is
+ * equivalent to xQueueSendToBack().
+ *
+ * Post an item on a queue.  The item is queued by copy, not by reference.
+ * This function must not be called from an interrupt service routine.
+ * See xQueueSendFromISR () for an alternative which may be used in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue.  The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full.  The call will return immediately if this is set to 0 and the
+ * queue is full.  The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ *  char ucMessageID;
+ *  char ucData[ 20 ];
+ * } xMessage;
+ *
+ * uint32_t ulVar = 10UL;
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ * struct AMessage *pxMessage;
+ *
+ *  // Create a queue capable of containing 10 uint32_t values.
+ *  xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ *
+ *  // Create a queue capable of containing 10 pointers to AMessage structures.
+ *  // These should be passed by pointer as they contain a lot of data.
+ *  xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *
+ *  // ...
+ *
+ *  if( xQueue1 != 0 )
+ *  {
+ *      // Send an uint32_t.  Wait for 10 ticks for space to become
+ *      // available if necessary.
+ *      if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+ *      {
+ *          // Failed to post the message, even after 10 ticks.
+ *      }
+ *  }
+ *
+ *  if( xQueue2 != 0 )
+ *  {
+ *      // Send a pointer to a struct AMessage object.  Don't block if the
+ *      // queue is already full.
+ *      pxMessage = & xMessage;
+ *      xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ *  }
+ *
+ *  // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueSend xQueueSend
+ * \ingroup QueueManagement
+ */
+#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
+    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
+
 /**
  * queue. h
  * @code{c}
@@ -147,6 +554,100 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
                               TickType_t xTicksToWait,
                               const BaseType_t xCopyPosition );
 
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueReceive(
+ *                               QueueHandle_t xQueue,
+ *                               void *pvBuffer,
+ *                               TickType_t xTicksToWait
+ *                          );
+ * @endcode
+ *
+ * Receive an item from a queue.  The item is received by copy so a buffer of
+ * adequate size must be provided.  The number of bytes copied into the buffer
+ * was defined when the queue was created.
+ *
+ * Successfully received items are removed from the queue.
+ *
+ * This function must not be used in an interrupt service routine.  See
+ * xQueueReceiveFromISR for an alternative that can.
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for an item to receive should the queue be empty at the time
+ * of the call. xQueueReceive() will return immediately if xTicksToWait
+ * is zero and the queue is empty.  The time is defined in tick periods so the
+ * constant portTICK_PERIOD_MS should be used to convert to real time if this is
+ * required.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ *  char ucMessageID;
+ *  char ucData[ 20 ];
+ * } xMessage;
+ *
+ * QueueHandle_t xQueue;
+ *
+ * // Task to create a queue and post a value.
+ * void vATask( void *pvParameters )
+ * {
+ * struct AMessage *pxMessage;
+ *
+ *  // Create a queue capable of containing 10 pointers to AMessage structures.
+ *  // These should be passed by pointer as they contain a lot of data.
+ *  xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *  if( xQueue == 0 )
+ *  {
+ *      // Failed to create the queue.
+ *  }
+ *
+ *  // ...
+ *
+ *  // Send a pointer to a struct AMessage object.  Don't block if the
+ *  // queue is already full.
+ *  pxMessage = & xMessage;
+ *  xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ *
+ *  // ... Rest of task code.
+ * }
+ *
+ * // Task to receive from the queue.
+ * void vADifferentTask( void *pvParameters )
+ * {
+ * struct AMessage *pxRxedMessage;
+ *
+ *  if( xQueue != 0 )
+ *  {
+ *      // Receive a message on the created queue.  Block for 10 ticks if a
+ *      // message is not immediately available.
+ *      if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+ *      {
+ *          // pcRxedMessage now points to the struct AMessage variable posted
+ *          // by vATask.
+ *      }
+ *  }
+ *
+ *  // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueReceive xQueueReceive
+ * \ingroup QueueManagement
+ */
+BaseType_t xQueueReceive( QueueHandle_t xQueue,
+                          void * const pvBuffer,
+                          TickType_t xTicksToWait );
+
 /**
  * queue. h
  * @code{c}

+ 4 - 0
FreeRTOS/portable/rt-thread/port.c

@@ -20,6 +20,10 @@ BaseType_t rt_err_to_freertos(rt_err_t rt_err)
             return pdPASS;
         case RT_ENOMEM:
             return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+        case RT_EFULL:
+            return errQUEUE_FULL;
+        case RT_EEMPTY:
+            return errQUEUE_EMPTY;
         default:
             return pdFAIL;
     }

+ 5 - 0
FreeRTOS/portable/rt-thread/portmacro.h

@@ -90,6 +90,11 @@
 
 /*-----------------------------------------------------------*/
 
+/* Use this macro to calculate the buffer size when allocating a queue statically
+ * To ensure the buffer can fit the desired number of messages
+ */
+    #define QUEUE_BUFFER_SIZE( uxQueueLength, uxItemSize )  ( ( RT_ALIGN( uxItemSize, RT_ALIGN_SIZE ) + sizeof( void * ) ) * uxQueueLength )
+
     BaseType_t rt_err_to_freertos(rt_err_t rt_err);
 
     #ifdef __cplusplus

+ 63 - 8
FreeRTOS/queue.c

@@ -45,6 +45,7 @@ typedef xQUEUE Queue_t;
 
 static volatile rt_uint8_t mutex_index = 0;
 static volatile rt_uint8_t sem_index = 0;
+static volatile rt_uint8_t queue_index = 0;
 
 /*-----------------------------------------------------------*/
 
@@ -73,15 +74,20 @@ static volatile rt_uint8_t sem_index = 0;
         {
             if ( ucQueueType == queueQUEUE_TYPE_RECURSIVE_MUTEX || ucQueueType == queueQUEUE_TYPE_MUTEX )
             {
-                rt_snprintf( name, RT_NAME_MAX - 1, "mutex%02d", mutex_index++ );
+                rt_snprintf( name, RT_NAME_MAX, "mutex%02d", mutex_index++ );
                 rt_mutex_init( ( rt_mutex_t ) &( ( StaticSemaphore_t * ) pxStaticQueue )->ipc_obj.mutex, name, RT_IPC_FLAG_PRIO );
             }
             else if ( ucQueueType == queueQUEUE_TYPE_BINARY_SEMAPHORE || ucQueueType == queueQUEUE_TYPE_COUNTING_SEMAPHORE )
             {
-                rt_snprintf( name, RT_NAME_MAX - 1, "sem%02d", sem_index++ );
+                rt_snprintf( name, RT_NAME_MAX, "sem%02d", sem_index++ );
                 rt_sem_init( ( rt_sem_t ) &( ( StaticSemaphore_t * ) pxStaticQueue )->ipc_obj.semaphore, name, 0, RT_IPC_FLAG_PRIO );
                 ( ( StaticSemaphore_t * ) pxStaticQueue )->ipc_obj.semaphore.max_value = uxQueueLength;
             }
+            else if ( ucQueueType == queueQUEUE_TYPE_BASE )
+            {
+                rt_snprintf( name, RT_NAME_MAX, "queue%02d", queue_index++ );
+                rt_mq_init( &( pxStaticQueue->ipc_obj ), name, pucQueueStorage, uxItemSize, QUEUE_BUFFER_SIZE( uxQueueLength, uxItemSize ), RT_IPC_FLAG_PRIO );
+            }
             else
             {
                 return pxNewQueue;
@@ -119,12 +125,12 @@ static volatile rt_uint8_t sem_index = 0;
             }
             if ( ucQueueType == queueQUEUE_TYPE_RECURSIVE_MUTEX || ucQueueType == queueQUEUE_TYPE_MUTEX )
             {
-                rt_snprintf( name, RT_NAME_MAX - 1, "mutex%02d", mutex_index++ );
+                rt_snprintf( name, RT_NAME_MAX, "mutex%02d", mutex_index++ );
                 pipc = ( struct rt_ipc_object * ) rt_mutex_create( name, RT_IPC_FLAG_PRIO );
             }
             else if ( ucQueueType == queueQUEUE_TYPE_BINARY_SEMAPHORE || ucQueueType == queueQUEUE_TYPE_COUNTING_SEMAPHORE )
             {
-                rt_snprintf( name, RT_NAME_MAX - 1, "sem%02d", sem_index++ );
+                rt_snprintf( name, RT_NAME_MAX, "sem%02d", sem_index++ );
                 pipc = ( struct rt_ipc_object * ) RT_KERNEL_MALLOC( sizeof( struct rt_semaphore_wrapper ) );
                 if ( pipc != RT_NULL )
                 {
@@ -134,6 +140,12 @@ static volatile rt_uint8_t sem_index = 0;
                     pipc->parent.type &= ~RT_Object_Class_Static;
                 }
             }
+            else if ( ucQueueType == queueQUEUE_TYPE_BASE )
+            {
+                rt_snprintf( name, RT_NAME_MAX, "queue%02d", queue_index++ );
+                pipc = ( struct rt_ipc_object * ) rt_mq_create( name, uxItemSize, uxQueueLength, RT_IPC_FLAG_PRIO);
+            }
+
             if ( pipc == RT_NULL )
             {
                 RT_KERNEL_FREE( pxNewQueue );
@@ -296,6 +308,18 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
         }
         rt_hw_interrupt_enable( level );
     }
+    else if ( type == RT_Object_Class_MessageQueue )
+    {
+        if ( xCopyPosition == queueSEND_TO_BACK )
+        {
+            err = rt_mq_send_wait( ( rt_mq_t ) pipc, pvItemToQueue, ( ( rt_mq_t ) pipc )->msg_size, ( rt_int32_t ) xTicksToWait );
+        }
+        else if ( xCopyPosition == queueSEND_TO_FRONT )
+        {
+            // TODO: need to implement the timeout for LIFO
+            err = rt_mq_urgent( ( rt_mq_t ) pipc, pvItemToQueue, ( ( rt_mq_t ) pipc )->msg_size );
+        }
+    }
 
     return rt_err_to_freertos( err );
 }
@@ -334,6 +358,37 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
 }
 /*-----------------------------------------------------------*/
 
+BaseType_t xQueueReceive( QueueHandle_t xQueue,
+                          void * const pvBuffer,
+                          TickType_t xTicksToWait )
+{
+    Queue_t * const pxQueue = xQueue;
+    struct rt_ipc_object *pipc;
+    rt_uint8_t type;
+    rt_err_t err = -RT_ERROR;
+
+    /* Check the queue pointer is not NULL. */
+    configASSERT( ( pxQueue ) );
+
+    /* Cannot block if the scheduler is suspended. */
+    #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+        {
+            configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+        }
+    #endif
+
+    pipc = pxQueue->rt_ipc;
+    RT_ASSERT( pipc != RT_NULL );
+    type = rt_object_get_type( &pipc->parent );
+    if ( type == RT_Object_Class_MessageQueue )
+    {
+        err = rt_mq_recv( ( rt_mq_t ) pipc, pvBuffer, ( ( rt_mq_t ) pipc )->msg_size, ( rt_int32_t ) xTicksToWait );
+    }
+
+    return rt_err_to_freertos( err );
+}
+/*-----------------------------------------------------------*/
+
 BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
                                 TickType_t xTicksToWait )
 {
@@ -420,9 +475,9 @@ void vQueueDelete( QueueHandle_t xQueue )
         {
             rt_sem_detach( ( rt_sem_t ) pipc );
         }
-        else if ( type == RT_Object_Class_MailBox )
+        else if ( type == RT_Object_Class_MessageQueue )
         {
-            rt_mb_detach( ( rt_mailbox_t ) pipc );
+            rt_mq_detach( ( rt_mq_t ) pipc );
         }
     #endif
 #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
@@ -442,9 +497,9 @@ void vQueueDelete( QueueHandle_t xQueue )
             rt_sem_detach( ( rt_sem_t ) pipc );
             RT_KERNEL_FREE( pipc );
         }
-        else if ( type == RT_Object_Class_MailBox )
+        else if ( type == RT_Object_Class_MessageQueue )
         {
-            rt_mb_delete( ( rt_mailbox_t ) pipc );
+            rt_mq_delete( ( rt_mq_t ) pipc );
         }
         else
         {

+ 98 - 0
test/test_queue_dynamic.c

@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: queue
+ *
+ * This demo demonstrates dynamically creating a queue and using it to send data between two tasks.
+ *
+ */
+
+#include <FreeRTOS.h>
+#include <queue.h>
+#include <task.h>
+
+#define TASK_PRIORITY         8
+#define QUEUE_LENGTH          10
+#define ITEM_SIZE             sizeof( uint32_t )
+
+/* queue handler */
+static QueueHandle_t xQueue = NULL;
+static TaskHandle_t TaskHandle1 = NULL;
+static TaskHandle_t TaskHandle2 = NULL;
+
+static void vTask1Code(void *pvParameters)
+{
+    BaseType_t xReturn;
+    uint32_t num = 0;
+    while (1)
+    {
+        xReturn = xQueueReceive(xQueue, &num, portMAX_DELAY);
+        if (xReturn != pdPASS)
+        {
+            rt_kprintf("Task 1 receive from queue failed\n");
+        }
+        else
+        {
+            rt_kprintf("Task 1 receive data %d from queue\n", num);
+        }
+        if (num >= 100)
+        {
+            return;
+        }
+    }
+}
+
+static void vTask2Code(void * pvParameters)
+{
+    BaseType_t xReturn;
+    uint32_t num = 0;
+    while (1)
+    {
+        xReturn = xQueueSendToBack(xQueue, &num, 0);
+        if (xReturn != pdPASS)
+        {
+            rt_kprintf("Task 2 send to queue failed\n");
+        }
+        num += 1;
+        if (num >= 100)
+        {
+            return;
+        }
+    }
+}
+
+int queue_dynamic(void)
+{
+    /* Create a queue dynamically */
+    xQueue = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE);
+    if (xQueue == NULL)
+    {
+        rt_kprintf("create dynamic queue failed.\n");
+        return -1;
+    }
+    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle1 );
+    if (TaskHandle1 == NULL)
+    {
+        rt_kprintf("Create task 1 failed\n");
+        return -1;
+    }
+    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &TaskHandle2 );
+    if (TaskHandle2 == NULL)
+    {
+        rt_kprintf("Create task 2 failed\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+MSH_CMD_EXPORT(queue_dynamic, queue sample);

+ 100 - 0
test/test_queue_static.c

@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ * 2020-10-17     Meco Man     translate to English comment
+ */
+
+/*
+ * Demo: queue
+ *
+ * This demo demonstrates statically creating a queue and using it to send data between two tasks.
+ *
+ */
+
+#include <FreeRTOS.h>
+#include <queue.h>
+#include <task.h>
+
+#define TASK_PRIORITY         8
+#define QUEUE_LENGTH          10
+#define ITEM_SIZE             sizeof( uint32_t )
+
+/* queue handler */
+static QueueHandle_t xQueue = NULL;
+static StaticQueue_t xQueueBuffer;
+static uint8_t ucQueueStorage[ QUEUE_BUFFER_SIZE( QUEUE_LENGTH, ITEM_SIZE) ];
+static TaskHandle_t TaskHandle1 = NULL;
+static TaskHandle_t TaskHandle2 = NULL;
+
+static void vTask1Code(void *pvParameters)
+{
+    BaseType_t xReturn;
+    uint32_t num = 0;
+    while (1)
+    {
+        xReturn = xQueueReceive(xQueue, &num, portMAX_DELAY);
+        if (xReturn != pdPASS)
+        {
+            rt_kprintf("Task 1 receive from queue failed\n");
+        }
+        else
+        {
+            rt_kprintf("Task 1 receive data %d from queue\n", num);
+        }
+        if (num >= 100)
+        {
+            return;
+        }
+    }
+}
+
+static void vTask2Code(void * pvParameters)
+{
+    BaseType_t xReturn;
+    uint32_t num = 0;
+    while (1)
+    {
+        xReturn = xQueueSendToBack(xQueue, &num, 0);
+        if (xReturn != pdPASS)
+        {
+            rt_kprintf("Task 2 send to queue failed\n");
+        }
+        num += 1;
+        if (num >= 100)
+        {
+            return;
+        }
+    }
+}
+
+int queue_static(void)
+{
+    /* Create a queue statically */
+    xQueue = xQueueCreateStatic( QUEUE_LENGTH, ITEM_SIZE, &( ucQueueStorage[ 0 ] ), &xQueueBuffer);
+    if (xQueue == NULL)
+    {
+        rt_kprintf("create static queue failed.\n");
+        return -1;
+    }
+    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle1 );
+    if (TaskHandle1 == NULL)
+    {
+        rt_kprintf("Create task 1 failed\n");
+        return -1;
+    }
+    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &TaskHandle2 );
+    if (TaskHandle2 == NULL)
+    {
+        rt_kprintf("Create task 2 failed\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+MSH_CMD_EXPORT(queue_static, queue sample);