From 7b41d6004af4b975ddaca2bfac5170fededead38 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Fri, 7 Apr 2023 01:32:44 +0800 Subject: [PATCH 1/4] freertos: Fix idf_additions.h include order error When building for CONFIG_FREERTOS_SMP, "idf_additions.h" was previously implicitly included by "task.h" so that other ESP-IDF components still have access to IDF API additions without needing to include "idf_additions.h" directly. However, some FreeRTOS headers (e.g., queue.h) will include task.h before declaring any types (e.g., QueueHandle_t). Thus if any of those types are used in idf_additions.h, we get a missing type error. This commit moves the implicity include of idf_additions.h to FreeRTOS.h --- .../FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h index 60abd75b6c..b25b7bd330 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h @@ -1391,4 +1391,11 @@ typedef StaticStreamBuffer_t StaticMessageBuffer_t; #endif /* *INDENT-ON* */ +/* IDF API additions have been moved to idf_additions.h when building for + * Amazon SMP FreeRTOS. However, the rest of ESP-IDF has not been updated to + * include this header explicitly when calling this additional API. Thus, we + * include this here as a workaround until the rest of ESP-IDF can be updated + * to include idf_additions.h explicitly. */ +#include "freertos/idf_additions.h" + #endif /* INC_FREERTOS_H */ From 3562cb805147a90723e407e37ac9014ffeb1a57b Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 21 Mar 2023 21:29:52 +0800 Subject: [PATCH 2/4] freertos: Add GetStaticBuffer functions This commit adds the various ...GetStaticBuffer() functions from upstream FreeRTOS. See https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/641 for more details. --- .../FreeRTOS-Kernel-SMP/event_groups.c | 36 ++++++++++++++ .../include/freertos/event_groups.h | 22 +++++++++ .../include/freertos/message_buffer.h | 31 ++++++++++++ .../include/freertos/queue.h | 41 ++++++++++++++++ .../include/freertos/semphr.h | 21 ++++++++ .../include/freertos/stream_buffer.h | 32 ++++++++++++ .../include/freertos/task.h | 30 ++++++++++++ .../include/freertos/timers.h | 19 +++++++ .../freertos/FreeRTOS-Kernel-SMP/queue.c | 49 +++++++++++++++++++ .../FreeRTOS-Kernel-SMP/stream_buffer.c | 28 +++++++++++ .../freertos/FreeRTOS-Kernel-SMP/tasks.c | 47 ++++++++++++++++++ .../freertos/FreeRTOS-Kernel-SMP/timers.c | 24 +++++++++ .../freertos/FreeRTOS-Kernel/event_groups.c | 36 ++++++++++++++ .../include/freertos/event_groups.h | 24 +++++++++ .../include/freertos/message_buffer.h | 33 +++++++++++++ .../FreeRTOS-Kernel/include/freertos/queue.h | 43 ++++++++++++++++ .../FreeRTOS-Kernel/include/freertos/semphr.h | 23 +++++++++ .../include/freertos/stream_buffer.h | 34 +++++++++++++ .../FreeRTOS-Kernel/include/freertos/task.h | 32 ++++++++++++ .../FreeRTOS-Kernel/include/freertos/timers.h | 20 ++++++++ components/freertos/FreeRTOS-Kernel/queue.c | 49 +++++++++++++++++++ .../freertos/FreeRTOS-Kernel/stream_buffer.c | 28 +++++++++++ components/freertos/FreeRTOS-Kernel/tasks.c | 47 ++++++++++++++++++ components/freertos/FreeRTOS-Kernel/timers.c | 24 +++++++++ .../include/freertos/idf_additions.h | 4 +- 25 files changed, 775 insertions(+), 2 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/event_groups.c b/components/freertos/FreeRTOS-Kernel-SMP/event_groups.c index ae8e20be7d..3e72547c49 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/event_groups.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/event_groups.c @@ -665,6 +665,42 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) } /*-----------------------------------------------------------*/ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, + StaticEventGroup_t ** ppxEventGroupBuffer ) + { + BaseType_t xReturn; + EventGroup_t * pxEventBits = xEventGroup; + + configASSERT( pxEventBits ); + configASSERT( ppxEventGroupBuffer ); + + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Check if the event group was statically allocated. */ + if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE ) + { + *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + #else /* configSUPPORT_DYNAMIC_ALLOCATION */ + { + /* Event group must have been statically allocated. */ + *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; + xReturn = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + return xReturn; + } +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + /* For internal use only - execute a 'set bits' command that was pended from * an interrupt. */ portTIMER_CALLBACK_ATTRIBUTE diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h index 3a80d78564..48108a3da3 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h @@ -753,6 +753,28 @@ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEG */ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; +/** + * event_groups.h + * @code{c} + * BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, + * StaticEventGroup_t ** ppxEventGroupBuffer ); + * @endcode + * + * Retrieve a pointer to a statically created event groups's data structure + * buffer. It is the same buffer that is supplied at the time of creation. + * + * @param xEventGroup The event group for which to retrieve the buffer. + * + * @param ppxEventGroupBuffer Used to return a pointer to the event groups's + * data structure buffer. + * + * @return pdTRUE if the buffer was retrieved, pdFALSE otherwise. + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, + StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION; +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /* For internal use only. */ void vEventGroupSetBitsCallback( void * pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h index be16eb1f30..aa05f233cb 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h @@ -210,6 +210,37 @@ typedef void * MessageBufferHandle_t; #define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \ ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer ) +/** + * message_buffer.h + * + * @code{c} + * BaseType_t xMessageBufferGetStaticBuffers( MessageBufferHandle_t xMessageBuffer, + * uint8_t ** ppucMessageBufferStorageArea, + * StaticMessageBuffer_t ** ppxStaticMessageBuffer ); + * @endcode + * + * Retrieve pointers to a statically created message buffer's data structure + * buffer and storage area buffer. These are the same buffers that are supplied + * at the time of creation. + * + * @param xMessageBuffer The message buffer for which to retrieve the buffers. + * + * @param ppucMessageBufferStorageArea Used to return a pointer to the + * message buffer's storage area buffer. + * + * @param ppxStaticMessageBuffer Used to return a pointer to the message + * buffer's data structure buffer. + * + * @return pdTRUE if buffers were retrieved, pdFALSE otherwise.. + * + * \defgroup xMessageBufferGetStaticBuffers xMessageBufferGetStaticBuffers + * \ingroup MessageBufferManagement + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xMessageBufferGetStaticBuffers( xMessageBuffer, ppucMessageBufferStorageArea, ppxStaticMessageBuffer ) \ + xStreamBufferGetStaticBuffers( ( xMessageBuffer ), ( ppucMessageBufferStorageArea ), ( ppxStaticMessageBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /** * message_buffer.h * diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h index 1f8b3a75e8..446f73493f 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h @@ -233,6 +233,35 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ +/** + * queue. h + * @code{c} + * BaseType_t xQueueGetStaticBuffers( QueueHandle_t xQueue, + * uint8_t ** ppucQueueStorage, + * StaticQueue_t ** ppxStaticQueue ); + * @endcode + * + * Retrieve pointers to a statically created queue's data structure buffer + * and storage area buffer. These are the same buffers that are supplied + * at the time of creation. + * + * @param xQueue The queue for which to retrieve the buffers. + * + * @param ppucQueueStorage Used to return a pointer to the queue's storage + * area buffer. + * + * @param ppxStaticQueue Used to return a pointer to the queue's data + * structure buffer. + * + * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. + * + * \defgroup xQueueGetStaticBuffers xQueueGetStaticBuffers + * \ingroup QueueManagement + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xQueueGetStaticBuffers( xQueue, ppucQueueStorage, ppxStaticQueue ) xQueueGenericGetStaticBuffers( ( xQueue ), ( ppucQueueStorage ), ( ppxStaticQueue ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /** * queue. h *
@@ -1558,6 +1587,18 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION;
                                              const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
 #endif
 
