Procházet zdrojové kódy

Semaphore get value.
Mutex get holder.
Queue get message count, spaces available

tangzz98 před 3 roky
rodič
revize
3c469c9b48

+ 1 - 0
FreeRTOS/include/FreeRTOSConfig.h

@@ -142,5 +142,6 @@ standard names. */
 #define configMAX_PRIORITIES                    ( 32 )
 #define configMAX_PRIORITIES                    ( 32 )
 #define configUSE_TIMERS                        1
 #define configUSE_TIMERS                        1
 #define INCLUDE_xTaskGetSchedulerState          1
 #define INCLUDE_xTaskGetSchedulerState          1
+#define INCLUDE_xSemaphoreGetMutexHolder        1
 
 
 #endif /* FREERTOS_CONFIG_H */
 #endif /* FREERTOS_CONFIG_H */

+ 48 - 0
FreeRTOS/include/queue.h

@@ -36,6 +36,8 @@
 #endif
 #endif
 /* *INDENT-ON* */
 /* *INDENT-ON* */
 
 
+#include "task.h"
+
 /**
 /**
  * Type by which queues are referenced.  For example, a call to xQueueCreate()
  * Type by which queues are referenced.  For example, a call to xQueueCreate()
  * returns an QueueHandle_t variable that can then be used as a parameter to
  * returns an QueueHandle_t variable that can then be used as a parameter to
@@ -648,6 +650,42 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue,
                           void * const pvBuffer,
                           void * const pvBuffer,
                           TickType_t xTicksToWait );
                           TickType_t xTicksToWait );
 
 
+/**
+ * queue. h
+ * @code{c}
+ * UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
+ * @endcode
+ *
+ * Return the number of messages stored in a queue.
+ *
+ * @param xQueue A handle to the queue being queried.
+ *
+ * @return The number of messages available in the queue.
+ *
+ * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting
+ * \ingroup QueueManagement
+ */
+UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
+
+/**
+ * queue. h
+ * @code{c}
+ * UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+ * @endcode
+ *
+ * Return the number of free spaces available in a queue.  This is equal to the
+ * number of items that can be sent to the queue before the queue becomes full
+ * if no items are removed.
+ *
+ * @param xQueue A handle to the queue being queried.
+ *
+ * @return The number of spaces available in the queue.
+ *
+ * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting
+ * \ingroup QueueManagement
+ */
+UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+
 /**
 /**
  * queue. h
  * queue. h
  * @code{c}
  * @code{c}
@@ -1057,6 +1095,14 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
                                  void * const pvBuffer,
                                  void * const pvBuffer,
                                  BaseType_t * const pxHigherPriorityTaskWoken );
                                  BaseType_t * const pxHigherPriorityTaskWoken );
 
 
+/*
+ * Utilities to query queues that are safe to use from an ISR.  These utilities
+ * should be used only from witin an ISR, or within a critical section.
+ */
+BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue );
+BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue );
+UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue );
+
 /*
 /*
  * For internal use only.  Use xSemaphoreCreateMutex(),
  * For internal use only.  Use xSemaphoreCreateMutex(),
  * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling
  * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling
@@ -1072,6 +1118,8 @@ QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
                                                    StaticQueue_t * pxStaticQueue );
                                                    StaticQueue_t * pxStaticQueue );
 BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
 BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
                                 TickType_t xTicksToWait );
                                 TickType_t xTicksToWait );
+TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore );
+TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore );
 
 
 /*
 /*
  * For internal use only.  Use xSemaphoreTakeMutexRecursive() or
  * For internal use only.  Use xSemaphoreTakeMutexRecursive() or

+ 58 - 0
FreeRTOS/include/semphr.h

@@ -1127,4 +1127,62 @@ typedef QueueHandle_t SemaphoreHandle_t;
  */
  */
 #define vSemaphoreDelete( xSemaphore )                   vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
 #define vSemaphoreDelete( xSemaphore )                   vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
 
 
