/* * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ /* * This file contains the implementation for some the functions in * idf_additions.h */ #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" /* -------------------------------------------- Creation With Memory Caps ------------------------------------------- */ /* ---------------------------------- Tasks --------------------------------- */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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; } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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 ); } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ /* ---------------------------------- Queue --------------------------------- */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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; } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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 ); } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ /* -------------------------------- Semaphore ------------------------------- */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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; } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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 ); } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ /* ------------------------- Stream & Message Buffers ----------------------- */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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; } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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 ); } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ /* ------------------------------ Event Groups ------------------------------ */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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; } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 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 ) */ /*----------------------------------------------------------*/