Parcourir la source

Merge branch 'feature/freertos_smp_sysview' into 'master'

sysview: Adds FreeRTOS SMP port

Closes IDF-4995

See merge request espressif/esp-idf!18615
Roland Dobai il y a 3 ans
Parent
commit
1a006cb718

+ 10 - 2
components/app_trace/sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c

@@ -142,7 +142,11 @@ static U64 _cbGetTime(void) {
 void SYSVIEW_AddTask(U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32  pxStack, unsigned uStackHighWaterMark) {
   unsigned n;
 
-  if (memcmp(pcTaskName, "IDLE", 5) == 0) {
+  /* On multi-core we have several idle tasks with 'IDLEx' names
+     Not best solution, because we can filter out user tasks starting with 'IDLE'.
+     But we can not use 'xTaskGetIdleTaskHandle' because at the moment when this
+     function is called array of idle tasks handles are not initialized yet. */
+  if (memcmp(pcTaskName, "IDLE", 4) == 0) {
     return;
   }
 
@@ -176,7 +180,11 @@ void SYSVIEW_AddTask(U32 xHandle, const char* pcTaskName, unsigned uxCurrentPrio
 void SYSVIEW_UpdateTask(U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark) {
   unsigned n;
 
-  if (memcmp(pcTaskName, "IDLE", 5) == 0) {
+  /* On multi-core we have several idle tasks with 'IDLEx' names
+     Not best solution, because we can filter out user tasks starting with 'IDLE'.
+     But we can not use 'xTaskGetIdleTaskHandle' because at the moment when this
+     function is called array of idle tasks handles are not initialized yet. */
+  if (memcmp(pcTaskName, "IDLE", 4) == 0) {
     return;
   }
 

+ 26 - 65
components/app_trace/sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.h

@@ -212,63 +212,27 @@ Notes:
 #define apiID_UXEVENTGROUPGETNUMBER               (73u)
 
 #ifdef CONFIG_FREERTOS_SMP
-/*
-FreeRTOS SMP has diverged from ESP-IDF FreeRTOS source quite a bit, thus Sysview is out of sync. For now, we just
-define away all of the tracing macros.
-*/
-#define traceTASK_NOTIFY_TAKE( uxIndexToWait )
-#define traceTASK_DELAY()
-#define traceTASK_DELAY_UNTIL( xTimeToWake )
-#define traceTASK_DELETE( pxTCB )
-#define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify )
-#define traceTASK_PRIORITY_INHERIT( pxTCB, uxPriority )
-#define traceTASK_RESUME( pxTCB )
-#define traceINCREASE_TICK_COUNT( xTicksToJump )
-#define traceTASK_SUSPEND( pxTCB )
-#define traceTASK_PRIORITY_DISINHERIT( pxTCB, uxBasePriority )
-#define traceTASK_RESUME_FROM_ISR( pxTCB )
-#define traceTASK_NOTIFY( uxIndexToNotify )
-#define traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify )
-#define traceTASK_NOTIFY_WAIT( uxIndexToWait )
-#define traceQUEUE_CREATE( pxNewQueue )
-#define traceQUEUE_DELETE( pxQueue )
-#define traceQUEUE_PEEK( pxQueue )
-#define traceQUEUE_PEEK_FROM_ISR( pxQueue )
-#define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue )
-#define traceQUEUE_RECEIVE( pxQueue )
-#define traceQUEUE_RECEIVE_FAILED( pxQueue )
-#define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue )
-#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue )
-#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue )
-#define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName )
-#define traceQUEUE_SEND( pxQueue )
-#define traceQUEUE_SEND_FAILED( pxQueue )
-#define traceQUEUE_SEND_FROM_ISR( pxQueue )
-#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue )
-#define traceQUEUE_GIVE_FROM_ISR( pxQueue )
-#define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue )
-#define traceTASK_CREATE(pxNewTCB)
-#define traceTASK_PRIORITY_SET(pxTask, uxNewPriority)
-#define traceTASK_SWITCHED_IN()
-#define traceMOVED_TASK_TO_READY_STATE(pxTCB)
-#define traceREADDED_TASK_TO_READY_STATE(pxTCB)
-#define traceMOVED_TASK_TO_DELAYED_LIST()
-#define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST()
-#define traceMOVED_TASK_TO_SUSPENDED_LIST(pxTCB)
-#define traceISR_EXIT_TO_SCHEDULER()
-#define traceISR_EXIT()
-#define traceISR_ENTER(_n_)
+
+#define traceQUEUE_SEND( pxQueue )                  SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0, 0, 0)
 
 #else // CONFIG_FREERTOS_SMP
 
+#if ( configUSE_QUEUE_SETS != 1 )
+  #define traceQUEUE_SEND( pxQueue )                SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
+#else
+  #define traceQUEUE_SEND( pxQueue )                SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0, 0, xCopyPosition)
+#endif
+
+#endif // CONFIG_FREERTOS_SMP
+
 #define traceTASK_NOTIFY_TAKE( uxIndexToWait )                        SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_ULTASKNOTIFYTAKE, xClearCountOnExit, xTicksToWait)
 #define traceTASK_DELAY()                                             SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELAY, xTicksToDelay)
 #define traceTASK_DELAY_UNTIL( xTimeToWake )                          SEGGER_SYSVIEW_RecordVoid(apiFastID_OFFSET + apiID_VTASKDELAYUNTIL)
-#define traceTASK_DELETE( pxTCB )                                     if (pxTCB != NULL) {                                              \
-						                                                SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELETE,  \
-						                                                                      SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)); 	\
-					                                                    SYSVIEW_DeleteTask((U32)pxTCB);                                 \
-					                                                  }
+#define traceTASK_DELETE( pxTCB )                                     do {                                              \
+                                                                        SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELETE,  \
+                                                                                              SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)); 	\
+                                                                        SYSVIEW_DeleteTask((U32)pxTCB);                                 \
+                                                                      } while(0)
 #define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify )             SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VTASKNOTIFYGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), (U32)pxHigherPriorityTaskWoken)
 #define traceTASK_PRIORITY_INHERIT( pxTCB, uxPriority )               SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKPRIORITYINHERIT, (U32)pxMutexHolder)
 #define traceTASK_RESUME( pxTCB )                                     SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKRESUME, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB))
