@@ -410,6 +410,11 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t
410410
411411/* File private functions. --------------------------------*/
412412
413+ /*
414+ * Creates the idle tasks during scheduler start
415+ */
416+ static BaseType_t prvCreateIdleTasks ( void );
417+
413418/*
414419 * Returns the yield pending count for the calling core.
415420 */
@@ -460,13 +465,11 @@ static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
460465 * The idle task is automatically created and added to the ready lists upon
461466 * creation of the first user task.
462467 *
463- * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
464- * language extensions. The equivalent prototype for this function is:
465- *
466- * void prvIdleTask( void *pvParameters );
467- *
468468 */
469469static portTASK_FUNCTION_PROTO ( prvIdleTask , pvParameters ) PRIVILEGED_FUNCTION ;
470+ #if ( configNUM_CORES > 1 )
471+ static portTASK_FUNCTION_PROTO ( prvMinimalIdleTask , pvParameters ) PRIVILEGED_FUNCTION ;
472+ #endif
470473
471474/*
472475 * Utility to free all memory allocated by the scheduler to hold a TCB,
@@ -1545,7 +1548,20 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
15451548 pxNewTCB -> xTaskRunState = taskTASK_NOT_RUNNING ;
15461549
15471550 /* Is this an idle task? */
1548- pxNewTCB -> xIsIdle = ( pxTaskCode == prvIdleTask );
1551+ if (pxTaskCode == prvIdleTask )
1552+ {
1553+ pxNewTCB -> xIsIdle = pdTRUE ;
1554+ }
1555+ #if (configNUM_CORES > 1 )
1556+ else if (pxTaskCode == prvMinimalIdleTask )
1557+ {
1558+ pxNewTCB -> xIsIdle = pdTRUE ;
1559+ }
1560+ #endif
1561+ else
1562+ {
1563+ pxNewTCB -> xIsIdle = pdFALSE ;
1564+ }
15491565
15501566 if ( pxCreatedTask != NULL )
15511567 {
@@ -2598,19 +2614,13 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
25982614#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
25992615/*-----------------------------------------------------------*/
26002616
2601- void vTaskStartScheduler ( void )
2617+ static BaseType_t prvCreateIdleTasks ( void )
26022618{
2603- BaseType_t xReturn ;
2619+ BaseType_t xReturn = pdPASS ;
26042620 BaseType_t xCoreID ;
26052621 char cIdleName [ configMAX_TASK_NAME_LEN ];
26062622
2607- #if ( configUSE_TIMERS == 1 )
2608- {
2609- xReturn = xTimerCreateTimerTask ();
2610- }
2611- #endif /* configUSE_TIMERS */
2612-
2613- /* Add each idle task at the lowest priority. */
2623+ /* Add each idle task at the lowest priority. */
26142624 for ( xCoreID = ( BaseType_t ) 0 ; xCoreID < ( BaseType_t ) configNUM_CORES ; xCoreID ++ )
26152625 {
26162626 BaseType_t x ;
@@ -2663,22 +2673,38 @@ void vTaskStartScheduler( void )
26632673
26642674 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
26652675 {
2666- #error User must specify an array of buffers for idle task TCBs and stacks
2667- StaticTask_t * pxIdleTaskTCBBuffer = NULL ;
2668- StackType_t * pxIdleTaskStackBuffer = NULL ;
2669- uint32_t ulIdleTaskStackSize ;
2670-
2671- /* The Idle task is created using user provided RAM - obtain the
2672- * address of the RAM then create the idle task. */
2673- vApplicationGetIdleTaskMemory ( & pxIdleTaskTCBBuffer , & pxIdleTaskStackBuffer , & ulIdleTaskStackSize );
2674- xIdleTaskHandle [ xCoreID ] = xTaskCreateStatic ( prvIdleTask ,
2675- cIdleName ,
2676- ulIdleTaskStackSize ,
2677- ( void * ) NULL , /*lint !e961. The cast is not redundant for all compilers. */
2678- portPRIVILEGE_BIT , /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
2679- pxIdleTaskStackBuffer ,
2680- pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
2681-
2676+ if (xCoreID == 0 )
2677+ {
2678+ StaticTask_t * pxIdleTaskTCBBuffer = NULL ;
2679+ StackType_t * pxIdleTaskStackBuffer = NULL ;
2680+ uint32_t ulIdleTaskStackSize ;
2681+
2682+ /* The Idle task is created using user provided RAM - obtain the
2683+ * address of the RAM then create the idle task. */
2684+ vApplicationGetIdleTaskMemory ( & pxIdleTaskTCBBuffer , & pxIdleTaskStackBuffer , & ulIdleTaskStackSize );
2685+ xIdleTaskHandle [ xCoreID ] = xTaskCreateStatic ( prvIdleTask ,
2686+ cIdleName ,
2687+ ulIdleTaskStackSize ,
2688+ ( void * ) NULL , /*lint !e961. The cast is not redundant for all compilers. */
2689+ portPRIVILEGE_BIT , /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
2690+ pxIdleTaskStackBuffer ,
2691+ pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
2692+ }
2693+ #if ( configNUM_CORES > 1 )
2694+ else
2695+ {
2696+ static StaticTask_t xIdleTCBBuffers [configNUM_CORES - 1 ];
2697+ static StackType_t xIdleTaskStackBuffers [configMINIMAL_STACK_SIZE ][configNUM_CORES - 1 ];
2698+
2699+ xIdleTaskHandle [ xCoreID ] = xTaskCreateStatic ( prvMinimalIdleTask ,
2700+ cIdleName ,
2701+ configMINIMAL_STACK_SIZE ,
2702+ ( void * ) NULL , /*lint !e961. The cast is not redundant for all compilers. */
2703+ portPRIVILEGE_BIT , /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
2704+ xIdleTaskStackBuffers [xCoreID - 1 ],
2705+ & xIdleTCBBuffers [xCoreID - 1 ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
2706+ }
2707+ #endif
26822708 if ( xIdleTaskHandle [ xCoreID ] != NULL )
26832709 {
26842710 xReturn = pdPASS ;
@@ -2690,16 +2716,44 @@ void vTaskStartScheduler( void )
26902716 }
26912717 #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
26922718 {
2719+ if (xCoreID == 0 )
2720+ {
26932721 /* The Idle task is being created using dynamically allocated RAM. */
26942722 xReturn = xTaskCreate ( prvIdleTask ,
26952723 cIdleName ,
26962724 configMINIMAL_STACK_SIZE ,
26972725 ( void * ) NULL ,
26982726 portPRIVILEGE_BIT , /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
26992727 & xIdleTaskHandle [ xCoreID ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
2728+ }
2729+ #if ( configNUM_CORES > 1 )
2730+ else
2731+ {
2732+ xReturn = xTaskCreate ( prvMinimalIdleTask ,
2733+ cIdleName ,
2734+ configMINIMAL_STACK_SIZE ,
2735+ ( void * ) NULL ,
2736+ portPRIVILEGE_BIT , /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
2737+ & xIdleTaskHandle [ xCoreID ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
2738+ }
2739+ #endif
27002740 }
27012741 #endif /* configSUPPORT_STATIC_ALLOCATION */
27022742 }
2743+ return xReturn ;
2744+ }
2745+
2746+ void vTaskStartScheduler ( void )
2747+ {
2748+ BaseType_t xReturn ;
2749+
2750+ #if ( configUSE_TIMERS == 1 )
2751+ {
2752+ xReturn = xTimerCreateTimerTask ();
2753+ }
2754+ #endif /* configUSE_TIMERS */
2755+
2756+ xReturn = prvCreateIdleTasks ();
27032757
27042758 if ( xReturn == pdPASS )
27052759 {
@@ -4148,13 +4202,59 @@ void vTaskMissedYield( void )
41484202
41494203/*
41504204 * -----------------------------------------------------------
4151- * The Idle task.
4205+ * The MinimalIdle task.
41524206 * ----------------------------------------------------------
41534207 *
4154- * The portTASK_FUNCTION() macro is used to allow port/compiler specific
4155- * language extensions. The equivalent prototype for this function is:
4208+ * The minimal idle task is used for all the additional Cores in a SMP system.
4209+ * There must be only 1 idle task and the rest are minimal idle tasks.
4210+ *
4211+ * @todo additional conditional compiles to remove this function.
4212+ */
4213+ #if (configNUM_CORES > 1 )
4214+ static portTASK_FUNCTION ( prvMinimalIdleTask , pvParameters )
4215+ {
4216+ for (;;)
4217+ {
4218+ #if ( configUSE_PREEMPTION == 0 )
4219+ {
4220+ /* If we are not using preemption we keep forcing a task switch to
4221+ * see if any other task has become available. If we are using
4222+ * preemption we don't need to do this as any task becoming available
4223+ * will automatically get the processor anyway. */
4224+ taskYIELD ();
4225+ }
4226+ #endif /* configUSE_PREEMPTION */
4227+
4228+ #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
4229+ {
4230+ /* When using preemption tasks of equal priority will be
4231+ * timesliced. If a task that is sharing the idle priority is ready
4232+ * to run then the idle task should yield before the end of the
4233+ * timeslice.
4234+ *
4235+ * A critical region is not required here as we are just reading from
4236+ * the list, and an occasional incorrect value will not matter. If
4237+ * the ready list at the idle priority contains one more task than the
4238+ * number of idle tasks, which is equal to the configured numbers of cores
4239+ * then a task other than the idle task is ready to execute. */
4240+ if ( listCURRENT_LIST_LENGTH ( & ( pxReadyTasksLists [ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUM_CORES )
4241+ {
4242+ taskYIELD ();
4243+ }
4244+ else
4245+ {
4246+ mtCOVERAGE_TEST_MARKER ();
4247+ }
4248+ }
4249+ #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
4250+ }
4251+ }
4252+ #endif
4253+ /*
4254+ * -----------------------------------------------------------
4255+ * The Idle task.
4256+ * ----------------------------------------------------------
41564257 *
4157- * void prvIdleTask( void *pvParameters );
41584258 *
41594259 */
41604260static portTASK_FUNCTION ( prvIdleTask , pvParameters )
0 commit comments