mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
feat(freertos): Add SMP kernel changes to FreeRTOS v10.5.1
This commit adds the key kernel changes to the v10.5.1 kernel to support dual-core SMP. These changes are temporarily documented in the `idf_changes.md` document. This commit... - Added changes to kernel data structures to support multiple cores - Changes to scheduling algorithm support SMP scheduling. - Changes to each FreeRTOS function to support multiple cores and SMP scheduling algorithm.
This commit is contained in:
@@ -405,48 +405,7 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt
|
||||
|
||||
/* ------------------------------------------------- Task Utilities ------------------------------------------------- */
|
||||
|
||||
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
|
||||
|
||||
TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID )
|
||||
{
|
||||
configASSERT( xCoreID >= 0 && xCoreID < configNUM_CORES );
|
||||
configASSERT( ( xIdleTaskHandle[ xCoreID ] != NULL ) );
|
||||
return ( TaskHandle_t ) xIdleTaskHandle[ xCoreID ];
|
||||
}
|
||||
|
||||
#endif /* INCLUDE_xTaskGetIdleTaskHandle */
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
|
||||
|
||||
TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID )
|
||||
{
|
||||
TaskHandle_t xReturn;
|
||||
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
{
|
||||
xReturn = xTaskGetCurrentTaskHandleCPU( xCoreID );
|
||||
}
|
||||
#else /* CONFIG_FREERTOS_SMP */
|
||||
{
|
||||
if( xCoreID < configNUM_CORES )
|
||||
{
|
||||
xReturn = pxCurrentTCB[ xCoreID ];
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_FREERTOS_SMP */
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
|
||||
BaseType_t xTaskGetCoreID( TaskHandle_t xTask )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
@@ -472,11 +431,10 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
|
||||
#else /* CONFIG_FREERTOS_SMP */
|
||||
TCB_t * pxTCB;
|
||||
|
||||
/* Todo: Remove xCoreID for single core builds (IDF-7894) */
|
||||
pxTCB = prvGetTCBFromHandle( xTask );
|
||||
/* Simply read the xCoreID member of the TCB */
|
||||
taskENTER_CRITICAL( &xKernelLock );
|
||||
|
||||
xReturn = pxTCB->xCoreID;
|
||||
taskEXIT_CRITICAL_ISR( &xKernelLock );
|
||||
#endif /* CONFIG_FREERTOS_SMP */
|
||||
}
|
||||
#else /* configNUM_CORES > 1 */
|
||||
@@ -490,6 +448,140 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
|
||||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
|
||||
|
||||
TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID )
|
||||
{
|
||||
#if CONFIG_FREERTOS_USE_KERNEL_10_5_1
|
||||
{
|
||||
/* If xTaskGetIdleTaskHandle() is called before the scheduler has been
|
||||
* started, then xIdleTaskHandle will be NULL. */
|
||||
configASSERT( ( xCoreID < configNUMBER_OF_CORES ) && ( xCoreID != tskNO_AFFINITY ) );
|
||||
configASSERT( ( xIdleTaskHandle[ xCoreID ] != NULL ) );
|
||||
return xIdleTaskHandle[ xCoreID ];
|
||||
}
|
||||
#else /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
|
||||
{
|
||||
configASSERT( xCoreID >= 0 && xCoreID < configNUM_CORES );
|
||||
configASSERT( ( xIdleTaskHandle[ xCoreID ] != NULL ) );
|
||||
return ( TaskHandle_t ) xIdleTaskHandle[ xCoreID ];
|
||||
}
|
||||
#endif /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
|
||||
}
|
||||
|
||||
#endif /* INCLUDE_xTaskGetIdleTaskHandle */
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
|
||||
|
||||
TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID )
|
||||
{
|
||||
TaskHandle_t xReturn;
|
||||
|
||||
#if CONFIG_FREERTOS_USE_KERNEL_10_5_1
|
||||
{
|
||||
configASSERT( xCoreID < configNUMBER_OF_CORES );
|
||||
configASSERT( xCoreID != tskNO_AFFINITY );
|
||||
|
||||
/* For SMP, we need to take the kernel lock here as we are about to
|
||||
* access kernel data structures. For single core, a critical section is
|
||||
* not required as this is not called from an interrupt and the current
|
||||
* TCB will always be the same for any individual execution thread. */
|
||||
taskENTER_CRITICAL_SMP_ONLY();
|
||||
{
|
||||
xReturn = pxCurrentTCBs[ xCoreID ];
|
||||
}
|
||||
/* Release the previously taken kernel lock. */
|
||||
taskEXIT_CRITICAL_SMP_ONLY();
|
||||
}
|
||||
#else /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
|
||||
{
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
{
|
||||
xReturn = xTaskGetCurrentTaskHandleCPU( xCoreID );
|
||||
}
|
||||
#else /* CONFIG_FREERTOS_SMP */
|
||||
{
|
||||
if( xCoreID < configNUM_CORES )
|
||||
{
|
||||
xReturn = pxCurrentTCB[ xCoreID ];
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_FREERTOS_SMP */
|
||||
}
|
||||
#endif /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( CONFIG_FREERTOS_USE_KERNEL_10_5_1 && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
|
||||
|
||||
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounterForCore( BaseType_t xCoreID )
|
||||
{
|
||||
uint32_t ulRunTimeCounter;
|
||||
|
||||
configASSERT( xCoreID < configNUMBER_OF_CORES );
|
||||
configASSERT( xCoreID != tskNO_AFFINITY );
|
||||
|
||||
/* For SMP, we need to take the kernel lock here as we are about to
|
||||
* access kernel data structures. */
|
||||
taskENTER_CRITICAL_SMP_ONLY();
|
||||
{
|
||||
ulRunTimeCounter = xIdleTaskHandle[ xCoreID ]->ulRunTimeCounter;
|
||||
}
|
||||
/* Release the previously taken kernel lock. */
|
||||
taskEXIT_CRITICAL_SMP_ONLY();
|
||||
|
||||
return ulRunTimeCounter;
|
||||
}
|
||||
|
||||
#endif /* ( CONFIG_FREERTOS_USE_KERNEL_10_5_1 && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( CONFIG_FREERTOS_USE_KERNEL_10_5_1 && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
|
||||
|
||||
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercentForCore( BaseType_t xCoreID )
|
||||
{
|
||||
configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
|
||||
|
||||
configASSERT( xCoreID < configNUMBER_OF_CORES );
|
||||
configASSERT( xCoreID != tskNO_AFFINITY );
|
||||
|
||||
ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
|
||||
/* For percentage calculations. */
|
||||
ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
|
||||
|
||||
/* Avoid divide by zero errors. */
|
||||
if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
|
||||
{
|
||||
/* For SMP, we need to take the kernel lock here as we are about
|
||||
* to access kernel data structures. */
|
||||
taskENTER_CRITICAL_SMP_ONLY();
|
||||
{
|
||||
ulReturn = xIdleTaskHandle[ xCoreID ]->ulRunTimeCounter / ulTotalTime;
|
||||
}
|
||||
/* Release the previously taken kernel lock. */
|
||||
taskEXIT_CRITICAL_SMP_ONLY();
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = 0;
|
||||
}
|
||||
|
||||
return ulReturn;
|
||||
}
|
||||
|
||||
#endif /* ( CONFIG_FREERTOS_USE_KERNEL_10_5_1 && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint8_t * pxTaskGetStackStart( TaskHandle_t xTask )
|
||||
{
|
||||
TCB_t * pxTCB;
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
/* -------------------------------------------------- Task Creation ------------------------------------------------- */
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
@@ -108,6 +109,35 @@
|
||||
|
||||
/* ------------------------------------------------- Task Utilities ------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Get the current core ID of a particular task
|
||||
*
|
||||
* Helper function to get the core ID of a particular task. If the task is
|
||||
* pinned to a particular core, the core ID is returned. If the task is not
|
||||
* pinned to a particular core, tskNO_AFFINITY is returned.
|
||||
*
|
||||
* If CONFIG_FREERTOS_UNICORE is enabled, this function simply returns 0.
|
||||
*
|
||||
* [refactor-todo] See if this needs to be deprecated (IDF-8145)(IDF-8164)
|
||||
*
|
||||
* @note If CONFIG_FREERTOS_SMP is enabled, please call vTaskCoreAffinityGet()
|
||||
* instead.
|
||||
* @note In IDF FreerTOS when configNUMBER_OF_CORES == 1, this function will
|
||||
* always return 0,
|
||||
* @param xTask The task to query
|
||||
* @return The task's core ID or tskNO_AFFINITY
|
||||
*/
|
||||
BaseType_t xTaskGetCoreID( TaskHandle_t xTask );
|
||||
|
||||
/** @cond */
|
||||
/* Todo: Deprecate this API in favor of xTaskGetIdleTaskHandleForCore (IDF-8163) */
|
||||
static inline __attribute__( ( always_inline ) )
|
||||
BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
|
||||
{
|
||||
return xTaskGetCoreID( xTask );
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Get the handle of idle task for the given core.
|
||||
*
|
||||
@@ -118,7 +148,16 @@
|
||||
* @param xCoreID The core to query
|
||||
* @return Handle of the idle task for the queried core
|
||||
*/
|
||||
TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID );
|
||||
TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID );
|
||||
|
||||
/** @cond */
|
||||
/* Todo: Deprecate this API in favor of xTaskGetIdleTaskHandleForCore (IDF-8163) */
|
||||
static inline __attribute__( ( always_inline ) )
|
||||
TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID )
|
||||
{
|
||||
return xTaskGetIdleTaskHandleForCore( xCoreID );
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Get the handle of the task currently running on a certain core
|
||||
@@ -134,25 +173,42 @@ TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID );
|
||||
* @param xCoreID The core to query
|
||||
* @return Handle of the current task running on the queried core
|
||||
*/
|
||||
TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID );
|
||||
TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID );
|
||||
|
||||
/** @cond */
|
||||
/* Todo: Deprecate this API in favor of xTaskGetCurrentTaskHandleForCore (IDF-8163) */
|
||||
static inline __attribute__( ( always_inline ) )
|
||||
TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID )
|
||||
{
|
||||
return xTaskGetCurrentTaskHandleForCore( xCoreID );
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
#if CONFIG_FREERTOS_USE_KERNEL_10_5_1
|
||||
|
||||
/**
|
||||
* @brief Get the current core affinity of a particular task
|
||||
* @brief Get the total execution of a particular core's idle task
|
||||
*
|
||||
* Helper function to get the core affinity of a particular task. If the task is
|
||||
* pinned to a particular core, the core ID is returned. If the task is not
|
||||
* pinned to a particular core, tskNO_AFFINITY is returned.
|
||||
* This function is equivalent to ulTaskGetIdleRunTimeCounter() but queries the
|
||||
* idle task of a particular core.
|
||||
*
|
||||
* If CONFIG_FREERTOS_UNICORE is enabled, this function simply returns 0.
|
||||
*
|
||||
* [refactor-todo] See if this needs to be deprecated (IDF-8145)(IDF-8164)
|
||||
*
|
||||
* @note If CONFIG_FREERTOS_SMP is enabled, please call vTaskCoreAffinityGet()
|
||||
* instead.
|
||||
* @param xTask The task to query
|
||||
* @return The tasks coreID or tskNO_AFFINITY
|
||||
* @param xCoreID Core ID of the idle task to query
|
||||
* @return The total run time of the idle task
|
||||
*/
|
||||
BaseType_t xTaskGetAffinity( TaskHandle_t xTask );
|
||||
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounterForCore( BaseType_t xCoreID );
|
||||
|
||||
/**
|
||||
* @brief Get the percentage run time of a particular core's idle task
|
||||
*
|
||||
* This function is equivalent to ulTaskGetIdleRunTimePercent() but queries the
|
||||
* idle task of a particular core.
|
||||
*
|
||||
* @param xCoreID Core ID of the idle task to query
|
||||
* @return The percentage run time of the idle task
|
||||
*/
|
||||
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercentForCore( BaseType_t xCoreID );
|
||||
|
||||
#endif /* CONFIG_FREERTOS_USE_KERNEL_10_5_1 */
|
||||
|
||||
/**
|
||||
* Returns the start of the stack associated with xTask.
|
||||
|
Reference in New Issue
Block a user