+/*
+ * Generic version of the function used to retrieve the buffers of statically
+ * created queues. This is called by other functions and macros that retrieve
+ * the buffers of other statically created RTOS objects that use the queue
+ * structure as their base.
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+    BaseType_t xQueueGenericGetStaticBuffers( QueueHandle_t xQueue,
+                                              uint8_t ** ppucQueueStorage,
+                                              StaticQueue_t ** ppxStaticQueue ) PRIVILEGED_FUNCTION;
+#endif
+
 /*
  * Queue sets provide a mechanism to allow a task to block (pend) on a read
  * operation from multiple queues or semaphores simultaneously.
diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h
index fd9469d9c9..d72bf45b1b 100644
--- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h
+++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h
@@ -1170,4 +1170,25 @@ typedef QueueHandle_t SemaphoreHandle_t;
  */
 #define uxSemaphoreGetCount( xSemaphore )                uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) )
 
+/**
+ * semphr.h
+ * @code{c}
+ * BaseType_t xSemaphoreGetStaticBuffer( SemaphoreHandle_t xSemaphore );
+ * @endcode
+ *
+ * Retrieve pointer to a statically created binary semaphore, counting semaphore,
+ * or mutex semaphore's data structure buffer. This is the same buffer that is
+ * supplied at the time of creation.
+ *
+ * @param xSemaphore The semaphore for which to retrieve the buffer.
+ *
+ * @param ppxSemaphoreBuffer Used to return a pointer to the semaphore's
+ * data structure buffer.
+ *
+ * @return pdTRUE if buffer was retrieved, pdFALSE otherwise.
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+    #define xSemaphoreGetStaticBuffer( xSemaphore, ppxSemaphoreBuffer )    xQueueGenericGetStaticBuffers( ( QueueHandle_t ) ( xSemaphore ), NULL, ( ppxSemaphoreBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
 #endif /* SEMAPHORE_H */
diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h
index c5eac02b02..00f9d0585e 100644
--- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h
+++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h
@@ -219,6 +219,38 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
 #define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \
     xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer )
 
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer,
+ *                                           uint8_t ** ppucStreamBufferStorageArea,
+ *                                           StaticStreamBuffer_t ** ppxStaticStreamBuffer );
+ * @endcode
+ *
+ * Retrieve pointers to a statically created stream buffer's data structure
+ * buffer and storage area buffer. These are the same buffers that are supplied
+ * at the time of creation.
+ *
+ * @param xStreamBuffer The stream buffer for which to retrieve the buffers.
+ *
+ * @param ppucStreamBufferStorageArea Used to return a pointer to the stream
+ * buffer's storage area buffer.
+ *
+ * @param ppxStaticStreamBuffer Used to return a pointer to the stream
+ * buffer's data structure buffer.
+ *
+ * @return pdTRUE if buffers were retrieved, pdFALSE otherwise.
+ *
+ * \defgroup xStreamBufferGetStaticBuffers xStreamBufferGetStaticBuffers
+ * \ingroup StreamBufferManagement
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+    BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer,
+                                              uint8_t ** ppucStreamBufferStorageArea,
+                                              StaticStreamBuffer_t ** ppxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
 /**
  * stream_buffer.h
  *
diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h
index 0a91ae8b98..93f6079d08 100644
--- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h
+++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h
@@ -1704,6 +1704,36 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION;     /*lin
  */
 TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION;     /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask,
