esp-idf/components/freertos/esp_additions/idf_additions.c

343 wiersze
11 KiB
C

/*
* 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 )
/* ---------------------------------- Tasks --------------------------------- */
BaseType_t xTaskCreatePinnedToCoreWithCaps( TaskFunction_t pvTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pvCreatedTask,
const BaseType_t xCoreID,
UBaseType_t uxMemoryCaps )
{
TaskHandle_t xHandle;
StaticTask_t * pxTaskBuffer;
StackType_t * pxStack;
/* Allocate memory for the task's TCB. We use pvPortMalloc() here as the
* TCB must be in internal memory. */
pxTaskBuffer = pvPortMalloc( sizeof( StaticTask_t ) );
/* Allocate memory for the task's stack using the provided memory caps
* */
pxStack = heap_caps_malloc( usStackDepth, ( uint32_t ) uxMemoryCaps );
if( ( pxTaskBuffer == NULL ) || ( pxStack == NULL ) )
{
goto err;
}
/* Create the task using static creation API*/
xHandle = xTaskCreateStaticPinnedToCore( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxStack, pxTaskBuffer, xCoreID );
if( xHandle == NULL )
{
/* Failed to create task */
goto err;
}
else if( pvCreatedTask != NULL )
{
/* Task created successfully. Return the task handle */
*pvCreatedTask = xHandle;
}
return pdPASS;
err:
heap_caps_free( pxStack );
vPortFree( pxTaskBuffer );
return pdFAIL;
}
void vTaskDeleteWithCaps( TaskHandle_t xTaskToDelete )
{
BaseType_t xResult;
StaticTask_t * pxTaskBuffer;
StackType_t * puxStackBuffer;
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
configASSERT( xResult == pdTRUE );
/* Delete the task */
vTaskDelete( xTaskToDelete );
/* Free the memory buffers */
heap_caps_free( puxStackBuffer );
vPortFree( pxTaskBuffer );
}
/* ---------------------------------- 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 ) */