FreeRTOS Run-time Statistics Error ("RTOS has not been detected")

Hi guys

I want to use FreeRTOS’ run time statistics in MCUXpresso (NXP’s Eclipse-based IDE).
When I pause a debug, I get the following error:

The debugger console provides the following error:
17:09:37.145 ERROR: [VariableReader] Could not read variable expression: “sizeof(pxReadyTasksLists)”.
17:09:37.145 INFO: [FreeRTOS] FreeRTOS has not been detected.

The weirdest part is that the run time statistics has worked a few times with exactly the same source code.
I have followed the FreeRTOS guide on rtos-run-time-stats for the FreeRTOSConfig.h macros, and since it has worked at times, I assume that these are okay.

Does anyone know how I can fix the stability of the FreeRTOS run time statistics?

Thanks in advance!

It seems that the debugger’s mechanism of detecting FreeRTOS is not working. Does it have anything to do with run time stats? In other words, if you disable run time stats, does it work?

Also, please share your FreeRTOSConfig.h.

Thanks.

Hi @aggarg

Thanks for your quick response!
The rest of the debugging functionality works, regardless of whether run time stats is enabled or not.

I will paste my FreeRTOSConfig.h below.
It references functions in my RuntimeStats.c, so I’ll give RuntimeStats.c and .h as well.

FreeRTOSConfig.h:

/*
FreeRTOS Kernel V10.3.0
Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 http://aws.amazon.com/freertos
 http://www.FreeRTOS.org
*/

#include "RunTimeStats.h"

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/

#define configUSE_PREEMPTION                    1
#define configUSE_TICKLESS_IDLE                 0
#define configCPU_CLOCK_HZ                      (SystemCoreClock)
#define configTICK_RATE_HZ                      ((TickType_t)1000) //TODO: Changed from 200 during porting as with what JvM did
#define configMAX_PRIORITIES                    18	//TODO: Changed from 5 during porting as with what JvM did
#define configMINIMAL_STACK_SIZE                ((unsigned short)90)
#define configMAX_TASK_NAME_LEN                 20
#define configUSE_16_BIT_TICKS                  0
#define configIDLE_SHOULD_YIELD                 1
#define configUSE_TASK_NOTIFICATIONS            1
#define configUSE_MUTEXES                       1
#define configUSE_RECURSIVE_MUTEXES             1
#define configUSE_COUNTING_SEMAPHORES           1
#define configUSE_ALTERNATIVE_API               0 /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE               8
#define configUSE_QUEUE_SETS                    0
#define configUSE_TIME_SLICING                  0
#define configUSE_NEWLIB_REENTRANT              0
#define configENABLE_BACKWARD_COMPATIBILITY     0
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5

/* Used memory allocation (heap_x.c) */
#define configFRTOS_MEMORY_SCHEME               4
/* Tasks.c additions (e.g. Thread Aware Debug capability) */
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1

/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION         0
#define configSUPPORT_DYNAMIC_ALLOCATION        1
#define configTOTAL_HEAP_SIZE                   ((size_t)(32 * 1024))	//10
#define configAPPLICATION_ALLOCATED_HEAP        0

/* Hook function related definitions. */
#define configUSE_IDLE_HOOK                     0
#define configUSE_TICK_HOOK                     0
#define configCHECK_FOR_STACK_OVERFLOW          0
#define configUSE_MALLOC_FAILED_HOOK            0
#define configUSE_DAEMON_TASK_STARTUP_HOOK      0

/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 1 // enabled for runtime stats
#define configGENERATE_RUN_TIME_STATS_USE_TICKS 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1

// additional defines for runtime statistics
#if (configGENERATE_RUN_TIME_STATS && !configGENERATE_RUN_TIME_STATS_USE_TICKS)
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() AppConfigureTimerForRuntimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() AppGetRuntimeCounterValueFromISR()
#define configRECORD_STACK_HIGH_ADDRESS 1
#endif

/* Task aware debugging. */
#define configRECORD_STACK_HIGH_ADDRESS         1

/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES                   0
#define configMAX_CO_ROUTINE_PRIORITIES         2

/* Software timer related definitions. */
#define configUSE_TIMERS                        1
#define configTIMER_TASK_PRIORITY               (configMAX_PRIORITIES - 1)
#define configTIMER_QUEUE_LENGTH                10
#define configTIMER_TASK_STACK_DEPTH            (configMINIMAL_STACK_SIZE * 2)

/* Define to trap errors during development. */
#define configASSERT(x) if(( x) == 0) {taskDISABLE_INTERRUPTS(); for (;;);}