+ *                                   StackType_t ** ppuxStackBuffer,
+ *                                   StaticTask_t ** ppxTaskBuffer );
+ * @endcode
+ *
+ * Retrieve pointers to a statically created task's data structure
+ * buffer and stack buffer. These are the same buffers that are supplied
+ * at the time of creation.
+ *
+ * @param xTask The task for which to retrieve the buffers.
+ *
+ * @param ppuxStackBuffer Used to return a pointer to the task's stack buffer.
+ *
+ * @param ppxTaskBuffer Used to return a pointer to the task's data structure
+ * buffer.
+ *
+ * @return pdTRUE if buffers were retrieved, pdFALSE otherwise.
+ *
+ * \defgroup xTaskGetStaticBuffers xTaskGetStaticBuffers
+ * \ingroup TaskUtils
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+    BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask,
+                                      StackType_t ** ppuxStackBuffer,
+                                      StaticTask_t ** ppxTaskBuffer ) PRIVILEGED_FUNCTION;
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
 /**
  * task.h
  * 
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h index 13492897af..5604cdd91e 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h @@ -1307,6 +1307,25 @@ TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; */ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; +/** + * BaseType_t xTimerGetStaticBuffer( TimerHandle_t xTimer, + * StaticTimer_t ** ppxTimerBuffer ); + * + * Retrieve pointer to a statically created timer's data structure + * buffer. This is the same buffer that is supplied at the time of + * creation. + * + * @param xTimer The timer for which to retrieve the buffer. + * + * @param ppxTimerBuffer Used to return a pointer to the timers's data + * structure buffer. + * + * @return pdTRUE if the buffer was retrieved, pdFALSE otherwise. + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xTimerGetStaticBuffer( TimerHandle_t xTimer, + StaticTimer_t ** ppxTimerBuffer ) PRIVILEGED_FUNCTION; +#endif /* configSUPPORT_STATIC_ALLOCATION */ /* * Functions beyond this part are not part of the public API and are intended * for use by the kernel only. diff --git a/components/freertos/FreeRTOS-Kernel-SMP/queue.c b/components/freertos/FreeRTOS-Kernel-SMP/queue.c index 56869290b8..51895e5a23 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/queue.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/queue.c @@ -379,6 +379,55 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + + BaseType_t xQueueGenericGetStaticBuffers( QueueHandle_t xQueue, + uint8_t ** ppucQueueStorage, + StaticQueue_t ** ppxStaticQueue ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + configASSERT( ppxStaticQueue ); + + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Check if the queue was statically allocated. */ + if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdTRUE ) + { + if( ppucQueueStorage != NULL ) + { + *ppucQueueStorage = ( uint8_t * ) pxQueue->pcHead; + } + + *ppxStaticQueue = ( StaticQueue_t * ) pxQueue; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + #else /* configSUPPORT_DYNAMIC_ALLOCATION */ + { + /* Queue must have been statically allocated. */ + if( ppucQueueStorage != NULL ) + { + *ppucQueueStorage = ( uint8_t * ) pxQueue->pcHead; + } + + *ppxStaticQueue = ( StaticQueue_t * ) pxQueue; + xReturn = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + return xReturn; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, diff --git a/components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c b/components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c index 47c8a9a652..0208032186 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c @@ -367,6 +367,34 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, #endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*-----------------------------------------------------------*/ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer, + uint8_t ** ppucStreamBufferStorageArea, + StaticStreamBuffer_t ** ppxStaticStreamBuffer ) + { + BaseType_t xReturn; + const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + + configASSERT( pxStreamBuffer ); + configASSERT( ppucStreamBufferStorageArea ); + configASSERT( ppxStaticStreamBuffer ); + + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) != ( uint8_t ) 0 ) + { + *ppucStreamBufferStorageArea = pxStreamBuffer->pucBuffer; + *ppxStaticStreamBuffer = ( StaticStreamBuffer_t * ) pxStreamBuffer; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; + } +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) { StreamBuffer_t * pxStreamBuffer = xStreamBuffer; diff --git a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c index ff3d3d9030..8ebecd7102 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c @@ -3359,6 +3359,53 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char #endif /* INCLUDE_xTaskGetHandle */ /*-----------------------------------------------------------*/ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + + BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, + StackType_t ** ppuxStackBuffer, + StaticTask_t ** ppxTaskBuffer ) + { + BaseType_t xReturn; + TCB_t * pxTCB; + + configASSERT( ppuxStackBuffer != NULL ); + configASSERT( ppxTaskBuffer != NULL ); + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 ) + { + if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ) + { + *ppuxStackBuffer = pxTCB->pxStack; + *ppxTaskBuffer = ( StaticTask_t * ) pxTCB; + xReturn = pdTRUE; + } + else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) + { + *ppuxStackBuffer = pxTCB->pxStack; + *ppxTaskBuffer = NULL; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + #else /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */ + { + *ppuxStackBuffer = pxTCB->pxStack; + *ppxTaskBuffer = ( StaticTask_t * ) pxTCB; + xReturn = pdTRUE; + } + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */ + + return xReturn; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, diff --git a/components/freertos/FreeRTOS-Kernel-SMP/timers.c b/components/freertos/FreeRTOS-Kernel-SMP/timers.c index 65455cc8da..b98e9b9ec9 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/timers.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/timers.c @@ -534,6 +534,30 @@ } /*-----------------------------------------------------------*/ + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xTimerGetStaticBuffer( TimerHandle_t xTimer, + StaticTimer_t ** ppxTimerBuffer ) + { + BaseType_t xReturn; + Timer_t * pxTimer = xTimer; + + configASSERT( ppxTimerBuffer != NULL ); + + if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) != 0 ) + { + *ppxTimerBuffer = ( StaticTimer_t * ) pxTimer; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { Timer_t * pxTimer = xTimer; diff --git a/components/freertos/FreeRTOS-Kernel/event_groups.c b/components/freertos/FreeRTOS-Kernel/event_groups.c index ffdf23db5c..8b1b184b17 100644 --- a/components/freertos/FreeRTOS-Kernel/event_groups.c +++ b/components/freertos/FreeRTOS-Kernel/event_groups.c @@ -702,6 +702,42 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) } /*-----------------------------------------------------------*/ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, + StaticEventGroup_t ** ppxEventGroupBuffer ) + { + BaseType_t xReturn; + EventGroup_t * pxEventBits = xEventGroup; + + configASSERT( pxEventBits ); + configASSERT( ppxEventGroupBuffer ); + + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Check if the event group was statically allocated. */ + if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE ) + { + *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + #else /* configSUPPORT_DYNAMIC_ALLOCATION */ + { + /* Event group must have been statically allocated. */ + *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; + xReturn = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + return xReturn; + } +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + /* For internal use only - execute a 'set bits' command that was pended from * an interrupt. */ void vEventGroupSetBitsCallback( void * pvEventGroup, diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/event_groups.h b/components/freertos/FreeRTOS-Kernel/include/freertos/event_groups.h index d84dcaf92b..8a26ccf9fe 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/event_groups.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/event_groups.h @@ -807,6 +807,30 @@ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEG */ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; +/** + * @cond !DOC_EXCLUDE_HEADER_SECTION + * event_groups.h + * @code{c} + * BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, + * StaticEventGroup_t ** ppxEventGroupBuffer ); + * @endcode + * @endcond + * + * Retrieve a pointer to a statically created event groups's data structure + * buffer. It is the same buffer that is supplied at the time of creation. + * + * @param xEventGroup The event group for which to retrieve the buffer. + * + * @param ppxEventGroupBuffer Used to return a pointer to the event groups's + * data structure buffer. + * + * @return pdTRUE if the buffer was retrieved, pdFALSE otherwise. + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, + StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION; +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /** @cond !DOC_EXCLUDE_HEADER_SECTION */ /* For internal use only. */ diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/message_buffer.h b/components/freertos/FreeRTOS-Kernel/include/freertos/message_buffer.h index 36efe9dc37..701a5d4ae9 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/message_buffer.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/message_buffer.h @@ -226,6 +226,39 @@ typedef void * MessageBufferHandle_t; #define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \ ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer ) +/** + * @cond !DOC_EXCLUDE_HEADER_SECTION + * message_buffer.h + * + * @code{c} + * BaseType_t xMessageBufferGetStaticBuffers( MessageBufferHandle_t xMessageBuffer, + * uint8_t ** ppucMessageBufferStorageArea, + * StaticMessageBuffer_t ** ppxStaticMessageBuffer ); + * @endcode + * @endcond + * + * Retrieve pointers to a statically created message buffer's data structure + * buffer and storage area buffer. These are the same buffers that are supplied + * at the time of creation. + * + * @param xMessageBuffer The message buffer for which to retrieve the buffers. + * + * @param ppucMessageBufferStorageArea Used to return a pointer to the + * message buffer's storage area buffer. + * + * @param ppxStaticMessageBuffer Used to return a pointer to the message + * buffer's data structure buffer. + * + * @return pdTRUE if buffers were retrieved, pdFALSE otherwise.. + * + * \defgroup xMessageBufferGetStaticBuffers xMessageBufferGetStaticBuffers + * \ingroup MessageBufferManagement + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xMessageBufferGetStaticBuffers( xMessageBuffer, ppucMessageBufferStorageArea, ppxStaticMessageBuffer ) \ + xStreamBufferGetStaticBuffers( ( xMessageBuffer ), ( ppucMessageBufferStorageArea ), ( ppxStaticMessageBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /** * @cond !DOC_EXCLUDE_HEADER_SECTION * message_buffer.h diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/queue.h b/components/freertos/FreeRTOS-Kernel/include/freertos/queue.h index a5200d7312..c16faf1046 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/queue.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/queue.h @@ -252,6 +252,37 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ +/** + * @cond !DOC_EXCLUDE_HEADER_SECTION + * queue. h + * @code{c} + * BaseType_t xQueueGetStaticBuffers( QueueHandle_t xQueue, + * uint8_t ** ppucQueueStorage, + * StaticQueue_t ** ppxStaticQueue ); + * @endcode + * @endcond + * + * Retrieve pointers to a statically created queue's data structure buffer + * and storage area buffer. These are the same buffers that are supplied + * at the time of creation. + * + * @param xQueue The queue for which to retrieve the buffers. + * + * @param ppucQueueStorage Used to return a pointer to the queue's storage + * area buffer. + * + * @param ppxStaticQueue Used to return a pointer to the queue's data + * structure buffer. + * + * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. + * + * \defgroup xQueueGetStaticBuffers xQueueGetStaticBuffers + * \ingroup QueueManagement + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xQueueGetStaticBuffers( xQueue, ppucQueueStorage, ppxStaticQueue ) xQueueGenericGetStaticBuffers( ( xQueue ), ( ppucQueueStorage ), ( ppxStaticQueue ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /** * @cond !DOC_EXCLUDE_HEADER_SECTION * queue. h @@ -1649,6 +1680,18 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; #endif +/* + * Generic version of the function used to retrieve the buffers of statically + * created queues. This is called by other functions and macros that retrieve + * the buffers of other statically created RTOS objects that use the queue + * structure as their base. + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xQueueGenericGetStaticBuffers( QueueHandle_t xQueue, + uint8_t ** ppucQueueStorage, + StaticQueue_t ** ppxStaticQueue ) PRIVILEGED_FUNCTION; +#endif + /** * Queue sets provide a mechanism to allow a task to block (pend) on a read * operation from multiple queues or semaphores simultaneously. diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/semphr.h b/components/freertos/FreeRTOS-Kernel/include/freertos/semphr.h index 41d724a12c..47d8ae13c5 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/semphr.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/semphr.h @@ -1244,4 +1244,27 @@ typedef QueueHandle_t SemaphoreHandle_t; */ #define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) +/** + * @cond !DOC_EXCLUDE_HEADER_SECTION + * semphr.h + * @code{c} + * BaseType_t xSemaphoreGetStaticBuffer( SemaphoreHandle_t xSemaphore ); + * @endcode + * @endcond + * + * Retrieve pointer to a statically created binary semaphore, counting semaphore, + * or mutex semaphore's data structure buffer. This is the same buffer that is + * supplied at the time of creation. + * + * @param xSemaphore The semaphore for which to retrieve the buffer. + * + * @param ppxSemaphoreBuffer Used to return a pointer to the semaphore's + * data structure buffer. + * + * @return pdTRUE if buffer was retrieved, pdFALSE otherwise. + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreGetStaticBuffer( xSemaphore, ppxSemaphoreBuffer ) xQueueGenericGetStaticBuffers( ( QueueHandle_t ) ( xSemaphore ), NULL, ( ppxSemaphoreBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + #endif /* SEMAPHORE_H */ diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/stream_buffer.h b/components/freertos/FreeRTOS-Kernel/include/freertos/stream_buffer.h index 3bbecb223c..6a11fbfe79 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/stream_buffer.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/stream_buffer.h @@ -236,6 +236,40 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; #define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \ xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer ) +/** + * @cond !DOC_EXCLUDE_HEADER_SECTION + * stream_buffer.h + * + * @code{c} + * BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer, + * uint8_t ** ppucStreamBufferStorageArea, + * StaticStreamBuffer_t ** ppxStaticStreamBuffer ); + * @endcode + * @endcond + * + * Retrieve pointers to a statically created stream buffer's data structure + * buffer and storage area buffer. These are the same buffers that are supplied + * at the time of creation. + * + * @param xStreamBuffer The stream buffer for which to retrieve the buffers. + * + * @param ppucStreamBufferStorageArea Used to return a pointer to the stream + * buffer's storage area buffer. + * + * @param ppxStaticStreamBuffer Used to return a pointer to the stream + * buffer's data structure buffer. + * + * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. + * + * \defgroup xStreamBufferGetStaticBuffers xStreamBufferGetStaticBuffers + * \ingroup StreamBufferManagement + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer, + uint8_t ** ppucStreamBufferStorageArea, + StaticStreamBuffer_t ** ppxStaticStreamBuffer ) PRIVILEGED_FUNCTION; +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /** * @cond !DOC_EXCLUDE_HEADER_SECTION * stream_buffer.h diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h index 43c5fa310e..2c016eb596 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h @@ -1852,6 +1852,38 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lin */ TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +/** + * @cond !DOC_EXCLUDE_HEADER_SECTION + * task. h + * @code{c} + * BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, + * StackType_t ** ppuxStackBuffer, + * StaticTask_t ** ppxTaskBuffer ); + * @endcode + * @endcond + * + * Retrieve pointers to a statically created task's data structure + * buffer and stack buffer. These are the same buffers that are supplied + * at the time of creation. + * + * @param xTask The task for which to retrieve the buffers. + * + * @param ppuxStackBuffer Used to return a pointer to the task's stack buffer. + * + * @param ppxTaskBuffer Used to return a pointer to the task's data structure + * buffer. + * + * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. + * + * \defgroup xTaskGetStaticBuffers xTaskGetStaticBuffers + * \ingroup TaskUtils + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, + StackType_t ** ppuxStackBuffer, + StaticTask_t ** ppxTaskBuffer ) PRIVILEGED_FUNCTION; +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /** * @cond !DOC_EXCLUDE_HEADER_SECTION * task.h diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/timers.h b/components/freertos/FreeRTOS-Kernel/include/freertos/timers.h index fed9b380b1..00c9f5179b 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/timers.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/timers.h @@ -1314,6 +1314,26 @@ TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; */ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; +/** + * BaseType_t xTimerGetStaticBuffer( TimerHandle_t xTimer, + * StaticTimer_t ** ppxTimerBuffer ); + * + * Retrieve pointer to a statically created timer's data structure + * buffer. This is the same buffer that is supplied at the time of + * creation. + * + * @param xTimer The timer for which to retrieve the buffer. + * + * @param ppxTimerBuffer Used to return a pointer to the timers's data + * structure buffer. + * + * @return pdTRUE if the buffer was retrieved, pdFALSE otherwise. + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xTimerGetStaticBuffer( TimerHandle_t xTimer, + StaticTimer_t ** ppxTimerBuffer ) PRIVILEGED_FUNCTION; +#endif /* configSUPPORT_STATIC_ALLOCATION */ + /** @cond !DOC_EXCLUDE_HEADER_SECTION */ /* diff --git a/components/freertos/FreeRTOS-Kernel/queue.c b/components/freertos/FreeRTOS-Kernel/queue.c index 2c3c76f20f..69da28f732 100644 --- a/components/freertos/FreeRTOS-Kernel/queue.c +++ b/components/freertos/FreeRTOS-Kernel/queue.c @@ -417,6 +417,55 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + + BaseType_t xQueueGenericGetStaticBuffers( QueueHandle_t xQueue, + uint8_t ** ppucQueueStorage, + StaticQueue_t ** ppxStaticQueue ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + configASSERT( ppxStaticQueue ); + + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Check if the queue was statically allocated. */ + if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdTRUE ) + { + if( ppucQueueStorage != NULL ) + { + *ppucQueueStorage = ( uint8_t * ) pxQueue->pcHead; + } + + *ppxStaticQueue = ( StaticQueue_t * ) pxQueue; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + #else /* configSUPPORT_DYNAMIC_ALLOCATION */ + { + /* Queue must have been statically allocated. */ + if( ppucQueueStorage != NULL ) + { + *ppucQueueStorage = ( uint8_t * ) pxQueue->pcHead; + } + + *ppxStaticQueue = ( StaticQueue_t * ) pxQueue; + xReturn = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + return xReturn; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, diff --git a/components/freertos/FreeRTOS-Kernel/stream_buffer.c b/components/freertos/FreeRTOS-Kernel/stream_buffer.c index fa9a3ce251..d67f091cba 100644 --- a/components/freertos/FreeRTOS-Kernel/stream_buffer.c +++ b/components/freertos/FreeRTOS-Kernel/stream_buffer.c @@ -387,6 +387,34 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, #endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*-----------------------------------------------------------*/ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer, + uint8_t ** ppucStreamBufferStorageArea, + StaticStreamBuffer_t ** ppxStaticStreamBuffer ) + { + BaseType_t xReturn; + const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + + configASSERT( pxStreamBuffer ); + configASSERT( ppucStreamBufferStorageArea ); + configASSERT( ppxStaticStreamBuffer ); + + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) != ( uint8_t ) 0 ) + { + *ppucStreamBufferStorageArea = pxStreamBuffer->pucBuffer; + *ppxStaticStreamBuffer = ( StaticStreamBuffer_t * ) pxStreamBuffer; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; + } +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) { StreamBuffer_t * pxStreamBuffer = xStreamBuffer; diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 32d054dda1..5478fef96b 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -2899,6 +2899,53 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char #endif /* INCLUDE_xTaskGetHandle */ /*-----------------------------------------------------------*/ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + + BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, + StackType_t ** ppuxStackBuffer, + StaticTask_t ** ppxTaskBuffer ) + { + BaseType_t xReturn; + TCB_t * pxTCB; + + configASSERT( ppuxStackBuffer != NULL ); + configASSERT( ppxTaskBuffer != NULL ); + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 ) + { + if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ) + { + *ppuxStackBuffer = pxTCB->pxStack; + *ppxTaskBuffer = ( StaticTask_t * ) pxTCB; + xReturn = pdTRUE; + } + else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) + { + *ppuxStackBuffer = pxTCB->pxStack; + *ppxTaskBuffer = NULL; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + #else /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */ + { + *ppuxStackBuffer = pxTCB->pxStack; + *ppxTaskBuffer = ( StaticTask_t * ) pxTCB; + xReturn = pdTRUE; + } + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */ + + return xReturn; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, diff --git a/components/freertos/FreeRTOS-Kernel/timers.c b/components/freertos/FreeRTOS-Kernel/timers.c index 448e183bb2..d68ab1e371 100644 --- a/components/freertos/FreeRTOS-Kernel/timers.c +++ b/components/freertos/FreeRTOS-Kernel/timers.c @@ -512,6 +512,30 @@ } /*-----------------------------------------------------------*/ + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + BaseType_t xTimerGetStaticBuffer( TimerHandle_t xTimer, + StaticTimer_t ** ppxTimerBuffer ) + { + BaseType_t xReturn; + Timer_t * pxTimer = xTimer; + + configASSERT( ppxTimerBuffer != NULL ); + + if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) != 0 ) + { + *ppxTimerBuffer = ( StaticTimer_t * ) pxTimer; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { Timer_t * pxTimer = xTimer; diff --git a/components/freertos/esp_additions/include/freertos/idf_additions.h b/components/freertos/esp_additions/include/freertos/idf_additions.h index 22aac424b7..3b5a7b347e 100644 --- a/components/freertos/esp_additions/include/freertos/idf_additions.h +++ b/components/freertos/esp_additions/include/freertos/idf_additions.h @@ -36,7 +36,7 @@ * @brief Create a new task that is pinned to a particular core * * Helper function to create a task that is pinned to a particular core, or has - * no affinity. In other wrods, the created task will have an affinity mask of: + * no affinity. In other words, the created task will have an affinity mask of: * - (1 << xCoreID) if it is pinned to a particular core * - Set to tskNO_AFFINITY if it has no affinity * @@ -119,7 +119,7 @@ TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID ); /** - * @brief Get the current core affintiy of a particular task + * @brief Get the current core affinity of a particular task * * Helper function to get the core affinity of a particular task. If the task is * pinned to a particular core, the core ID is returned. If the task is not From c5fe3ec05d17c6e9e6b8c7ec0fd2b356b045e91e Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Thu, 6 Apr 2023 22:36:58 +0800 Subject: [PATCH 3/4] freertos: Add wrapper functions to create objects with capabilities This commit adds various ...WithCaps() functions to create FreeRTOS objects with specific memory capabilities. --- components/freertos/CMakeLists.txt | 1 + .../freertos/esp_additions/idf_additions.c | 275 ++++++++++++++++++ .../include/freertos/idf_additions.h | 255 +++++++++++++++- components/freertos/linker_common.lf | 6 + docs/doxygen/Doxyfile | 1 + .../system/freertos_additions.rst | 11 + 6 files changed, 545 insertions(+), 4 deletions(-) create mode 100644 components/freertos/esp_additions/idf_additions.c diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 903c69f851..aea0dfbcca 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -22,6 +22,7 @@ endif() set(srcs "heap_idf.c" + "esp_additions/idf_additions.c" "${kernel_dir}/list.c" "${kernel_dir}/queue.c" "${kernel_dir}/tasks.c" diff --git a/components/freertos/esp_additions/idf_additions.c b/components/freertos/esp_additions/idf_additions.c new file mode 100644 index 0000000000..ee47b98a76 --- /dev/null +++ b/components/freertos/esp_additions/idf_additions.c @@ -0,0 +1,275 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/stream_buffer.h" +#include "freertos/message_buffer.h" +#include "freertos/event_groups.h" +#include "freertos/timers.h" +#include "freertos/idf_additions.h" +#include "esp_heap_caps.h" + +/* + * This file contains the implementation for some the functions in + * idf_additions.h + */ + +/* ----------------------------------------------------------------------------- + * Creation With Memory Caps + * -------------------------------------------------------------------------- */ + +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + +/* ---------------------------------- Queue --------------------------------- */ + + QueueHandle_t xQueueCreateWithCaps( UBaseType_t uxQueueLength, + UBaseType_t uxItemSize, + UBaseType_t uxMemoryCaps ) + { + QueueHandle_t xQueue; + StaticQueue_t * pxQueueBuffer; + uint8_t * pucQueueStorageBuffer; + + /* Allocate memory for the queue using the provided memory caps */ + pxQueueBuffer = heap_caps_malloc( sizeof( StaticQueue_t ), ( uint32_t ) uxMemoryCaps ); + + if( uxItemSize == 0 ) + { + pucQueueStorageBuffer = NULL; + } + else + { + pucQueueStorageBuffer = heap_caps_malloc( uxQueueLength * uxItemSize, ( uint32_t ) uxMemoryCaps ); + } + + if( ( pxQueueBuffer == NULL ) || ( ( uxItemSize > 0 ) && ( pucQueueStorageBuffer == NULL ) ) ) + { + goto err; + } + + /* Create the queue using static creation API */ + xQueue = xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorageBuffer, pxQueueBuffer ); + + if( xQueue == NULL ) + { + goto err; + } + + return xQueue; + +err: + heap_caps_free( pucQueueStorageBuffer ); + heap_caps_free( pxQueueBuffer ); + return NULL; + } + + void vQueueDeleteWithCaps( QueueHandle_t xQueue ) + { + BaseType_t xResult; + StaticQueue_t * pxQueueBuffer; + uint8_t * pucQueueStorageBuffer; + + /* Retrieve the buffers used to create the queue before deleting it */ + xResult = xQueueGetStaticBuffers( xQueue, &pucQueueStorageBuffer, &pxQueueBuffer ); + configASSERT( xResult == pdTRUE ); + + /* Delete the queue */ + vQueueDelete( xQueue ); + + /* Free the memory buffers */ + heap_caps_free( pxQueueBuffer ); + heap_caps_free( pucQueueStorageBuffer ); + } + +/* -------------------------------- Semaphore ------------------------------- */ + + SemaphoreHandle_t xSemaphoreCreateGenericWithCaps( UBaseType_t uxMaxCount, + UBaseType_t uxInitialCount, + const uint8_t ucQueueType, + UBaseType_t uxMemoryCaps ) + { + SemaphoreHandle_t xSemaphore; + StaticSemaphore_t * pxSemaphoreBuffer; + + /* Allocate memory for the semaphore using the provided memory caps */ + pxSemaphoreBuffer = heap_caps_malloc( sizeof( StaticSemaphore_t ), ( uint32_t ) uxMemoryCaps ); + + if( pxSemaphoreBuffer == NULL ) + { + return NULL; + } + + /* Create the semaphore using static creation API */ + if( ucQueueType == queueQUEUE_TYPE_MUTEX ) + { + xSemaphore = xSemaphoreCreateMutexStatic( pxSemaphoreBuffer ); + } + else if( ucQueueType == queueQUEUE_TYPE_COUNTING_SEMAPHORE ) + { + xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ); + } + else if( ucQueueType == queueQUEUE_TYPE_BINARY_SEMAPHORE ) + { + xSemaphore = xSemaphoreCreateBinaryStatic( pxSemaphoreBuffer ); + } + else /* ucQueueType == queueQUEUE_TYPE_RECURSIVE_MUTEX */ + { + xSemaphore = xSemaphoreCreateRecursiveMutexStatic( pxSemaphoreBuffer ); + } + + if( xSemaphore == NULL ) + { + heap_caps_free( pxSemaphoreBuffer ); + } + + return xSemaphore; + } + + void vSemaphoreDeleteWithCaps( SemaphoreHandle_t xSemaphore ) + { + BaseType_t xResult; + StaticSemaphore_t * pxSemaphoreBuffer; + + /* Retrieve the buffer used to create the semaphore before deleting it + * */ + xResult = xSemaphoreGetStaticBuffer( xSemaphore, &pxSemaphoreBuffer ); + configASSERT( xResult == pdTRUE ); + + /* Delete the semaphore */ + vSemaphoreDelete( xSemaphore ); + + /* Free the memory buffer */ + heap_caps_free( pxSemaphoreBuffer ); + } + +/* ------------------------- Stream & Message Buffers ----------------------- */ + + StreamBufferHandle_t xStreamBufferGenericCreateWithCaps( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer, + UBaseType_t uxMemoryCaps ) + { + StreamBufferHandle_t xStreamBuffer; + StaticStreamBuffer_t * pxStaticStreamBuffer; + uint8_t * pucStreamBufferStorageArea; + + /* Allocate memory for the stream or message buffer using the provided + * memory caps */ + pxStaticStreamBuffer = heap_caps_malloc( sizeof( StaticStreamBuffer_t ), ( uint32_t ) uxMemoryCaps ); + pucStreamBufferStorageArea = heap_caps_malloc( xBufferSizeBytes, ( uint32_t ) uxMemoryCaps ); + + if( ( pxStaticStreamBuffer == NULL ) || ( pucStreamBufferStorageArea == NULL ) ) + { + goto err; + } + + /* Create the stream or message buffer using static creation API */ + if( xIsMessageBuffer == pdTRUE ) + { + xStreamBuffer = ( StreamBufferHandle_t ) xMessageBufferCreateStatic( xBufferSizeBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ); + } + else + { + xStreamBuffer = xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ); + } + + if( xStreamBuffer == NULL ) + { + goto err; + } + + return xStreamBuffer; + +err: + heap_caps_free( pucStreamBufferStorageArea ); + heap_caps_free( pxStaticStreamBuffer ); + return NULL; + } + + void vStreamBufferGenericDeleteWithCaps( StreamBufferHandle_t xStreamBuffer, + BaseType_t xIsMessageBuffer ) + { + BaseType_t xResult; + StaticStreamBuffer_t * pxStaticStreamBuffer; + uint8_t * pucStreamBufferStorageArea; + + /* Retrieve the buffers used to create the stream or message buffer + * before deleting it */ + if( xIsMessageBuffer == pdTRUE ) + { + xResult = xMessageBufferGetStaticBuffers( xStreamBuffer, &pucStreamBufferStorageArea, &pxStaticStreamBuffer ); + } + else + { + xResult = xStreamBufferGetStaticBuffers( xStreamBuffer, &pucStreamBufferStorageArea, &pxStaticStreamBuffer ); + } + + configASSERT( xResult == pdTRUE ); + + /* Delete the stream or message buffer */ + if( xIsMessageBuffer == pdTRUE ) + { + vMessageBufferDelete( xStreamBuffer ); + } + else + { + vSemaphoreDelete( xStreamBuffer ); + } + + /* Free the memory buffers */ + heap_caps_free( pxStaticStreamBuffer ); + heap_caps_free( pucStreamBufferStorageArea ); + } + +/* ------------------------------ Event Groups ------------------------------ */ + + EventGroupHandle_t xEventGroupCreateWithCaps( UBaseType_t uxMemoryCaps ) + { + EventGroupHandle_t xEventGroup; + StaticEventGroup_t * pxEventGroupBuffer; + + /* Allocate memory for the event group using the provided memory caps */ + pxEventGroupBuffer = heap_caps_malloc( sizeof( StaticEventGroup_t ), uxMemoryCaps ); + + if( pxEventGroupBuffer == NULL ) + { + return NULL; + } + + /* Create the event group using static creation API */ + xEventGroup = xEventGroupCreateStatic( pxEventGroupBuffer ); + + if( xEventGroup == NULL ) + { + heap_caps_free( pxEventGroupBuffer ); + } + + return xEventGroup; + } + + void vEventGroupDeleteWithCaps( EventGroupHandle_t xEventGroup ) + { + BaseType_t xResult; + StaticEventGroup_t * pxEventGroupBuffer; + + /* Retrieve the buffer used to create the event group before deleting it + * */ + xResult = xEventGroupGetStaticBuffer( xEventGroup, &pxEventGroupBuffer ); + configASSERT( xResult == pdTRUE ); + + /* Delete the event group */ + vEventGroupDelete( xEventGroup ); + + /* Free the memory buffer */ + heap_caps_free( pxEventGroupBuffer ); + } + +#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ diff --git a/components/freertos/esp_additions/include/freertos/idf_additions.h b/components/freertos/esp_additions/include/freertos/idf_additions.h index 3b5a7b347e..a917b97595 100644 --- a/components/freertos/esp_additions/include/freertos/idf_additions.h +++ b/components/freertos/esp_additions/include/freertos/idf_additions.h @@ -18,6 +18,12 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/stream_buffer.h" +#include "freertos/message_buffer.h" +#include "freertos/event_groups.h" +#include "esp_heap_caps.h" #ifdef __cplusplus extern "C" { @@ -28,9 +34,11 @@ * * Todo: Move IDF FreeRTOS SMP related additions to this header as well (see * IDF-7201) + * Todo: Add these SMP related additions to docs once they are combined with + * IDF FreeRTOS. * -------------------------------------------------------------------------- */ -#if CONFIG_FREERTOS_SMP || __DOXYGEN__ +#if CONFIG_FREERTOS_SMP /** * @brief Create a new task that is pinned to a particular core @@ -133,16 +141,18 @@ */ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ); -#endif // CONFIG_FREERTOS_SMP || __DOXYGEN__ +#endif // CONFIG_FREERTOS_SMP /* ----------------------------------------------------------------------------- * TLSP Deletion Callback related API additions * * Todo: Move IDF FreeRTOS TLSP Deletion Callback related additions to this * header as well (see IDF-7201) + * Todo: Add these SMP related additions to docs once they are combined with + * IDF FreeRTOS. * -------------------------------------------------------------------------- */ -#if CONFIG_FREERTOS_SMP || __DOXYGEN__ +#if CONFIG_FREERTOS_SMP #if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS ) @@ -180,7 +190,244 @@ TlsDeleteCallbackFunction_t pvDelCallback ); #endif // CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS -#endif // CONFIG_FREERTOS_SMP || __DOXYGEN__ +#endif // CONFIG_FREERTOS_SMP + +/* ----------------------------------------------------------------------------- + * Creation With Memory Caps + * + * Helper functions to create various FreeRTOS objects (e.g., queues, + * semaphores) with specific memory capabilities (e.g., MALLOC_CAP_INTERNAL). + * -------------------------------------------------------------------------- */ + +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + +/* ---------------------- Queue ------------------------- */ + +/** + * @brief Creates a queue with specific memory capabilities + * + * This function is similar to xQueueCreate(), except that it allows the memory + * allocated for the queue to have specific capabilities (e.g., + * MALLOC_CAP_INTERNAL). + * + * @note A queue created using this function must only be deleted using + * vQueueDeleteWithCaps() + * @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. + * @param uxMemoryCaps Memory capabilities of the queue's memory (see + * esp_heap_caps.h) + * @return Handle to the created queue or NULL on failure. + */ + QueueHandle_t xQueueCreateWithCaps( UBaseType_t uxQueueLength, + UBaseType_t uxItemSize, + UBaseType_t uxMemoryCaps ); + +/** + * @brief Deletes a queue previously created using xQueueCreateWithCaps() + * + * @param xQueue A handle to the queue to be deleted. + */ + void vQueueDeleteWithCaps( QueueHandle_t xQueue ); + +/* -------------------- Semaphore ----------------------- */ + +/** @cond */ /* Doxygen command to hide this from docs */ + SemaphoreHandle_t xSemaphoreCreateGenericWithCaps( UBaseType_t uxMaxCount, + UBaseType_t uxInitialCount, + const uint8_t ucQueueType, + UBaseType_t uxMemoryCaps ); +/** @endcond */ + +/** + * @brief Creates a binary semaphore with specific memory capabilities + * + * This function is similar to vSemaphoreCreateBinary(), except that it allows + * the memory allocated for the binary semaphore to have specific capabilities + * (e.g., MALLOC_CAP_INTERNAL). + * + * @note A binary semaphore created using this function must only be deleted + * using vSemaphoreDeleteWithCaps() + * @param uxMemoryCaps Memory capabilities of the binary semaphore's memory (see + * esp_heap_caps.h) + * @return Handle to the created binary semaphore or NULL on failure. + */ + static inline SemaphoreHandle_t xSemaphoreCreateBinaryWithCaps( UBaseType_t uxMemoryCaps ) + { + return xSemaphoreCreateGenericWithCaps( 0, 0, queueQUEUE_TYPE_BINARY_SEMAPHORE, uxMemoryCaps ); + } + +/** + * @brief Creates a counting semaphore with specific memory capabilities + * + * This function is similar to xSemaphoreCreateCounting(), except that it allows + * the memory allocated for the counting semaphore to have specific capabilities + * (e.g., MALLOC_CAP_INTERNAL). + * + * @note A counting semaphore created using this function must only be deleted + * using vSemaphoreDeleteWithCaps() + * @param uxMaxCount The maximum count value that can be reached. + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * @param uxMemoryCaps Memory capabilities of the counting semaphore's memory + * (see esp_heap_caps.h) + * @return Handle to the created counting semaphore or NULL on failure. + */ + static inline SemaphoreHandle_t xSemaphoreCreateCountingWithCaps( UBaseType_t uxMaxCount, + UBaseType_t uxInitialCount, + UBaseType_t uxMemoryCaps ) + { + return xSemaphoreCreateGenericWithCaps( uxMaxCount, uxInitialCount, queueQUEUE_TYPE_COUNTING_SEMAPHORE, uxMemoryCaps ); + } + +/** + * @brief Creates a mutex semaphore with specific memory capabilities + * + * This function is similar to xSemaphoreCreateMutex(), except that it allows + * the memory allocated for the mutex semaphore to have specific capabilities + * (e.g., MALLOC_CAP_INTERNAL). + * + * @note A mutex semaphore created using this function must only be deleted + * using vSemaphoreDeleteWithCaps() + * @param uxMemoryCaps Memory capabilities of the mutex semaphore's memory (see + * esp_heap_caps.h) + * @return Handle to the created mutex semaphore or NULL on failure. + */ + static inline SemaphoreHandle_t xSemaphoreCreateMutexWithCaps( UBaseType_t uxMemoryCaps ) + { + return xSemaphoreCreateGenericWithCaps( 0, 0, queueQUEUE_TYPE_MUTEX, uxMemoryCaps ); + } + +/** + * @brief Creates a recursive mutex with specific memory capabilities + * + * This function is similar to xSemaphoreCreateRecursiveMutex(), except that it + * allows the memory allocated for the recursive mutex to have specific + * capabilities (e.g., MALLOC_CAP_INTERNAL). + * + * @note A recursive mutex created using this function must only be deleted + * using vSemaphoreDeleteWithCaps() + * @param uxMemoryCaps Memory capabilities of the recursive mutex's memory (see + * esp_heap_caps.h) + * @return Handle to the created recursive mutex or NULL on failure. + */ + static inline SemaphoreHandle_t xSemaphoreCreateRecursiveMutexWithCaps( UBaseType_t uxMemoryCaps ) + { + return xSemaphoreCreateGenericWithCaps( 0, 0, queueQUEUE_TYPE_RECURSIVE_MUTEX, uxMemoryCaps ); + } + +/** + * @brief Deletes a semaphore previously created using one of the + * xSemaphoreCreate...WithCaps() functions + * + * @param xSemaphore A handle to the semaphore to be deleted. + */ + void vSemaphoreDeleteWithCaps( SemaphoreHandle_t xSemaphore ); + +/* ------------ Stream & Message Buffers ---------------- */ + +/** @cond */ /* Doxygen command to hide this from docs */ + StreamBufferHandle_t xStreamBufferGenericCreateWithCaps( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer, + UBaseType_t uxMemoryCaps ); + + void vStreamBufferGenericDeleteWithCaps( StreamBufferHandle_t xStreamBuffer, + BaseType_t xIsMessageBuffer ); +/** @endcond */ + +/** + * @brief Creates a stream buffer with specific memory capabilities + * + * This function is similar to xStreamBufferCreate(), except that it allows the + * memory allocated for the stream buffer to have specific capabilities (e.g., + * MALLOC_CAP_INTERNAL). + * + * @note A stream buffer created using this function must only be deleted using + * vStreamBufferDeleteWithCaps() + * @param xBufferSizeBytes The total number of bytes the stream buffer will be + * able to hold at any one time. + * @param xTriggerLevelBytes The number of bytes that must be in the stream + * buffer before unblocking + * @param uxMemoryCaps Memory capabilities of the stream buffer's memory (see + * esp_heap_caps.h) + * @return Handle to the created stream buffer or NULL on failure. + */ + static inline StreamBufferHandle_t xStreamBufferCreateWithCaps( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + UBaseType_t uxMemoryCaps ) + { + return xStreamBufferGenericCreateWithCaps( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, uxMemoryCaps ); + } + +/** + * @brief Deletes a stream buffer previously created using + * xStreamBufferCreateWithCaps() + * + * @param xStreamBuffer A handle to the stream buffer to be deleted. + */ + static inline void vStreamBufferDeleteWithCaps( StreamBufferHandle_t xStreamBuffer ) + { + vStreamBufferGenericDeleteWithCaps( xStreamBuffer, pdFALSE ); + } + +/** + * @brief Creates a message buffer with specific memory capabilities + * + * This function is similar to xMessageBufferCreate(), except that it allows the + * memory allocated for the message buffer to have specific capabilities (e.g., + * MALLOC_CAP_INTERNAL). + * + * @note A message buffer created using this function must only be deleted using + * vMessageBufferDeleteWithCaps() + * @param xBufferSizeBytes The total number of bytes (not messages) the message + * buffer will be able to hold at any one time. + * @param uxMemoryCaps Memory capabilities of the message buffer's memory (see + * esp_heap_caps.h) + * @return Handle to the created message buffer or NULL on failure. + */ + static inline MessageBufferHandle_t xMessageBufferCreateWithCaps( size_t xBufferSizeBytes, + UBaseType_t uxMemoryCaps ) + { + return ( MessageBufferHandle_t ) xStreamBufferGenericCreateWithCaps( xBufferSizeBytes, ( size_t ) 0, pdTRUE, uxMemoryCaps ); + } + +/** + * @brief Deletes a stream buffer previously created using + * xMessageBufferCreateWithCaps() + * + * @param xMessageBuffer A handle to the message buffer to be deleted. + */ + static inline void vMessageBufferDeleteWithCaps( MessageBufferHandle_t xMessageBuffer ) + { + vStreamBufferGenericDeleteWithCaps( ( StreamBufferHandle_t ) xMessageBuffer, pdTRUE ); + } + +/* ------------------ Event Groups ---------------------- */ + +/** + * @brief Creates an event group with specific memory capabilities + * + * This function is similar to xEventGroupCreate(), except that it allows the + * memory allocated for the event group to have specific capabilities (e.g., + * MALLOC_CAP_INTERNAL). + * + * @note An event group created using this function must only be deleted using + * vEventGroupDeleteWithCaps() + * @param uxMemoryCaps Memory capabilities of the event group's memory (see + * esp_heap_caps.h) + * @return Handle to the created event group or NULL on failure. + */ + EventGroupHandle_t xEventGroupCreateWithCaps( UBaseType_t uxMemoryCaps ); + +/** + * @brief Deletes an event group previously created using + * xEventGroupCreateWithCaps() + * + * @param xEventGroup A handle to the event group to be deleted. + */ + void vEventGroupDeleteWithCaps( EventGroupHandle_t xEventGroup ); + +#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ #ifdef __cplusplus } diff --git a/components/freertos/linker_common.lf b/components/freertos/linker_common.lf index 7cbb6e17af..425b10d362 100644 --- a/components/freertos/linker_common.lf +++ b/components/freertos/linker_common.lf @@ -34,6 +34,12 @@ entries: tasks:prvTaskPriorityRaise (default) tasks:prvTaskPriorityRestore (default) + # ------------------------------------------------------------------------------------------------------------------ + # idf_additions.c + # Placement Rules: Functions always in flash as they are never called from an ISR + # ------------------------------------------------------------------------------------------------------------------ + idf_additions (default) + # ------------------------------------------------------------------------------------------------------------------ # app_startup.c # Placement Rules: Functions always in flash as they are never called from an ISR diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 284ede346c..97d8a5f309 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -191,6 +191,7 @@ INPUT = \ $(PROJECT_PATH)/components/fatfs/diskio/diskio_sdmmc.h \ $(PROJECT_PATH)/components/fatfs/diskio/diskio_wl.h \ $(PROJECT_PATH)/components/fatfs/vfs/esp_vfs_fat.h \ + $(PROJECT_PATH)/components/freertos/esp_additions/include/freertos/idf_additions.h \ $(PROJECT_PATH)/components/freertos/FreeRTOS-Kernel/include/freertos/event_groups.h \ $(PROJECT_PATH)/components/freertos/FreeRTOS-Kernel/include/freertos/message_buffer.h \ $(PROJECT_PATH)/components/freertos/FreeRTOS-Kernel/include/freertos/queue.h \ diff --git a/docs/en/api-reference/system/freertos_additions.rst b/docs/en/api-reference/system/freertos_additions.rst index c3d54aea1b..4e40499589 100644 --- a/docs/en/api-reference/system/freertos_additions.rst +++ b/docs/en/api-reference/system/freertos_additions.rst @@ -430,6 +430,12 @@ When implementing TLSP callbacks, users should note the following: - The callback **must never attempt to block or yield** and critical sections should be kept as short as possible - The callback is called shortly before a deleted task's memory is freed. Thus, the callback can either be called from :cpp:func:`vTaskDelete` itself, or from the idle task. +.. ----------------------------------------------- IDF Additional API -------------------------------------------------- + +IDF Additional API +------------------ + +The :component_file:`freertos/esp_additions/include/freertos/idf_additions.h` header contains FreeRTOS related helper functions added by ESP-IDF. Users can include this header via ``#include "freertos/idf_additions.h"``. .. ------------------------------------------ Component Specific Properties -------------------------------------------- @@ -455,3 +461,8 @@ Hooks API ^^^^^^^^^ .. include-build-file:: inc/esp_freertos_hooks.inc + +Additional API +^^^^^^^^^^^^^^ + +.. include-build-file:: inc/idf_additions.inc From 46fe70fb46e7d27f7046ca0b20492daab435f45b Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Fri, 7 Apr 2023 16:13:10 +0800 Subject: [PATCH 4/4] freertos: Add unit tests for ...WithCaps() functions --- .../freertos/misc/test_idf_additions.c | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 components/freertos/test_apps/freertos/misc/test_idf_additions.c diff --git a/components/freertos/test_apps/freertos/misc/test_idf_additions.c b/components/freertos/test_apps/freertos/misc/test_idf_additions.c new file mode 100644 index 0000000000..38cf692cef --- /dev/null +++ b/components/freertos/test_apps/freertos/misc/test_idf_additions.c @@ -0,0 +1,139 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/stream_buffer.h" +#include "freertos/message_buffer.h" +#include "freertos/event_groups.h" +#include "freertos/idf_additions.h" +#include "esp_memory_utils.h" +#include "unity.h" + +/* +Test ...Create...WithCaps() functions + +Purpose: + - Test that the ___Create___WithCaps() functions create objects using with correct memory capabilities + +Procedure: + - Create different FreeRTOS objects (e.g. queues, event groups etc) using the various ___Create___WithCaps() + functions with (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) capabilities. + - Call the ___GetStaticBuffers() functions to get the address of the memory of the created objects + - Check that the memory has (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) capabilities by calling esp_ptr_in_dram() + +Expected: + - ___Create___WithCaps() should create objects in DRAM +*/ + +#define OBJECT_MEMORY_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) + +TEST_CASE("IDF additions: Queue creation with memory caps", "[freertos]") +{ + QueueHandle_t queue_handle; + uint8_t *queue_storage; + StaticQueue_t *queue_obj; + + // Create queue with caps + queue_handle = xQueueCreateWithCaps(5, sizeof(uint32_t), OBJECT_MEMORY_CAPS); + TEST_ASSERT_NOT_EQUAL(NULL, queue_handle); + // Get the queue's memory + TEST_ASSERT_EQUAL(pdTRUE, xQueueGetStaticBuffers(queue_handle, &queue_storage, &queue_obj)); + TEST_ASSERT(esp_ptr_in_dram(queue_storage)); + TEST_ASSERT(esp_ptr_in_dram(queue_obj)); + // Free the queue + vQueueDeleteWithCaps(queue_handle); +} + +TEST_CASE("IDF additions: Semaphore creation with memory caps", "[freertos]") +{ + SemaphoreHandle_t sem_handle; + StaticSemaphore_t *sem_obj; + + // Create binary semaphore with caps + sem_handle = xSemaphoreCreateBinaryWithCaps(OBJECT_MEMORY_CAPS); + TEST_ASSERT_NOT_EQUAL(NULL, sem_handle); + // Get the binary semaphore's memory + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreGetStaticBuffer(sem_handle, &sem_obj)); + TEST_ASSERT(esp_ptr_in_dram(sem_obj)); + // Free the binary semaphore + vSemaphoreDeleteWithCaps(sem_handle); + + // Create counting semaphore with caps + sem_handle = xSemaphoreCreateCountingWithCaps(4, 0, OBJECT_MEMORY_CAPS); + TEST_ASSERT_NOT_EQUAL(NULL, sem_handle); + // Get the counting semaphore's memory + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreGetStaticBuffer(sem_handle, &sem_obj)); + TEST_ASSERT(esp_ptr_in_dram(sem_obj)); + // Free the counting semaphore + vSemaphoreDeleteWithCaps(sem_handle); + + // Create mutex semaphore with caps + sem_handle = xSemaphoreCreateMutexWithCaps(OBJECT_MEMORY_CAPS); + TEST_ASSERT_NOT_EQUAL(NULL, sem_handle); + // Get the mutex semaphore's memory + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreGetStaticBuffer(sem_handle, &sem_obj)); + TEST_ASSERT(esp_ptr_in_dram(sem_obj)); + // Free the mutex semaphore + vSemaphoreDeleteWithCaps(sem_handle); + + // Create recursive mutex with caps + sem_handle = xSemaphoreCreateRecursiveMutexWithCaps(OBJECT_MEMORY_CAPS); + TEST_ASSERT_NOT_EQUAL(NULL, sem_handle); + // Get the recursive mutex's memory + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreGetStaticBuffer(sem_handle, &sem_obj)); + TEST_ASSERT(esp_ptr_in_dram(sem_obj)); + // Free the recursive mutex + vSemaphoreDeleteWithCaps(sem_handle); +} + +TEST_CASE("IDF additions: Stream & message buffer creation with memory caps", "[freertos]") +{ + StreamBufferHandle_t stream_buffer_handle; + uint8_t *stream_buffer_storage; + StaticStreamBuffer_t *stream_buffer_obj; + + // Create stream buffer with caps + stream_buffer_handle = xStreamBufferCreateWithCaps(16, 0, OBJECT_MEMORY_CAPS); + TEST_ASSERT_NOT_EQUAL(NULL, stream_buffer_handle); + // Get the stream buffer's memory + TEST_ASSERT_EQUAL(pdTRUE, xStreamBufferGetStaticBuffers(stream_buffer_handle, &stream_buffer_storage, &stream_buffer_obj)); + TEST_ASSERT(esp_ptr_in_dram(stream_buffer_storage)); + TEST_ASSERT(esp_ptr_in_dram(stream_buffer_obj)); + // Free the stream buffer + vStreamBufferDelete(stream_buffer_handle); + + MessageBufferHandle_t msg_buffer_handle; + uint8_t *msg_buffer_storage; + StaticMessageBuffer_t *msg_buffer_obj; + + // Create message buffer with caps + msg_buffer_handle = xMessageBufferCreateWithCaps(16, OBJECT_MEMORY_CAPS); + TEST_ASSERT_NOT_EQUAL(NULL, msg_buffer_handle); + // Get the message buffer's memory + TEST_ASSERT_EQUAL(pdTRUE, xMessageBufferGetStaticBuffers(msg_buffer_handle, &msg_buffer_storage, &msg_buffer_obj)); + TEST_ASSERT(esp_ptr_in_dram(msg_buffer_storage)); + TEST_ASSERT(esp_ptr_in_dram(msg_buffer_obj)); + // Free the message buffer + vMessageBufferDelete(msg_buffer_handle); +} + +TEST_CASE("IDF additions: Event group creation with memory caps", "[freertos]") +{ + EventGroupHandle_t evt_group_handle; + StaticEventGroup_t *evt_group_obj; + + // Create event group with caps + evt_group_handle = xEventGroupCreateWithCaps(OBJECT_MEMORY_CAPS); + TEST_ASSERT_NOT_EQUAL(NULL, evt_group_handle); + // Get the event group's memory + TEST_ASSERT_EQUAL(pdTRUE, xEventGroupGetStaticBuffer(evt_group_handle, &evt_group_obj)); + TEST_ASSERT(esp_ptr_in_dram(evt_group_obj)); + // Free the event group + vEventGroupDelete(evt_group_handle); +}