【发布时间】:2018-04-28 18:18:17
【问题描述】:
当我调用 vTaskDelay 时,延迟持续了预期时间的一半。我已经追溯了这个问题,我发现 Tick 速率值是 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 时,滴答频率是正确的,所以我想我在某处为运行操作系统滴答的计时器遗漏了一些配置。
以下是我在不同 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 节拍定时器时钟源配置为以 32kHz 运行的内部超低功耗振荡器 ULPOSC32k 时,节拍率是正确的,与 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);
}
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 )
我非常感谢您对此计时器问题的任何见解,这让我陷入困境。我已经检查了两个与此相关的类似问题:
【问题讨论】:
-
我投票结束这个问题作为题外话,因为:你有调试器 - 是什么阻止你检查定时器 o systick 寄存器值?自己做一些调试。如果你付出一些努力,很容易回答问题。
-
是的,我完全同意。我一直在使用调试器并尽我所能检查定时器和频率变量,我已经尝试了所有不同的组合来改变 CPU 时钟源和频率,以及定时器时钟源。我还检查了滴答和无滴答模式。我已经检查了几天能找到的所有寄存器,但找不到原因,可能我遗漏了一些明显的东西。在尝试了我能想到的一切之后,询问是我最后的手段。如果有任何建议可以继续我的努力,我将不胜感激。
-
你确定你定义的时钟频率对你的硬件是正确的吗?您的处理器似乎能够以 48 MHz 运行,可能使用来自外部时钟的 PLL 乘法器。
-
我想是的,我使用 SYSTEM_CLOCK_SOURCE_OSC16M 通过 GLCK_0 为 CPU 提供时钟,在 SAM L21 中它允许 4、8、12 和 16 MHz 模式。也可以使用 DFLL 或 DPLL 获得 48 MHz。我也尝试过这个 CPU 频率,滴答频率是 2.25 kHz。我已经编辑了问题,添加了一些结果。
标签: timer embedded atmel freertos atmelstudio