freertos: Add changes to FreeRTOS SMP sources

This commit adds the necessary changes to the FreeRTOS SMP source and
and header files so that it can be compatible with ESP-IDF.
This commit is contained in:
Darian Leung 2022-02-25 19:15:40 +08:00
parent 37c270b337
commit 9da5d7c40a
6 changed files with 296 additions and 8 deletions

View File

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

View File

@ -65,7 +65,7 @@ typedef struct corCoRoutineControlBlock
* crCOROUTINE_CODE pxCoRoutineCode,
* UBaseType_t uxPriority,
* UBaseType_t uxIndex
* );
* );
* </pre>
*
* Create a new co-routine and add it to the list of co-routines that are

View File

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

View File

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

View File

@ -1347,10 +1347,10 @@ BaseType_t xTimerGenericCommandFromISR( TimerHandle_t xTimer,
/**
* task.h
* <pre>void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) </pre>
*
* 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

View File

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