/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet                1
#define INCLUDE_uxTaskPriorityGet               1
#define INCLUDE_vTaskDelete                     1
#define INCLUDE_vTaskSuspend                    1
#define INCLUDE_vTaskDelayUntil                 1
#define INCLUDE_vTaskDelay                      1
#define INCLUDE_xTaskGetSchedulerState          1
#define INCLUDE_xTaskGetCurrentTaskHandle       1
#define INCLUDE_uxTaskGetStackHighWaterMark     0
#define INCLUDE_xTaskGetIdleTaskHandle          0
#define INCLUDE_eTaskGetState                   0
#define INCLUDE_xTimerPendFunctionCall          1
#define INCLUDE_xTaskAbortDelay                 0
#define INCLUDE_xTaskGetHandle                  0
#define INCLUDE_xTaskResumeFromISR              1



#if defined(__ICCARM__)||defined(__CC_ARM)||defined(__GNUC__)
    /* in Kinetis SDK, this contains the system core clock frequency */
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif

/* Interrupt nesting behaviour configuration. Cortex-M specific. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4 /* 15 priority levels */
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1U << (configPRIO_BITS)) - 1)

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */

RuntimeStats.h:

#ifndef RUNTIMESTATS_H_
#define RUNTIMESTATS_H_

extern uint32_t Time100us;;


extern void AppConfigureTimerForRuntimeStats(void);
extern uint32_t AppGetRuntimeCounterValueFromISR(void);
extern void GPT2_IRQHandler(void);



#endif /* RUNTIMESTATS_H_ */

RuntimeStats.c:

#include "fsl_gpt.h"

uint32_t Time100us;

uint32_t AppGetRuntimeCounterValueFromISR(void);
uint32_t AppGetRuntimeCounterValueFromISR(void);
void GPT2_IRQHandler(void);

uint32_t McuRTOS_RunTimeCounter; /* runtime counter, used for configGENERATE_RUNTIME_STATS */



void AppConfigureTimerForRuntimeStats(void)
{
	uint32_t gptFreq;
	gpt_config_t gptConfig;

	GPT_GetDefaultConfig(&gptConfig);

	/* Initialize GPT module */
	GPT_Init(GPT2, &gptConfig);

	/* Divide GPT clock source frequency by 3 inside GPT module */
	GPT_SetClockDivider(GPT2, 16);		//TODO: 400/16= 25Mhz like on RT1064. Is this fine
	//GPT_SetClockDivider(GPT2, 3);

	/* Get GPT clock frequency */
	gptFreq = CLOCK_GetFreq(kCLOCK_OscRc400M);		//TODO: What timer should we use??
	//gptFreq = CLOCK_GetFreq(kCLOCK_PerClk);

	/* GPT frequency is divided by 3 inside module */
	gptFreq /= 16;		//TODO: Is devision fine??
	//gptFreq /= 3;

	/* Set GPT module to 10x of the FreeRTOS tick counter */
	gptFreq = USEC_TO_COUNT(100, gptFreq); /* FreeRTOS tick is 1 kHz */
	GPT_SetOutputCompareValue(GPT2, kGPT_OutputCompare_Channel1, gptFreq);

	/* Enable GPT Output Compare1 interrupt */
	GPT_EnableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable);

	/* Enable at the Interrupt and start timer */
	EnableIRQ(GPT2_IRQn);
	GPT_StartTimer(GPT2);
}

uint32_t AppGetRuntimeCounterValueFromISR(void)
{
	return McuRTOS_RunTimeCounter;
}

void GPT2_IRQHandler(void)
{
	/* Clear interrupt flag.*/
	GPT_ClearStatusFlags(GPT2, kGPT_OutputCompare1Flag);
	McuRTOS_RunTimeCounter++; /* increment runtime counter */
	Time100us++;
	__DSB();
}

This seems more like an MCUXpresso issue that thread aware debugging is not working. I’d suggest to ask on NXP forums.

Thanks.

Thanks.
I’ll update this forum if I get a solution there.

For those with the same problem:

  1. Go to Window → Preferences → C/C++ → Debug → GDB
  2. Uncheck the box for “Non-stop mode”

Now it will work each time you debug.
There’s a catch though. You can’t have the “Tasks (FreeRTOS)” tab selected when you start the debug. The tab can be open, but not currently selected, like this:

Thank you for taking time to report back.

1 Like

Update: There are even more nuances to this.
Firstly, one must follow the instructions in my previous reply:

In addition to the above:

  1. The above setting is not always retained by MCUXpresso between system reboots. Remember to check it each time you want to use FreeRTOS Run-time Statistics in this program.

  2. Halting the debug with the “Suspend” or “Suspend All Debug Sessions” buttons (pause-looking icons) does not show the statistics. Instead, halt the debug with a breakpoint, and you will have access to the FreeRTOS Run-time Statistics.

  3. To start your debug, hold shift and click on the ‘debug’ button in the ‘Quickstart panel’ to “force probe re-discovery”. Once your probe shows, make sure that the debugging mode is set to “All-stop” and NOT “Non-stop” mode.