freertos: Add wrapper functions to create objects with capabilities

This commit adds various ...WithCaps() functions to create FreeRTOS objects
with specific memory capabilities.
pull/11519/head
Darian Leung 2023-04-06 22:36:58 +08:00
rodzic 3562cb8051
commit c5fe3ec05d
6 zmienionych plików z 545 dodań i 4 usunięć

Wyświetl plik

@ -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"

Wyświetl plik

@ -0,0 +1,275 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include <stdint.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 "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 ) */

Wyświetl plik

@ -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
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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 \

Wyświetl plik

@ -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