diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h index 6aa3b803c0..7faa8a8344 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h @@ -1229,6 +1229,11 @@ typedef struct xSTATIC_TCB #endif #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) void * pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #ifdef ESP_PLATFORM + #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + void *pvDummaTLSDelCb[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + #endif //ESP_PLATFORM #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) uint32_t ulDummy16; diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h index c8b3362c8f..5caecd29a8 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h @@ -65,7 +65,7 @@ typedef struct corCoRoutineControlBlock * crCOROUTINE_CODE pxCoRoutineCode, * UBaseType_t uxPriority, * UBaseType_t uxIndex - * ); + * ); * * * Create a new co-routine and add it to the list of co-routines that are diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h index 0d0cf1d70b..2f443e6402 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h @@ -117,4 +117,16 @@ typedef void (* TaskFunction_t)( void * ); #define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN +/* ------------------------------------------------ IDF Compatibility -------------------------------------------------- + * + * ------------------------------------------------------------------------------------------------------------------ */ + +#ifdef ESP_PLATFORM + +#ifndef pdTICKS_TO_MS + #define pdTICKS_TO_MS( xTicks ) ( ( TickType_t ) ( ( uint64_t ) ( xTicks ) * 1000 / configTICK_RATE_HZ ) ) +#endif + +#endif // ESP_PLATFORM + #endif /* PROJDEFS_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h index 64fdd7a9f8..be2e41d9c2 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h @@ -3147,7 +3147,7 @@ TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; /* * Return the handle of the task running on specified core. */ -TaskHandle_t xTaskGetCurrentTaskHandleCPU( UBaseType_t xCoreID ) PRIVILEGED_FUNCTION; +TaskHandle_t xTaskGetCurrentTaskHandleCPU( BaseType_t xCoreID ) PRIVILEGED_FUNCTION; /* * Shortcut used by the queue implementation to prevent unnecessary call to @@ -3240,6 +3240,92 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC */ void vTaskYieldWithinAPI( void ); +/* ------------------------------------------------ IDF Compatibility -------------------------------------------------- + * + * ------------------------------------------------------------------------------------------------------------------ */ + +#ifdef ESP_PLATFORM +BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pvCreatedTask, + const BaseType_t xCoreID); + +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) +TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pxTaskCode, + const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer, + const BaseType_t xCoreID ) PRIVILEGED_FUNCTION; +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + + /** + * Prototype of local storage pointer deletion callback. + */ + typedef void (*TlsDeleteCallbackFunction_t)( int, void * ); + + /** + * Set local storage pointer and deletion callback. + * + * Each task contains an array of pointers that is dimensioned by the + * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. + * The kernel does not use the pointers itself, so the application writer + * can use the pointers for any purpose they wish. + * + * Local storage pointers set for a task can reference dynamically + * allocated resources. This function is similar to + * vTaskSetThreadLocalStoragePointer, but provides a way to release + * these resources when the task gets deleted. For each pointer, + * a callback function can be set. This function will be called + * when task is deleted, with the local storage pointer index + * and value as arguments. + * + * @param xTaskToSet Task to set thread local storage pointer for + * @param xIndex The index of the pointer to set, from 0 to + * configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1. + * @param pvValue Pointer value to set. + * @param pvDelCallback Function to call to dispose of the local + * storage pointer when the task is deleted. + */ + void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue, TlsDeleteCallbackFunction_t pvDelCallback); +#endif + +/* + * Return the handle of the task running on a certain CPU. Because of + * the nature of SMP processing, there is no guarantee that this + * value will still be valid on return and should only be used for + * debugging purposes. + */ +TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid ); + +/** + * Get the handle of idle task for the given CPU. + * + * xTaskGetIdleTaskHandleForCPU() is only available if + * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * @param cpuid The CPU to get the handle for + * + * @return Idle task handle of a given cpu. It is not valid to call + * xTaskGetIdleTaskHandleForCPU() before the scheduler has been started. + */ +TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t cpuid ); + +/* + * Get the current core affinity of a task + */ +BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + + +#endif //ESP_PLATFORM + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h index 2ef995114b..13492897af 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h @@ -1347,10 +1347,10 @@ BaseType_t xTimerGenericCommandFromISR( TimerHandle_t xTimer, /** * task.h *
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) 
- * - * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Timer Task TCB. This function is required when + * + * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Timer Task TCB. This function is required when * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION - * + * * @param ppxTimerTaskTCBBuffer A handle to a statically allocated TCB buffer * @param ppxTimerTaskStackBuffer A handle to a statically allocated Stack buffer for thie idle task * @param pulTimerTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer diff --git a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c index 901c73899a..1017bed41c 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c @@ -39,6 +39,12 @@ #include "timers.h" #include "stack_macros.h" +#ifdef ESP_PLATFORM +#include "esp_newlib.h" /* required for esp_reent_init() in tasks.c */ +#undef _REENT_INIT_PTR +#define _REENT_INIT_PTR esp_reent_init +#endif + /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the @@ -280,6 +286,11 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #ifdef ESP_PLATFORM + #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + TlsDeleteCallbackFunction_t pvThreadLocalStoragePointersDelCallback[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + #endif //ESP_PLATFORM #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) @@ -823,7 +834,7 @@ static void prvYieldForTask( TCB_t * pxTCB, BaseType_t xTaskScheduled = pdFALSE; BaseType_t xDecrementTopPriority = pdTRUE; - #if ( configUSE_CORE_AFFINITY == 1 ) + #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) TCB_t * pxPreviousTCB = NULL; #endif #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) @@ -899,7 +910,7 @@ static void prvYieldForTask( TCB_t * pxTCB, { /* If the task is not being executed by any core swap it in */ pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_NOT_RUNNING; - #if ( configUSE_CORE_AFFINITY == 1 ) + #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) pxPreviousTCB = pxCurrentTCBs[ xCoreID ]; #endif pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID; @@ -1458,6 +1469,11 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) { memset( ( void * ) &( pxNewTCB->pvThreadLocalStoragePointers[ 0 ] ), 0x00, sizeof( pxNewTCB->pvThreadLocalStoragePointers ) ); + #ifdef ESP_PLATFORM + #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + memset ( (void * ) &( pxNewTCB->pvThreadLocalStoragePointersDelCallback[0] ), 0x00, sizeof( pxNewTCB->pvThreadLocalStoragePointersDelCallback ) ); + #endif + #endif //ESP_PLATFORM } #endif @@ -2744,6 +2760,13 @@ static BaseType_t prvCreateIdleTasks( void ) #endif } #endif /* configSUPPORT_STATIC_ALLOCATION */ + +#ifdef ESP_PLATFORM + #if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) + //Don't forget to pin the created IDLE tasks + vTaskCoreAffinitySet(xIdleTaskHandle[ xCoreID ], (1 << xCoreID) ); + #endif +#endif } return xReturn; @@ -2785,7 +2808,9 @@ void vTaskStartScheduler( void ) * structure specific to the task that will run first. * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html * for additional information. */ +#ifndef ESP_PLATFORM _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); +#endif } #endif /* configUSE_NEWLIB_REENTRANT */ @@ -3876,7 +3901,9 @@ void vTaskSwitchContext( BaseType_t xCoreID ) * structure specific to this task. * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html * for additional information. */ +#ifndef ESP_PLATFORM _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); +#endif } #endif /* configUSE_NEWLIB_REENTRANT */ } @@ -4833,6 +4860,18 @@ static void prvCheckTasksWaitingTermination( void ) static void prvDeleteTCB( TCB_t * pxTCB ) { + #ifdef ESP_PLATFORM + #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + for( int x = 0; x < configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) + { + if (pxTCB->pvThreadLocalStoragePointersDelCallback[ x ] != NULL) //If del cb is set + { + pxTCB->pvThreadLocalStoragePointersDelCallback[ x ](x, pxTCB->pvThreadLocalStoragePointers[ x ]); //Call del cb + } + } + #endif + #endif //ESP_PLATFORM + /* This call is required specifically for the TriCore port. It must be * above the vPortFree() calls. The call is also used by ports/demos that * want to allocate and clean RAM statically. */ @@ -4922,7 +4961,7 @@ static void prvResetNextTaskUnblockTime( void ) return xReturn; } - TaskHandle_t xTaskGetCurrentTaskHandleCPU( UBaseType_t xCoreID ) + TaskHandle_t xTaskGetCurrentTaskHandleCPU( BaseType_t xCoreID ) { TaskHandle_t xReturn = NULL; @@ -6354,3 +6393,149 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, #endif #endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */ + +/* ------------------------------------------------ IDF Compatibility -------------------------------------------------- + * + * ------------------------------------------------------------------------------------------------------------------ */ + +#ifdef ESP_PLATFORM + +BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pvCreatedTask, + const BaseType_t xCoreID) +{ + BaseType_t ret; +#if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) + /* + If we are using multiple cores and core affinity, we need to create the task then set the core affinity of that + task. We do this with interrupts disabled to prevent the task from being scehduled immediately after + xTaskCreate(). + */ + portDISABLE_INTERRUPTS(); + TaskHandle_t xTaskHandleTemp; + ret = xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, &xTaskHandleTemp); + if (ret == pdPASS) { + UBaseType_t uxCoreAffinityMask; + if (xCoreID == tskNO_AFFINITY) { + uxCoreAffinityMask = tskNO_AFFINITY; + } else { + uxCoreAffinityMask = (1 << xCoreID); + } + vTaskCoreAffinitySet(xTaskHandleTemp, uxCoreAffinityMask); + if (pvCreatedTask != NULL) { + *pvCreatedTask = xTaskHandleTemp; + } + } + portENABLE_INTERRUPTS(); +#else /* if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) */ + //No need to set the affinity. Just create the task + ret = xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask); +#endif /* if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) */ + return ret; +} + +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) +TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer, + const BaseType_t xCoreID) +{ + TaskHandle_t xTaskHandleTemp; +#if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) + /* + If we are using multiple cores and core affinity, we need to create the task then set the core affinity of that + task. We do this with interrupts disabled to prevent the task from being scehduled immediately after + xTaskCreate(). + */ + portDISABLE_INTERRUPTS(); + xTaskHandleTemp = xTaskCreateStatic(pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer); + if (xTaskHandleTemp != NULL) { + UBaseType_t uxCoreAffinityMask; + if (xCoreID == tskNO_AFFINITY) { + uxCoreAffinityMask = tskNO_AFFINITY; + } else { + uxCoreAffinityMask = (1 << xCoreID); + } + vTaskCoreAffinitySet(xTaskHandleTemp, uxCoreAffinityMask); + } + portENABLE_INTERRUPTS(); +#else /* if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) */ + xTaskHandleTemp = xTaskCreateStatic(pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer); +#endif /* if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) */ + return xTaskHandleTemp; +} +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue , TlsDeleteCallbackFunction_t xDelCallback) + { + //Set the local storage pointer first + vTaskSetThreadLocalStoragePointer(xTaskToSet, xIndex, pvValue); + //Set the deletion callback + TCB_t * pxTCB; + pxTCB = prvGetTCBFromHandle( xTaskToSet ); + pxTCB->pvThreadLocalStoragePointersDelCallback[ xIndex ] = xDelCallback; + } +#endif + +TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid ) +{ + TaskHandle_t xTaskHandleTemp; + assert(cpuid >= 0 && cpuid < configNUM_CORES); + taskENTER_CRITICAL(); + xTaskHandleTemp = (TaskHandle_t) pxCurrentTCBs[cpuid]; + taskEXIT_CRITICAL(); + return xTaskHandleTemp; +} + +TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t cpuid ) +{ + assert(cpuid >= 0 && cpuid < configNUM_CORES); + return (TaskHandle_t) xIdleTaskHandle[cpuid]; +} + +BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) +{ + taskENTER_CRITICAL(); + UBaseType_t uxCoreAffinityMask; +#if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) + TCB_t *pxTCB = prvGetTCBFromHandle( xTask ); + uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; +#else + uxCoreAffinityMask = tskNO_AFFINITY; +#endif + taskEXIT_CRITICAL(); + BaseType_t ret; + if (uxCoreAffinityMask == tskNO_AFFINITY) { + ret = tskNO_AFFINITY; + } else { + int index_plus_one = __builtin_ffs(uxCoreAffinityMask); + assert(index_plus_one >= 1); + ret = index_plus_one - 1; + } + return ret; +} + +#if ( configUSE_NEWLIB_REENTRANT == 1 ) +//Return global reent struct if FreeRTOS isn't running, +struct _reent* __getreent(void) { + //No lock needed because if this changes, we won't be running anymore. + TCB_t *currTask=xTaskGetCurrentTaskHandle(); + if (currTask==NULL) { + //No task running. Return global struct. + return _GLOBAL_REENT; + } else { + //We have a task; return its reentrant struct. + return &currTask->xNewLib_reent; + } +} +#endif +#endif //ESP_PLATFORM