Тактирование микроконтроллеров Atmel SAMD20/21

Немного теории


9c6b68a020d64579992828fdcaa2a323.png
Согласно документации на микроконтроллеры Atmel серии SAMD20/21 система тактирования состоит из следующих блоков:

  • блок источников сигнала (управляется SYSCTRL)
    • Clock source — это базовая частота в системе. Это может быть, например, внутренний осциллятор 8 МГц (OSC8M), внешний осциллятор (XOSC), блок цифровой фазовой автоподстройки частоты (DFLL48M);
  • базовый контроллер тактовой частоты (GLCK-generic clock controller), который управляет системой распределения тактовых сигналов и состоит из:
    • базовых генераторов частоты (Generic Clock Generator) — это программируемый предделитель, к которому может быть подключен любой источник сигнала. С выхода генератора 0 (GCLKGEN[0], GCLK_MAIN) сигнал идет на блок управления питанием (Power manager), который генерирует главный тактовый сигнал;
    • базовые тактовые сигналы (Generic Clocks) — обычно это сигналы, которые тактируют периферию. Базовые тактовые сигналы, с помощью базовых мультиплексоров сигнала могут использовать любой из доступных в системе тактовых сигналов. Разные периферийные блоки могут использовать разные тактовые сигналы. Выход мультиплексора 0 используется как источник опорного сигнала для блока цифровой фазовой автоподстройки частоты. Обратите внимание, что в таком случае выход с DFLL не должен использоваться как опорный сигнал для генератора, выход которого используется как опорный для мультиплексора 0.
  • блок управления питанием (PM — Power manager)
    • блок управления питанием управляет синхронным тактированием системы. Это включает в себя CPU, шины (APB, AHB) и синхронную (с точки зрения CPU) периферию. Он содержит маски тактирования, с помощью которых можно включать и выключать пользовательский интерфейс периферии, а также делители для тактовых сигналов CPU, шин.


Периферия может тактироваться одновременно 2 тактовыми сигналами:

  • синхронным от Power Manager (обеспечивает работу периферии с CPU посредством APB/AHB шины);
  • асинхронным от GCLK (обеспечивает работу «ядра» периферии).


Синхронизация между двумя этими тактовыми сигналами реализована аппаратно. И даже если частоты и источники сигналов одинаковы, все равно происходит синхронизация.
Все регистры, тактирующиеся той же частотой и источником, что и шины, не требуют синхронизации. Все регистры «ядра» требуют синхронизации при записи, а некоторые и при чтении.
Процесс синхронизации индицируется битом SYNCBUSY в регистре статуса или по прерыванию.
Таким образом, в теории для настройки тактовых сигналов нужно:

  1. Выбрать базовый источник (или несколько) опорного тактового сигнала: это может быть внешний осциллятор, внутренний и т.д. (блок SYSCTRL)
  2. Настроить предделитель и мультиплексор для каждого из базовых сигналов (блок GCLK).
  3. Выбрать основной тактовый сигнал (выход с генератора 0).
  4. Настроить тактирование периферии (generic clocks).


Для корректной работы с тактовыми сигналами необходимо заглянуть в электрические характеристики в конце даташита, так как там много интересного. В частности:

  • опорный тактовый сигнал для DFLL может быть:
    • минимальное значение: 0.732 кГц
    • типичное значение: 32.768 кГц
    • максимальное значение: 35.1 кГц
  • выходной сигнал DFLL: от 47 до 49 МГц
  • внешний генератор должен быть: не более 32 МГц.


Как устроен код в ASF


Не будем вдаваться в подробности всей библиотеки, об этом можно прочитать в статье про ASF. Рассмотрим лишь то, что касается тактирования. При создании проекта в Atmel Studio создается файл main.c, который уже содержит system_init ().
Прототип этой функции расположен в файле src/asf/sam0/system/system.c:

/**
 * \brief Initialize system.
 *
 * This function will call the various initialization functions within the
 * system namespace. If a given optional system module is not available, the
 * associated call will effectively be a NOP (No Operation).
 *
 * Currently the following initialization functions are supported:
 *  - System clock initialization (via the SYSTEM CLOCK sub-module)
 *  - Board hardware initialization (via the Board module)
 *  - Event system driver initialization (via the EVSYS module)
 *  - External Interrupt driver initialization (via the EXTINT module)
 */
void system_init(void)
{
        /* Configure GCLK and clock sources according to conf_clocks.h */
        system_clock_init();

        /* Initialize board hardware */
        system_board_init();

        /* Initialize EVSYS hardware */
        _system_events_init();

        /* Initialize External hardware */
        _system_extint_init();
}


Нас интересует system_clock_init (), который, в свою очередь, определен в clock.c.
Вообще код этой функции сделан полностью на дефайнах из asf/config/conf_clocks.h. Поэтому сильно можно не разбираться, скорее просто ради интереса посмотреть.
А вот вся настройка происходит в conf_clocks.h в соответствии с планом, приведенным выше.