@@ -291,11 +255,6 @@ define away all of the tracing macros.
 #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue )                        SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUERECEIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), (U32)pxHigherPriorityTaskWoken)
 #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue )                 SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUERECEIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), (U32)pxHigherPriorityTaskWoken)
 #define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName )                SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VQUEUEADDTOREGISTRY, SEGGER_SYSVIEW_ShrinkId((U32)xQueue), (U32)pcQueueName)
-#if ( configUSE_QUEUE_SETS != 1 )
-  #define traceQUEUE_SEND( pxQueue )                                    SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
-#else
-  #define traceQUEUE_SEND( pxQueue )                                    SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0, 0, xCopyPosition)
-#endif
 #define traceQUEUE_SEND_FAILED( pxQueue )                             SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
 #define traceQUEUE_SEND_FROM_ISR( pxQueue )                           SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition)
 #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue )                    SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition)
@@ -338,35 +297,37 @@ define away all of the tracing macros.
 //
 // Define INCLUDE_xTaskGetIdleTaskHandle as 1 in FreeRTOSConfig.h to allow identification of Idle state.
 //
-#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
+// SMP FreeRTOS uses unpinned IDLE tasks, so sometimes IDEL0 runs on CPU1, IDLE1 runs on CPU0 and so on.
+// So IDLE state detection based on 'xTaskGetIdleTaskHandle' does not work for SMP kernel.
+// We could compare current task handle with every element of the array returned by 'xTaskGetIdleTaskHandle',
+// but it deos not seem to be efficient enough to be worth of making code more complex and less readabl.
+// So always use task name comparison mechanism for SMP kernel.
+#if ( INCLUDE_xTaskGetIdleTaskHandle == 1  && !defined(CONFIG_FREERTOS_SMP))
   #define traceTASK_SWITCHED_IN()                   if(prvGetTCBFromHandle(NULL) == xTaskGetIdleTaskHandle()) {           \
                                                       SEGGER_SYSVIEW_OnIdle();                                          \
                                                     } else {                                                            \
-                                                      SEGGER_SYSVIEW_OnTaskStartExec((U32)pxCurrentTCB[esp_cpu_get_core_id()]); \
+                                                      SEGGER_SYSVIEW_OnTaskStartExec((U32)prvGetTCBFromHandle(NULL)); \
                                                     }
 #else
   #define traceTASK_SWITCHED_IN()                   {                                                                   \
-                                                      if (memcmp(pxCurrentTCB[esp_cpu_get_core_id()]->pcTaskName, "IDLE", 5) != 0) { \
-                                                        SEGGER_SYSVIEW_OnTaskStartExec((U32)pxCurrentTCB[esp_cpu_get_core_id()]);    \
+                                                      if (memcmp(prvGetTCBFromHandle(NULL)->pcTaskName, "IDLE", 4) != 0) { \
+                                                        SEGGER_SYSVIEW_OnTaskStartExec((U32)prvGetTCBFromHandle(NULL));    \
                                                       } else {                                                          \
                                                         SEGGER_SYSVIEW_OnIdle();                                        \
                                                       }                                                                 \
                                                     }
 #endif
-
 #define traceMOVED_TASK_TO_READY_STATE(pxTCB)       SEGGER_SYSVIEW_OnTaskStartReady((U32)pxTCB)
 #define traceREADDED_TASK_TO_READY_STATE(pxTCB)
 
