Alvaro Muro
Alvaro Muro

Reputation: 57

FreeRTOS timer Tick too fast in SAM L21 Xplained Pro

When I call vTaskDelay, the delay lasts half of the supposed time. I have traced back the problem and I see that the Tick rate value is the double of what it should be as defined in configTICK_RATE_HZ. I checked this using the tick hook to toggle a led and measuring the frequency with an oscilloscope.

I am configuring the Atmel SAM L21 Xplained pro A board (ATSAML21J18A), with Atmel Studio 7 and FreeRTOS v8.0.1, based on the files of an ASF example called "FreeRTOS tickless demo using OLED1 Xplained".

My CPU clock runs at 12MHz from the SYSTEM_CLOCK_SOURCE_OSC16M. The configured tick rate is 100 Hz, from a timer clocked from GLCK_O(CPU clock). However, when I change the CPU clock rate at 4MHz instead 12 MHz, the Tick rate is correct, so I guess I'm missing some configuration somewhere for the timer which runs the OS tick.

Here are some values of OS tick rate I get with different CPU clock rates:

Also, when I configure the OS tick timer clock source as the internal ultra low power oscilator ULPOSC32k running at 32kHz, the tick rate is correct, independently of the CPU clock frequency (100Hz).

Moreover, when I select tickless mode (1 or 2), even with the configuration that works well in tick mode, with the CPU at 4MHz and the tick interrupt generated from the Systick timer, I have the same problem, the dalay lasts half of what it should.

In FreeRTOSConfig I have:

#define configUSE_PREEMPTION                    1
#define configUSE_TICKLESS_IDLE                 0
#define configUSE_IDLE_HOOK                     0
#define configUSE_TICK_HOOK                     1
#define configPRIO_BITS                         2
#define configCPU_CLOCK_HZ                      ( system_gclk_gen_get_hz(GCLK_GENERATOR_0) )
#define configTICK_RATE_HZ                      ( ( portTickType ) 100 )

The tick timer configuration is:

void vPortSetupTimerInterrupt(void)
{
    // Struct for configuring TC
    struct tc_config tcconf;
    // Set up configuration values
    tc_get_config_defaults(&tcconf);
    tcconf.clock_source    = GCLK_GENERATOR_0;
    tcconf.counter_size    = TC_COUNTER_SIZE_32BIT;
    tcconf.run_in_standby  = true;
    tcconf.clock_prescaler = TC_CLOCK_PRESCALER_DIV1;
    tcconf.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;

    // Initialize the TC
    tc_init(&tc, TICK_TC, &tcconf);

    // Register and enable callback for freeRTOS tick handler
    tc_register_callback(&tc, (tc_callback_t) xPortSysTickHandler, TC_CALLBACK_CC_CHANNEL0);
    tc_enable_callback(&tc, TC_CALLBACK_CC_CHANNEL0);

    // Set top value equal to one os tick
    tc_set_top_value(&tc, TIMER_RELOAD_VALUE_ONE_TICK);

    // Enable the timer
    tc_enable(&tc);
}

where TIMER_RELOAD_VALUE_ONE_TICK comes from:

//! Frequency of timer
#define TIMER_HZ                            ( configCPU_CLOCK_HZ )

//! Value per os tick of timer
#define TIMER_RELOAD_VALUE_ONE_TICK         ( TIMER_HZ / configTICK_RATE_HZ )

//!  Maximum value of timer
#define TIMER_MAX_COUNT                     ( 0xffffffff )

//! Maximum possible suppressed ticks with timer
#define TIMER_MAX_POSSIBLE_SUPPRESSED_TICKS ( TIMER_MAX_COUNT / TIMER_RELOAD_VALUE_ONE_TICK )

I would appreciate very much any insight on this timer issue, which keeps me stuck. I have already checked two similar questions related to this:

STM32 SysTick counting twice as fast as it should

freertos tick factor 2 too fast on stm32f4xx

Upvotes: 2

Views: 724

Answers (2)

Scott Schmitt
Scott Schmitt

Reputation: 26

The saml21 has 5 timer/counters TC0 - TC4. The count registers are 16bit. You can use TC0 and TC1(or TC2 and TC3) together to make it 32bit. TC4, the only timer in PDO, does not have another timer paired with it. It can't be used as a 32bit timer(though it will allow you to try).

Change TIMER_MAX_COUNT to 0xffff and tcconf.counter_size to TC_COUNTER_SIZE_16BIT and you will be able to use TC4 instead of TC2.

Upvotes: 1

Alvaro Muro
Alvaro Muro

Reputation: 57

Changing the Timer instance from TC4 to TC2 solves the issue.

  // Initialize the TC
    tc_init(&tc, TICK_TC, &tcconf);

  //! Timer/Counter instance to use as tick timer
  //#define TICK_TC TC4
  #define TICK_TC TC2

Now it generates a correct 100 Hz tick independently of the CPU clock frequency configured.

However, I still have to see the implications this will have when I activate the low power modes, as it seems the TC4 is the only timer active in Power Domain 0 (PD0)(the lowest power domain).

Upvotes: 0

Related Questions