1
votes

Firstly, I'm building on the Giant Gecko EFM32 using SiLabs IDE and want to track my task usage via vTaskGetRunTimeStats(). So firstly, I use the STK3700_freertos_tickless which has two tasks - one of which I add:

static char cBuffer[ 512 ];
vTaskGetRunTimeStats( cBuffer );

To my FreeRTOSConfig.h:

#define configUSE_TRACE_FACILITY                  ( 1 )
#define configGENERATE_RUN_TIME_STATS             ( 1 )
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()  ( ulHighFrequencyTimerTicks = 0UL )
#define configUSE_STATS_FORMATTING_FUNCTIONS      ( 1 )
#define portGET_RUN_TIME_COUNTER_VALUE()          ulHighFrequencyTimerTicks

Now, firstly - I removed:

volatile unsigned long ulHighFrequencyTimerTicks;

And moved it to tasks.c as I was getting:

./FreeRTOS/efm32gg/tasks.o: In function vTaskStartScheduler': C:\Users\Chris\SimplicityStudio\v3_workspace\STK3700_freertos_tickless\GNU ARM v4.8.3 - Debug/../FreeRTOS/efm32gg/tasks.c:1532: undefined reference to ulHighFrequencyTimerTicks' ./FreeRTOS/efm32gg/tasks.o: In function uxTaskGetSystemState': C:\Users\Chris\SimplicityStudio\v3_workspace\STK3700_freertos_tickless\GNU ARM v4.8.3 - Debug/../FreeRTOS/efm32gg/tasks.c:1815: undefined reference to ulHighFrequencyTimerTicks' ./FreeRTOS/efm32gg/tasks.o: In function vTaskSwitchContext': C:\Users\Chris\SimplicityStudio\v3_workspace\STK3700_freertos_tickless\GNU ARM v4.8.3 - Debug/../FreeRTOS/efm32gg/tasks.c:2173: undefined reference to ulHighFrequencyTimerTicks' collect2.exe: error: ld returned 1 exit status make: *** [STK3700_freertos_tickless.axf] Error 1

If I put it in tasks.c to remove the error, then my demo gets stuck in

void vPortFree( void *pv )
{
    /* Memory cannot be freed using this scheme.  See heap_2.c, heap_3.c and
    heap_4.c for alternative implementations, and the memory management pages of
    http://www.FreeRTOS.org for more information. */
    ( void ) pv;

    /* Force an assert as it is invalid to call this function. */
    configASSERT( pv == NULL );
}

Increasing my heap does nothing to help. I know I should resolve the first error, but there putting it as an extern in FreeRTOSConfig.h isn't working.

Which setting is missing? Is it valid to move the high tick def to tasks.c?

Thanks in advance, Chris

UPDATE 1:

Added functions in the FreeRTOSconfig.h:

/* Run time stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS             ( 1 )
extern volatile unsigned long ulHighFrequencyTimerTicks;
extern void vConfigureTimerForRunTimeStats( void );
extern unsigned long vGetTimerForRunTimeStats( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()    vConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE()            vGetTimerForRunTimeStats()

And main.c respectively:

void vConfigureTimerForRunTimeStats( void ) {
    CMU->HFRCOCTRL = 0x8;                           // Set High Freq. RC Osc. to 1 MHz
    CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_TIMER3;     // Enable clock for Timer3
    TIMER3->CNT = 0x0;
    TIMER3->CTRL = ( TIMER3->CTRL & ~_TIMER_CTRL_PRESC_MASK) | TIMER_CTRL_PRESC_DIV1024; // Prescaler needed to reduce resolution, 1024
    TIMER3->CMD = 0x1;                              // Start Timer3
}

unsigned long vGetTimerForRunTimeStats( void ) {
    return ( TIMER3->CNT );
}

All compiles fine and my vTaskGetRunTimeStats is called in the following function, based on the STK3700_freertos_tickless example code:

static void LcdPrint(void *pParameters)
{
  pParameters = pParameters;   /* to quiet warnings */
  static char sBuffer[ 240 ]; // 40 B per task

  for (;;)
  {
    /* Wait for semaphore, then display next number */
   if (pdTRUE == xSemaphoreTake(sem, portMAX_DELAY)) {  
    SegmentLCD_Write(text);
    }

   vTaskGetRunTimeStats( ( char * ) sBuffer );

  }
}

But now my error is an undefined reference:

