Когда я вызываю vTaskDelay, задержка длится половину предполагаемого времени. Я отследил проблему и вижу, что значение Tick rate в два раза больше, чем должно быть, как определено в configTICK_RATE_HZ. Я проверил это с помощью тика, чтобы переключить светодиод и измерить частоту с помощью осциллографа.
Я настраиваю плату Atmel SAM L21 Xplained pro A (ATSAML21J18A) с Atmel Studio 7 и FreeRTOS v8.0.1 на основе файлов примера ASF под названием «Демо FreeRTOS без тиков с использованием OLED1 Xplained».
Тактовая частота моего процессора составляет 12 МГц от SYSTEM_CLOCK_SOURCE_OSC16M. Настроенная тактовая частота составляет 100 Гц от таймера, синхронизируемого от GLCK_O (частота процессора). Однако, когда я изменяю тактовую частоту процессора на 4 МГц вместо 12 МГц, скорость Tick является правильной, поэтому я предполагаю, что мне где-то не хватает какой-то конфигурации для таймера, который запускает тик ОС.
Вот некоторые значения тактовой частоты ОС, которые я получаю при разных тактовых частотах ЦП:
- ЦП: 4 МГц - Тиковая частота: 100 Гц
- ЦП: 8 МГц - Тактовая частота: 548 Гц
- ЦП: 12 МГц - Тактовая частота: 218 Гц
- ЦП: 16 МГц - Тактовая частота: 548 Гц
- ЦП: 48 МГц - Тактовая частота: 2,25 кГц
Кроме того, когда я настраиваю источник тактовой частоты таймера ОС в качестве внутреннего генератора сверхмалого энергопотребления ULPOSC32k, работающего на частоте 32 кГц, тактовая частота является правильной, независимо от тактовой частоты процессора (100 Гц).
Более того, когда я выбираю режим без тиков (1 или 2), даже с конфигурацией, которая хорошо работает в тиковом режиме, с процессором на 4 МГц и прерыванием по тикам, сгенерированным таймером Systick, у меня такая же проблема, длится половина что надо.
В 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 )
Я был бы очень признателен за любое понимание этой проблемы с таймером, которая заставляет меня застрять. Я уже проверял два похожих вопроса по этому поводу: