Таймер FreeRTOS Тикает слишком быстро в SAM L21 Xplained Pro

Когда я вызываю 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 )

Я был бы очень признателен за любое понимание этой проблемы с таймером, которая заставляет меня застрять. Я уже проверял два похожих вопроса по этому поводу:

STM32 SysTick считает вдвое быстрее, чем следовало бы

коэффициент тика 2 freertos слишком велик на stm32f4xx


person Alvaro Muro    schedule 15.11.2017    source источник
comment
Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что: У вас есть отладчик - что мешает вам проверять таймер или значения регистров systick? Проведите небольшую отладку самостоятельно. На вопрос легко ответить, если приложить немного усилий.   -  person 0___________    schedule 15.11.2017
comment
Да, полностью согласен. Я использовал отладчик и проверял переменные таймера и частоты в меру своих возможностей, я уже пробовал все различные комбинации, изменяя источник и частоту процессора, а также источник тактовой частоты таймера. Еще я проверил в тиковом и тиковом режиме. Я просмотрел все регистры, которые смог найти в течение нескольких дней, и не могу найти причину, возможно, я упускаю что-то очевидное. Спрашивать - это мое последнее средство после того, как я испробовал все, что мог придумать. Буду признателен за любой совет, чтобы продолжить мои усилия.   -  person Alvaro Muro    schedule 16.11.2017
comment
Вы уверены, что ваша тактовая частота соответствует вашему оборудованию? Ваш процессор, похоже, способен работать на частоте 48 МГц, вероятно, с использованием умножителя ФАПЧ от внешних часов.   -  person Chris Stratton    schedule 17.11.2017
comment
Думаю, да, я использую SYSTEM_CLOCK_SOURCE_OSC16M для синхронизации процессора через GLCK_0, а в SAM L21 он позволяет работать в режимах 4, 8, 12 и 16 МГц. Также возможно получить 48 МГц с DFLL или DPLL. Я тоже пробовал с этой частотой процессора, и тактовая частота составляет 2,25 кГц. Я отредактировал вопрос, добавив некоторые результаты.   -  person Alvaro Muro    schedule 17.11.2017


Ответы (2)


Saml21 имеет 5 таймеров / счетчиков TC0 - TC4. Регистры счета 16-битные. Вы можете использовать TC0 и TC1 (или TC2 и TC3) вместе, чтобы сделать его 32-битным. TC4, единственный таймер в PDO, не имеет другого связанного с ним таймера. Его нельзя использовать в качестве 32-битного таймера (хотя это позволит вам попробовать).

Измените TIMER_MAX_COUNT на 0xffff и tcconf.counter_size на TC_COUNTER_SIZE_16BIT, и вы сможете использовать TC4 вместо TC2.

person Scott Schmitt    schedule 25.05.2018

Изменение экземпляра таймера с 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

Теперь он генерирует правильный тик 100 Гц независимо от настроенной тактовой частоты процессора.

Однако мне все еще нужно увидеть последствия, которые это будет иметь, когда я активирую режимы низкого энергопотребления, поскольку кажется, что TC4 - единственный таймер, активный в области мощности 0 (PD0) (область самой низкой мощности).

person Alvaro Muro    schedule 17.11.2017