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 节拍率的一些值:
- 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 滴答定时器时钟源配置为内部超低功耗振荡器 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。
当我调用 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 节拍率的一些值:
- 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 滴答定时器时钟源配置为内部超低功耗振荡器 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。