Эх сурвалжийг харах

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.
Darian Leung 4 жил өмнө
parent
commit
9da5d7c40a

+ 5 - 0
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;

+ 1 - 1
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
- *                             ); 
+ *                             );
  * </pre>
  *
  * Create a new co-routine and add it to the list of co-routines that are

+ 12 - 0
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 */

+ 87 - 1
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
     }

+ 3 - 3
components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h

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

+ 188 - 3
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