-#define traceMOVED_TASK_TO_DELAYED_LIST()           SEGGER_SYSVIEW_OnTaskStopReady((U32)pxCurrentTCB[esp_cpu_get_core_id()],  (1u << 2))
-#define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST()  SEGGER_SYSVIEW_OnTaskStopReady((U32)pxCurrentTCB[esp_cpu_get_core_id()],  (1u << 2))
+#define traceMOVED_TASK_TO_DELAYED_LIST()           SEGGER_SYSVIEW_OnTaskStopReady((U32)prvGetTCBFromHandle(NULL)],  (1u << 2))
+#define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST()  SEGGER_SYSVIEW_OnTaskStopReady((U32)prvGetTCBFromHandle(NULL)],  (1u << 2))
 #define traceMOVED_TASK_TO_SUSPENDED_LIST(pxTCB)    SEGGER_SYSVIEW_OnTaskStopReady((U32)pxTCB,         ((3u << 3) | 3))
 
 #define traceISR_EXIT_TO_SCHEDULER()                SEGGER_SYSVIEW_RecordExitISRToScheduler()
 #define traceISR_EXIT()                             SEGGER_SYSVIEW_RecordExitISR()
 #define traceISR_ENTER(_n_)                         SEGGER_SYSVIEW_RecordEnterISR(_n_)
 
-#endif // CONFIG_FREERTOS_SMP
-
 /*********************************************************************
 *
 *       API functions

+ 12 - 0
components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/FreeRTOSConfig_smp.h

@@ -250,6 +250,18 @@ Default values for trace macros added by ESP-IDF and are not part of Vanilla Fre
     #define traceISR_ENTER(_n_)
 #endif
 
+#ifndef traceQUEUE_GIVE_FROM_ISR
+    #define traceQUEUE_GIVE_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_GIVE_FROM_ISR_FAILED
+    #define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEMAPHORE_RECEIVE
+    #define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue )
+#endif
+
 /* ------------------------------------------------ IDF Compatibility --------------------------------------------------
  * - We need these in order for ESP-IDF to compile
  * ------------------------------------------------------------------------------------------------------------------ */

+ 10 - 1
components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c

@@ -107,7 +107,16 @@ void vPortSetStackWatchpoint(void *pxStackStart)
 
 BaseType_t xPortSysTickHandler(void);
 
-#if CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
+#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
+
+#ifdef CONFIG_FREERTOS_CORETIMER_0
+    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
+#endif
+#ifdef CONFIG_FREERTOS_CORETIMER_1
+    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
+#endif
+
+#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
 
 _Static_assert(SOC_CPU_CORES_NUM <= SOC_SYSTIMER_ALARM_NUM - 1, "the number of cores must match the number of core alarms in SYSTIMER");
 

+ 12 - 0
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/FreeRTOSConfig_smp.h

@@ -282,6 +282,18 @@ Default values for trace macros added by ESP-IDF and are not part of Vanilla Fre
     #define traceISR_ENTER(_n_)
 #endif
 
+#ifndef traceQUEUE_GIVE_FROM_ISR
+    #define traceQUEUE_GIVE_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_GIVE_FROM_ISR_FAILED
+    #define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEMAPHORE_RECEIVE
+    #define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue )
+#endif
+
 /* ------------------------------------------------ IDF Compatibility --------------------------------------------------
  * - We need these in order for ESP-IDF to compile
  * ------------------------------------------------------------------------------------------------------------------ */

+ 7 - 0
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c

@@ -174,6 +174,13 @@ BaseType_t xPortSysTickHandler(void);
 extern void _frxt_tick_timer_init(void);
 extern void _xt_tick_divisor_init(void);
 
+#ifdef CONFIG_FREERTOS_CORETIMER_0
+    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
+#endif
+#ifdef CONFIG_FREERTOS_CORETIMER_1
+    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
+#endif
+
 /**
  * @brief Initialize CCONT timer to generate the tick interrupt
  *

+ 9 - 4
components/freertos/FreeRTOS-Kernel-SMP/queue.c

@@ -1202,7 +1202,9 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
         {
             const int8_t cTxLock = pxQueue->cTxLock;
 
-            traceQUEUE_SEND_FROM_ISR( pxQueue );
+#ifdef ESP_PLATFORM // IDF-5384
+            traceQUEUE_GIVE_FROM_ISR( pxQueue );
+#endif
 
             /* A task can only have an inherited priority if it is a mutex
              * holder - and if there is a mutex holder then the mutex cannot be
@@ -1309,7 +1311,9 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
         }
         else
         {
-            traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
+#ifdef ESP_PLATFORM // IDF-5384
+            traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue );
+#endif
             xReturn = errQUEUE_FULL;
         }
     }
@@ -1502,8 +1506,9 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
              * must be the highest priority task wanting to access the queue. */
             if( uxSemaphoreCount > ( UBaseType_t ) 0 )
             {
-                traceQUEUE_RECEIVE( pxQueue );
-
+#ifdef ESP_PLATFORM
+                traceQUEUE_SEMAPHORE_RECEIVE( pxQueue );
+#endif
                 /* Semaphores are queues with a data size of zero and where the
                  * messages waiting is the semaphore's count.  Reduce the count. */
                 pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;