Timer 在SAM L21 Explained Pro中,FreeRTOS定时器滴答过快

Timer 在SAM L21 Explained Pro中,FreeRTOS定时器滴答过快,timer,embedded,atmel,freertos,atmelstudio,Timer,Embedded,Atmel,Freertos,Atmelstudio,当我打电话给vTaskDelay时,延迟持续了预期时间的一半。我已经追踪到了问题所在,我发现Tick rate值是configTICK\u rate\u HZ中定义的值的两倍。我使用勾号钩切换led并用示波器测量频率来检查这一点 我正在配置Atmel SAM L21 Explained pro A板(ATSAML21J18A),使用Atmel Studio 7和FreeRTOS v8.0.1,基于名为“FreeRTOS tickless demo using OLED1 Explained”的A

当我打电话给vTaskDelay时,延迟持续了预期时间的一半。我已经追踪到了问题所在,我发现Tick rate值是configTICK\u rate\u HZ中定义的值的两倍。我使用勾号钩切换led并用示波器测量频率来检查这一点

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

我的CPU时钟从系统时钟源OSC16M以12MHz的频率运行。从GLCK_O(CPU时钟)计时的计时器中,配置的滴答频率为100 Hz。然而,当我将CPU时钟频率改为4MHz而不是12MHz时,滴答声频率是正确的,因此我想我缺少运行OS滴答声的计时器的某些配置

以下是我在不同CPU时钟频率下得到的一些操作系统时钟频率值:

  • CPU:4 MHz-滴答频率:100 Hz
  • CPU:8 MHz-滴答频率:548 Hz
  • CPU:12 MHz-滴答频率:218 Hz
  • CPU:16 MHz-滴答频率:548 Hz
  • CPU:48 MHz-滴答频率:2,25 kHz
此外,当我将OS tick timer时钟源配置为以32kHz运行的内部超低功率振荡器ULPOSC32k时,tick速率是正确的,与CPU时钟频率(100Hz)无关

此外,当我选择无滴答模式(1或2)时,即使配置在滴答模式下运行良好,CPU频率为4MHz,并且由Systick定时器生成滴答中断,我也会遇到同样的问题,dalay的持续时间是它应该持续的一半

在FreeRTOSConfig中,我有:

#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);
}
其中计时器\u重新加载\u值\u一个\u勾号来自:

//! 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 )
我将非常感谢任何关于这个计时器问题的见解,这让我陷入困境。我已经检查了与此相关的两个类似问题:


将计时器实例从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个定时器/计数器TC0-TC4。计数寄存器为16位。您可以同时使用TC0和TC1(或TC2和TC3)使其成为32位。PDO中唯一的计时器TC4没有与之配对的另一个计时器。它不能用作32位计时器(尽管它允许您尝试)


将TIMER\u MAX\u COUNT更改为0xffff,将tcconf.counter\u size更改为TC\u counter\u size\u 16位,您将能够使用TC4而不是TC2。

我投票将此问题作为主题外的问题来结束,因为:您有调试器-是什么阻止您检查计时器和系统寄存器的值?自己调试一下。若你们付出一些努力,回答这个问题很容易。是的,我完全同意。我一直在使用调试器,并尽我所能检查计时器和频率变量,我已经尝试了所有不同的组合来更改CPU时钟源和频率,以及计时器时钟源。我还检查了滴答声和滴答声模式。我已经查了好几天我能找到的所有记录,但我找不到原因,可能我遗漏了一些明显的东西。在尝试了我所能想到的一切之后,问是我最后的选择。如果您能给我一些建议,我将不胜感激。您确定您的时钟频率定义适合您的硬件吗?您的处理器似乎能够运行48 MHz,可能使用外部时钟的PLL乘法器。我想是的,我使用SYSTEM_clock_SOURCE_OSC16;通过GLCK_0为CPU计时,在SAM L21中,它允许4、8、12和16 MHz模式。使用DFLL或DPLL也可以获得48 MHz。我也尝试过这个CPU频率,滴答频率是2,25千赫。我编辑了问题,添加了一些结果。