Skip to content

Commit

Permalink
Merge branch 'feature/freertos_smp_sysview' into 'master'
Browse files Browse the repository at this point in the history
sysview: Adds FreeRTOS SMP port

Closes IDF-4995

See merge request espressif/esp-idf!18615
  • Loading branch information
dobairoland committed Aug 29, 2022
2 parents 84acc58 + e5085db commit 1a006cb
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 72 deletions.
12 changes: 10 additions & 2 deletions components/app_trace/sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
91 changes: 26 additions & 65 deletions components/app_trace/sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,63 +212,27 @@ Revision: $Rev: 3734 $
#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))
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
* ------------------------------------------------------------------------------------------------------------------ */
Expand Down
11 changes: 10 additions & 1 deletion components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
* ------------------------------------------------------------------------------------------------------------------ */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
13 changes: 9 additions & 4 deletions components/freertos/FreeRTOS-Kernel-SMP/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1a006cb

Please sign in to comment.