Практика


Рассмотрим все на примере. Предположим, у нас есть плата с МК SAM20/21, который тактируется от внешнего кварца 7,3728 МГц, а системную тактовую мы хотим получить 48 МГц.
Мы должны все настроить так, как показано оранжевыми стрелками на рисунке ниже:
f97d303ac0374834bedbb1b4dc13496c.png

Т.е. базовый генератор 1 должен на входе иметь тактовый сигнал от внешнего кварца, который должен быть поделен до приемлемой для DFLL частоты (от 0,7 до 35 кГц). Должен быть разрешен DFLL, выбран соответствующий опорный сигнал для него и коэффициент умножения, чтобы получить на выходе что-то близкое к 48 МГц. Выход DFLL должен быть заведен на базовый генератор 0.
Расчет коэффициентов деления и умножения.
Для того, чтобы получить приемлемый опорный тактовый сигнал для DFLL, сигнал с внешнего осциллятора нужно сильно поделить:
7,3728МГц/256=28,8 кГц
А коэффициент умножения для DFLL определяется исходя из входной (опорной частоты) и желаемой частоты на выходе:
28,8×1666=47,980800 МГц
Теперь рассмотрим, как это сделать в conf_clocks.h.
Разрешаем тактирование от внешнего источника и указываем его параметры:

// SYSTEM_CLOCK_SOURCE_XOSC configuration - External clock/oscillator 
#  define CONF_CLOCK_XOSC_ENABLE                  true
#  define CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL        SYSTEM_CLOCK_EXTERNAL_CRYSTAL
#  define CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY      7372800UL
#  define CONF_CLOCK_XOSC_STARTUP_TIME            SYSTEM_XOSC_STARTUP_32768
#  define CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL       true
#  define CONF_CLOCK_XOSC_ON_DEMAND               true
#  define CONF_CLOCK_XOSC_RUN_IN_STANDBY          false


Разрешаем работу DFLL:

// SYSTEM_CLOCK_SOURCE_DFLL configuration - Digital Frequency Locked Loop 
#  define CONF_CLOCK_DFLL_ENABLE                  true
#  define CONF_CLOCK_DFLL_LOOP_MODE               SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED
#  define CONF_CLOCK_DFLL_ON_DEMAND               false


Настраиваем DFFL (источник опорной частоты и коэффициент умножения):

// DFLL closed loop mode configuration 
#  define CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR   GCLK_GENERATOR_1
#  define CONF_CLOCK_DFLL_MULTIPLY_FACTOR         1666
#  define CONF_CLOCK_DFLL_QUICK_LOCK              true
#  define CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK   true
#  define CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP     true
#  define CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE      true
#  define CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE    (0x1f / 4)
#  define CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE      (0xff / 4)


Настраиваем генераторы 0 и 1 (разрешаем работы, выбираем опорную частоту):

// Set this to true to configure the GCLK when running clocks_init. If set to
// false, none of the GCLK generators will be configured in clocks_init(). 
#  define CONF_CLOCK_CONFIGURE_GCLK               true

// Configure GCLK generator 0 (Main Clock) 
#  define CONF_CLOCK_GCLK_0_ENABLE                true
#  define CONF_CLOCK_GCLK_0_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_0_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_DFLL
#  define CONF_CLOCK_GCLK_0_PRESCALER             1
#  define CONF_CLOCK_GCLK_0_OUTPUT_ENABLE         false

// Configure GCLK generator 1 
#  define CONF_CLOCK_GCLK_1_ENABLE                true
#  define CONF_CLOCK_GCLK_1_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_1_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_XOSC
#  define CONF_CLOCK_GCLK_1_PRESCALER             256
#  define CONF_CLOCK_GCLK_1_OUTPUT_ENABLE         false


Акция
Для самых внимательных рады сообщить, что компания Rainbow возобновляет акцию по бесплатному распространению микроконтроллеров ATSAMD20G16A-AU для радиолюбителей (и не только):
  1. Образцы предоставляются бесплатно при условии самовывоза из московского офиса Rainbow
  2. Предоставляются по 2 микроконтроллера в одни руки
  3. Для участия в акции необходимо на электронный адрес gav@rtcs.ru направить заявку на получение образцов с указанием краткой информации о себе и предполагаемом применении микроконтроллеров (ФИО и контактные данные, 3–5 предложений описания проекта)
  4. Участникам акции предлагается спец. цена на оценочную плату серии SAM D20 со встроенным отладчиком ATSAMD20-XPRO — 1000 рублей (количество плат ограничено)

После получения и обработки заявки, мы свяжемся с Вами и объясним где и когда забрать образцы (СВАО).


Готово!

© Geektimes