Finished building: ../src/main.c Building target: STK3700_freertos_tickless.axf Invoking: GNU ARM C Linker arm-none-eabi-gcc -g -gdwarf-2 -mcpu=cortex-m3 -mthumb -T "STK3700_freertos_tickless.ld" -Xlinker --gc-sections -Xlinker -Map="STK3700_freertos_tickless.map" --specs=nano.specs -o STK3700_freertos_tickless.axf "./src/low_power_tick_management.o" "./src/main.o" "./emlib/em_assert.o" "./emlib/em_burtc.o" "./emlib/em_cmu.o" "./emlib/em_emu.o" "./emlib/em_gpio.o" "./emlib/em_int.o" "./emlib/em_lcd.o" "./emlib/em_rmu.o" "./emlib/em_rtc.o" "./emlib/em_system.o" "./FreeRTOS/efm32gg/croutine.o" "./FreeRTOS/efm32gg/heap_1.o" "./FreeRTOS/efm32gg/list.o" "./FreeRTOS/efm32gg/port_gcc.o" "./FreeRTOS/efm32gg/queue.o" "./FreeRTOS/efm32gg/tasks.o" "./FreeRTOS/efm32gg/timers.o" "./Drivers/segmentlcd.o" "./Drivers/sleep.o" "./CMSIS/efm32gg/startup_gcc_efm32gg.o" "./CMSIS/efm32gg/system_efm32gg.o" "./BSP/bsp_trace.o" -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group ./src/main.o: In function LcdPrint': C:\Users\Chris\SimplicityStudio\v3_workspace\STK3700_freertos_tickless\GNU ARM v4.8.3 - Debug/../src/main.c:61: undefined reference to vTaskGetRunTimeStats' collect2.exe: error: ld returned 1 exit status make: *** [STK3700_freertos_tickless.axf] Error 1

I have #include "FreeRTOSConfig.h" #include "FreeRTOS.h" and #include "task.h" in my main.c file. Task.h contains: void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION;

Any last ideas? Almost there! C

UPDATE 2:

forget update 1, the code works - a project clean did the trick.

But now it really is a heap_1.c issue being stuck in assertEFM function.

file    "../FreeRTOS/efm32gg/heap_1.c"  
line    153 

I'll try increasing the stack + using the smaller sprintf code too. Best, C

1
How would a linker error be related to the heap size?? "Is not working" is not a specific error description. Also provide what you actually want to achieve and a minimal reproducible example.too honest for this site
Not sure, but portGET_RUN_TIME_COUNTER_VALUE() looks like expecting a function. This also sounds reasonable.too honest for this site
Comments well received Olaf on the problem definition- there are indeed two issues rolled into one here.The ulHighFrequencyTimerTicks is usually defined in freertosconfig.h - and I moved it to tasks.c. I've seen a lot of places where many of these routines are / are not expecting functions and I was trying to avoid it! I'll add the routines which return the values which will be in scope of the main.c and tasks.c. I'll let you know how I get on! Thanks, Cchris
Last piece of the puzzle from an undefined reference. Code all written for the timer. Please see new update and explanation. Best, Cchris
Got it going! Just need to optimise the timer resolution a bit more. Best, Chris "LcdPrint 342 28% IDLE 18 1% Count 11 <1% Tmr Svc 897 74% "chris

1 Answers

1
votes

I think there are several things mixed up here.

First, I don't know where ulHighFrequencyTimerTicks is normally defined or incremented, it is not a FreeRTOS variable so assume it is part of the application. That would make sense as run-time-stats require a clock provided by the application (as the clock is dependent on the available hardware). In any case, it is just a variable, so the normal C scope rules apply. I expect it will be declared and incremented in one file, but then defining portGET_RUN_TIME_COUNTER_VALUE() to reference it means you are trying to reference it from a separate file - hence the linker error. That can be fixed by leaving the variable where it was, and declaring it as extern just in the file that is trying to use it out of scope. Or, implement a 'get' function in the file that declares ulHighFrequenyTimerTicks that just returns the variable's value, and define portGET_RUN_TIME_COUNTER_VALUE() to call the function.

(To answer the other comment portGET_RUN_TIME_COUNTER_VALUE() just needs to evaluate to a value, which can be a function return value, or a direct reference to a variable: http://www.freertos.org/rtos-run-time-stats.html)

Next, configUSE_STATS_FORMATTING_FUNCTIONS does not need to be 1 to use vTaskGetRunTimeState(). It only needs to be 1 if you want to use one of the helper functions that will format the collected stats into a human readable table. http://www.freertos.org/a00110.html#configUSE_STATS_FORMATTING_FUNCTIONS

Then, as already mentioned, getting stuck in vPortFree() is not related to a linker issue. I assume you are getting stuck in the configASSERT()? If so, then you are trying to free a block of memory that was not first allocated by calling pvPortMalloc(), or you are trying to free a block of memory that has been corrupted, or you are trying to free the same block of memory twice.