+/**
+ * semphr.h
+ * @code{c}
+ * TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
+ * @endcode
+ *
+ * If xMutex is indeed a mutex type semaphore, return the current mutex holder.
+ * If xMutex is not a mutex type semaphore, or the mutex is available (not held
+ * by a task), return NULL.
+ *
+ * Note: This is a good way of determining if the calling task is the mutex
+ * holder, but not a good way of determining the identity of the mutex holder as
+ * the holder may change between the function exiting and the returned value
+ * being tested.
+ */
+#define xSemaphoreGetMutexHolder( xSemaphore )           xQueueGetMutexHolder( ( xSemaphore ) )
+
+/**
+ * semphr.h
+ * @code{c}
+ * TaskHandle_t xSemaphoreGetMutexHolderFromISR( SemaphoreHandle_t xMutex );
+ * @endcode
+ *
+ * If xMutex is indeed a mutex type semaphore, return the current mutex holder.
+ * If xMutex is not a mutex type semaphore, or the mutex is available (not held
+ * by a task), return NULL.
+ *
+ */
+#define xSemaphoreGetMutexHolderFromISR( xSemaphore )    xQueueGetMutexHolderFromISR( ( xSemaphore ) )
+
+/**
+ * semphr.h
+ * @code{c}
+ * UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
+ * @endcode
+ *
+ * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns
+ * its current count value.  If the semaphore is a binary semaphore then
+ * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the
+ * semaphore is not available.
+ *
+ */
+#define uxSemaphoreGetCount( xSemaphore )                uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) )
+
+/**
+ * semphr.h
+ * @code{c}
+ * UBaseType_t uxSemaphoreGetCountFromISR( SemaphoreHandle_t xSemaphore );
+ * @endcode
+ *
+ * If the semaphore is a counting semaphore then uxSemaphoreGetCountFromISR() returns
+ * its current count value.  If the semaphore is a binary semaphore then
+ * uxSemaphoreGetCountFromISR() returns 1 if the semaphore is available, and 0 if the
+ * semaphore is not available.
+ *
+ */
+#define uxSemaphoreGetCountFromISR( xSemaphore )         uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) )
+
 #endif /* SEMAPHORE_H */
 #endif /* SEMAPHORE_H */

+ 154 - 0
FreeRTOS/queue.c

@@ -216,6 +216,48 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
 #endif /* configUSE_MUTEXES */
 #endif /* configUSE_MUTEXES */
 /*-----------------------------------------------------------*/
 /*-----------------------------------------------------------*/
 
 
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+
+    TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore )
+    {
+        TaskHandle_t pxReturn;
+        struct rt_ipc_object *pipc;
+        rt_uint8_t type;
+        rt_base_t level;
+
+        configASSERT( xSemaphore );
+
+        pipc = xSemaphore->rt_ipc;
+        RT_ASSERT( pipc != RT_NULL );
+        type = rt_object_get_type( &pipc->parent );
+
+        if ( type == RT_Object_Class_Mutex )
+        {
+            level = rt_hw_interrupt_disable();
+            pxReturn = ( TaskHandle_t ) ( ( rt_mutex_t ) pipc )->owner;
+            rt_hw_interrupt_enable( level );
+        }
+        else
+        {
+            pxReturn = NULL;
+        }
+
+        return pxReturn;
+    }
+
+#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+
+    TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore )
+    {
+        return xQueueGetMutexHolder( xSemaphore );
+    }
+
+#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
+/*-----------------------------------------------------------*/
+
 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
 
 
     BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
     BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
@@ -515,6 +557,80 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
 }
 }
 /*-----------------------------------------------------------*/
 /*-----------------------------------------------------------*/
 
 
+UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
+{
+    UBaseType_t uxReturn = 0;
+    struct rt_ipc_object *pipc;
+    rt_uint8_t type;
+    rt_base_t level;
+
+    configASSERT( xQueue );
+
+    pipc = xQueue->rt_ipc;
+    RT_ASSERT( pipc != RT_NULL );
+    type = rt_object_get_type( &pipc->parent );
+
+    level = rt_hw_interrupt_disable();
+
+    if ( type == RT_Object_Class_Mutex )
+    {
+        uxReturn = ( ( rt_mutex_t ) pipc )->value;
+    }
+    else if ( type == RT_Object_Class_Semaphore )
+    {
+        uxReturn = ( ( rt_sem_t ) pipc )->value;
+    }
+    else if ( type == RT_Object_Class_MessageQueue )
+    {
+        uxReturn = ( ( rt_mq_t ) pipc )->entry;
+    }
+
+    rt_hw_interrupt_enable( level );
+
+    return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
+{
+    UBaseType_t uxReturn = 0;
+    struct rt_ipc_object *pipc;
+    rt_uint8_t type;
+    rt_base_t level;
+
+    configASSERT( xQueue );
+
+    pipc = xQueue->rt_ipc;
+    RT_ASSERT( pipc != RT_NULL );
+    type = rt_object_get_type( &pipc->parent );
+
+    level = rt_hw_interrupt_disable();
+
+    if ( type == RT_Object_Class_Mutex )
+    {
+        uxReturn = 1 - ( ( rt_mutex_t ) pipc )->value;
+    }
+    else if ( type == RT_Object_Class_Semaphore )
+    {
+        uxReturn = ( ( struct rt_semaphore_wrapper * ) pipc )->max_value - ( ( rt_sem_t ) pipc )->value;
+    }
+    else if ( type == RT_Object_Class_MessageQueue )
+    {
+        uxReturn = ( ( rt_mq_t ) pipc )->max_msgs - ( ( rt_mq_t ) pipc )->entry;
+    }
+
+    rt_hw_interrupt_enable( level );
+
+    return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )
+{
+    return uxQueueMessagesWaiting( xQueue );
+}
+/*-----------------------------------------------------------*/
+
 void vQueueDelete( QueueHandle_t xQueue )
 void vQueueDelete( QueueHandle_t xQueue )
 {
 {
     Queue_t * const pxQueue = xQueue;
     Queue_t * const pxQueue = xQueue;
@@ -574,3 +690,41 @@ void vQueueDelete( QueueHandle_t xQueue )
     }
     }
 }
 }
 /*-----------------------------------------------------------*/
 /*-----------------------------------------------------------*/
+
+BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )
+{
+    BaseType_t xReturn;
+
+    configASSERT( pxQueue );
+
+    if( uxQueueMessagesWaiting( xQueue ) == ( UBaseType_t ) 0 )
+    {
+        xReturn = pdTRUE;
+    }
+    else
+    {
+        xReturn = pdFALSE;
+    }
+
+    return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
+{
+    BaseType_t xReturn;
+
+    configASSERT( pxQueue );
+
+    if ( uxQueueSpacesAvailable( xQueue ) == ( UBaseType_t ) 0 )
+    {
+        xReturn = pdTRUE;
+    }
+    else
+    {
+        xReturn = pdFALSE;
+    }
+
+    return xReturn;
+}
+/*-----------------------------------------------------------*/

+ 6 - 6
test/test_semaphore_counting_dynamic.c

@@ -97,18 +97,18 @@ int semaphore_counting_dynamic()
         rt_kprintf("create dynamic semaphore failed.\n");
         rt_kprintf("create dynamic semaphore failed.\n");
         return -1;
         return -1;
     }
     }
-    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &TaskHandle1 );
-    if (TaskHandle1 == NULL)
-    {
-        rt_kprintf("Create task 1 failed\n");
-        return -1;
-    }
     xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle2 );
     xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle2 );
     if (TaskHandle2 == NULL)
     if (TaskHandle2 == NULL)
     {
     {
         rt_kprintf("Create task 2 failed\n");
         rt_kprintf("Create task 2 failed\n");
         return -1;
         return -1;
     }
     }
+    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &TaskHandle1 );
+    if (TaskHandle1 == NULL)
+    {
+        rt_kprintf("Create task 1 failed\n");
+        return -1;
+    }
 
 
     return 0;
     return 0;
 }
 }

+ 6 - 6
test/test_semaphore_counting_static.c

@@ -100,18 +100,18 @@ int semaphore_counting_static()
         rt_kprintf("create static semaphore failed.\n");
         rt_kprintf("create static semaphore failed.\n");
         return -1;
         return -1;
     }
     }
-    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &TaskHandle1 );
-    if (TaskHandle1 == NULL)
-    {
-        rt_kprintf("Create task 1 failed\n");
-        return -1;
-    }
     xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle2 );
     xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle2 );
     if (TaskHandle2 == NULL)
     if (TaskHandle2 == NULL)
     {
     {
         rt_kprintf("Create task 2 failed\n");
         rt_kprintf("Create task 2 failed\n");
         return -1;
         return -1;
     }
     }
+    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &TaskHandle1 );
+    if (TaskHandle1 == NULL)
+    {
+        rt_kprintf("Create task 1 failed\n");
+        return -1;
+    }
 
 
     return 0;
     return 0;
 }
 }