FreeRTOS 计时器在 SAM L21 Xplained Pro 中计时太快

FreeRTOS timer Tick too fast in SAM L21 Xplained Pro

当我调用 vTaskDelay 时,延迟持续了预期时间的一半。我追溯了这个问题,发现 Tick rate 值是 configTICK_RATE_HZ 中定义的值的两倍。我使用勾选钩来切换 LED 并使用示波器测量频率来检查这个。

我正在使用 Atmel Studio 7 和 FreeRTOS v8.0.1 配置 Atmel SAM L21 Xplained pro A 板 (ATSAML21J18A),基于名为 "FreeRTOS tickless demo using OLED1 Xplained" 的 ASF 示例的文件。

我的 CPU 时钟运行在 SYSTEM_CLOCK_SOURCE_OSC16M 的 12MHz。配置的节拍率为 100 Hz,来自从 GLCK_O(CPU 时钟计时的计时器)。但是,当我将 CPU 时钟速率更改为 4MHz 而不是 12MHz 时,滴答速率是正确的,所以我想我在运行 OS 滴答的计时器的某处缺少一些配置。

以下是我在不同 CPU 时钟频率下得到的 OS 节拍率的一些值:

此外,当我将 OS 滴答定时器时钟源配置为内部超低功耗振荡器 ULPOSC32k 运行 时,滴答速率是正确的,独立于CPU 时钟频率 (100Hz)。

此外,当我 select 无滴答模式(1 或 2)时,即使配置在滴答模式下运行良好,CPU 在 4MHz 并且滴答中断从 Systick 生成计时器,我有同样的问题,延迟持续了一半。

在 FreeRT 中OS配置我有:

#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 )

滴答计时器配置为:

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);
}

其中 TIMER_RELOAD_VALUE_ONE_TICK 来自:

//! 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 )

我将非常感谢任何关于此计时器问题的见解,这让我陷入困境。我已经检查了两个与此相关的类似问题:

STM32 SysTick counting twice as fast as it should

freertos tick factor 2 too fast on stm32f4xx

将 Timer 实例从 TC4 更改为 TC2 可以解决问题。

  // 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

现在它会独立于配置的 CPU 时钟频率生成正确的 100 Hz 节拍。

然而,当我激活低功耗模式时,我仍然需要看看这会产生什么影响,因为 TC4 似乎是 Power Domain 0 中唯一活动的定时器 (PD0)(最低功率域)。

saml21 有 5 个 timer/counters TC0 - TC4。计数寄存器为 16 位。您可以同时使用 TC0 和 TC1(或 TC2 和 TC3)使其成为 32 位。 TC4 是 PDO 中唯一的定时器,没有与之配对的另一个定时器。它不能用作 32 位定时器(尽管它允许您尝试)。

将 TIMER_MAX_COUNT 更改为 0xffff,将 tcconf.counter_size 更改为 TC_COUNTER_SIZE_16BIT,您将能够使用 TC4 而不是 TC2。