Май 292012
 

Для данной серии максимально возможная системная тактовая частота SYSCLK равна 32 МГц. Достичь такого значения можно только при выборе PLL источником тактирования. Далее будет описан порядок конфигурации PLL для работы микроконтроллера “на пределе”.  А заодно задействуем внешний вывод на отладочной плате STM32L-DISCOVERY для наблюдения за результатом.

Системную тактовую частоту и сигналы генераторов можно увидеть на выводе MCO, для микроконтроллера платы STM32L-DISCOVERY это вывод PA8. На него можно вывести следующие сигналы:

  • SYSCLK – системная тактовая частота
  • HSI – внутренний генератор на 16 МГц
  • MSI – внутренний генератор на 2.097 МГц (это значение по умолчанию, вообще этот генератор можно настроить на несколько фиксированных частот)
  • HSE – внешний генератор (кварц)
  • PLL – внутренний генератор (можно настраивать в широком диапазоне значений, имеет собственные делитель и умножитель частоты, в качестве источника входного сигнала у него могут быть HSI или HSE)
  • LSI – внутренний генератор на 37 кГц (приблизительная величина)
  • LSE – внешний генератор на 32.768 кГц (кварц)

Сигналы всех этих генераторов, а также системную частоту SYSCLK, для контроля поочередно подключим на вывод MCO. За исключением генератора HSE, поскольку этот внешний кварцевый резонатор на STM32L-DISCOVERY не установлен.

Проект создан в IAR EWARM версии 6.30. Порядок создания проекта я описывал ранее, поэтому сразу перейдем к рассмотрению кода программы, а в конце статьи будет ссылка для загрузки готового проекта.

Вначале подключаем внешний файл stm32l1xx.h, в нем заданы готовые битовые маски для модификации регистров микроконтроллера.

#include "stm32l1xx.h"


Далее сразу переходим в основную функцию main(), все настройки будут в ее теле, отдельных функций я не создавал. Сразу же включим все возможные генераторы – источники тактирования. Тут рассмотрим процедуру включения каждого из генераторов по отдельности, поскольку не каждый из них можно включить одной командой. В первую очередь включаем внутренний генератор на 16 МГц – HSI. Далее ждем установки бита HSIRDY, что говорит о стабилизации генератора и готовности к использованию.

RCC->CR |= RCC_CR_HSION; 
while(!(RCC->CR&RCC_CR_HSIRDY));

Теперь включим генераторы LSI (37 кГц – внутренний) и LSE (внешний, с кварцем на 32.768 кГц). А вот тут уже не все так просто. Внутренний LSI включается также одной командой, а вот для запуска внешнего LSE надо выполнить еще кое-какие действия. Вот что написано в документации:

The LSEON, LSEBYP, RTCSEL and RTCEN bits in the RCC control and status register

(RCC_CSR) are in the RTC domain. As these bits are write protected after reset, the DBP

bit in the Power control register (PWR_CR) has to be set to be able to modify them.

Это значит, что для установки бита LSEON (включение генератора LSE) в регистре RCC_CR нужно разрешить доступ к домену RTC (real time clock – часы реального времени). Делается это установкой разрешающего бита DBP  регистра PWR_CR. А это уже в секции, отвечающей за режимы энергопотребления. А еще вначале нужно тактировать этот модуль (POWER). Выполним эти действия, затем включим генераторы (биты LSEON, LSION регистра RCC_CR)  и дождемся их работоспособности, проверяя установку бит готовности LSERDY и LSIRDY.

RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_DBP; 
RCC->CSR |= RCC_CSR_LSEON; 
while(!(RCC->CSR & RCC_CSR_LSERDY)); 
RCC->CSR |= RCC_CSR_LSION; 
while(!(RCC->CSR & RCC_CSR_LSIRDY));

Теперь займемся настройкой PLL.

Вначале выберем для PLL источник входного сигнала – это будет HSI (16 МГц).

RCC->CFGR |= RCC_CFGR_PLLSRC_HSI;


Далее настроим делитель и множитель PLL. Делить входную частоту будем на 2, а умножать на 4. В итоге должно получиться 32 МГц на выходе PLL.

RCC->CFGR |= RCC_CFGR_PLLMUL4; 
RCC->CFGR |= RCC_CFGR_PLLDIV2;


Запускаем источник PLL и, как положено ждем его стабилизации.

RCC->CR |= RCC_CR_PLLON; 
while(!(RCC->CR&RCC_CR_PLLRDY));

Теперь все возможные источники (кроме HSE, по причине отсутствия кварца) запущены. Пока еще системная тактовая частота SYSCLK формируется от внутреннего источника MSI = 2.097 МГц, как задано по умолчанию. Нам же нужно перейти на PLL. Выбор источника производится в регистре RCC_CFGR. Все тут довольно просто, до некоторого предела. Пока значение частоты не превысило 16 МГц. А если это произошло, то будете наблюдать “зависший” МК (а “зависнет” он в прямом смысле – чтение флэш-памяти, а соответственно и выполнение кода программы станет невозможным!!!). Но заявлено ведь, что максимальная тактовая частота может быть равна 32 МГц?! Тут снова придется перелопатить документацию (иногда восхищаешься тем, как понятно и кратко в ней все расписано, но иногда пара нужных строк находится в совсем другом разделе!), чтобы наткнуться на решение проблемы в теме, описывающей работу с модулем флэш-памяти. Вот как там изложена процедура перехода на более высокую рабочую частоту (настройка производится через регистр FLASH_ACR):

  • Включить режим чтения 64-битных слов – бит ACC64.
  • Задать время ожидания доступа к флэш-памяти равное одному периоду тактовой частоты – бит LATENCY
  • Если необходимо, настроить выборку с упреждением – бит PRFTEN (я не использовал)
FLASH->ACR |= FLASH_ACR_ACC64; 
FLASH->ACR |= FLASH_ACR_LATENCY;


Далее выбираем PLL в качестве источника системной тактовой частоты:

RCC->CFGR |= RCC_CFGR_SW_PLL;


Для проверки выведем сигнал на внешний выход MCO. Для этого надо настроить вывод порта PA8. В следующих строках выполняются процедуры настройки нужного вывода:

RCC->AHBENR |= RCC_AHBENR_GPIOAEN; 
GPIOA->MODER |= GPIO_MODER_MODER8_1; 
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_8; 
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR8; 
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8; 
GPIOA->AFR[1] &= ~GPIO_AFRH_AFRH8; 
RCC->CFGR &= ~RCC_CFGR_MCOPRE;

Опишу по их по порядку следования:

  • Разрешаем тактирование порта А
  • Вывод 8 этого порта настраиваем в режим работы с альтернативной функцией
  • Режим Push-Pull
  • Подтягивающие резисторы отключены
  • Скорость вывода в порт максимальная – 40 МГц
  • Для данного вывода выбрана альтернативная функция AF0 – выход MCO
  • На выходе MCO возможно использование предварительного делителя. Оставляем выходную частоту без изменений — MCO is divided by 1

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

//RCC->CFGR |= RCC_CFGR_MCO_MSI; 
//RCC->CFGR |= RCC_CFGR_MCO_HSI; 
//RCC->CFGR |= RCC_CFGR_MCO_LSI; 
//RCC->CFGR |= RCC_CFGR_MCO_LSE; 
//RCC->CFGR |= RCC_CFGR_MCO_PLL; 
RCC->CFGR |= RCC_CFGR_MCO_SYSCLK;

Естественно, это может быть только один из сигналов, поэтому закомментированы все строки, кроме одной. В данный момент на выводе MCO (PA8) можно наблюдать системную тактовую частоту SYSCLK, которая имеет максимально возможное значение – 32 МГц. Чтобы понаблюдать другие сигналы, надо убрать символы комментария у нужной строки. Далее приведены осциллограммы сигналов, снятые на этом выводе.

MSI

mco_msi

LSI

mco_lsi

LSE

mco_lse

HSI

mco_hsi

PLL

mco_pll

Ну и, наконец, максимально возможная системная тактовая частота SYSCLK при работе от источника PLL

SYSCLK

mco_sysclk_pll_source

По ссылке можно загрузить архив с проектом:

Maximum SYSCLK and MCO output

Другие статьи:

  20 Responses to “STM32L. Максимальная тактовая частота от источника PLL.”

  1. Я тоже получил на выходе 32 МГц! Дал жару своему осилографу…
    А вот если у меня камень на 150МГц заработает (ну, например, STM32F407), то там тоже можно будет наблюдать?

    • Не могу точно сказать возможно ли на выходе получить 150 МГц для данного чипа, поскольку сам этого не пробовал делать. Способны ли GPIO работать на такой частоте, от какой матрицы шин они тактируются, все это надо читать в мануалах на данное семейство и пробовать экспериментально.

  2. Великолепная статья. Наглядно показывает принципы формирования источников синхронизации. Также видно, что на вывод MCO выводится сигнал вне зависимости от того, чем тактируется внутреннее ядро.

  3. Запускаю пример. На выводе PA8 32МГц.
    Комментирую строчку «Далее выбираем PLL в качестве источника системной тактовой частоты:
    RCC->CFGR |= RCC_CFGR_SW_PLL;» .Также 32МГц.
    Меняю коэфициенты PLL : RCC->CFGR |= RCC_CFGR_PLLMUL3;
    RCC->CFGR |= RCC_CFGR_PLLDIV2;
    Ни один ни другой сигнал не меняется:
    RCC->CFGR |= RCC_CFGR_MCO_PLL;
    RCC->CFGR |= RCC_CFGR_MCO_SYSCLK; Все те же 32МГц.
    Выбрал источником HSE 8МГц — ничего.
    В чем причина?

  4. Проверил, все работает.
    Похоже, что у тебя прошивка не обновляется в чипе. Чем прошиваешь после изменений в программе? Не st-link utility случайно?
    И источник HSE 8 MHz на этой плате будет работать, только если установить внешний кварц, на плате его нет.

  5. MSI,HSI,LSI,LSE прошивается и меняется. на плате есть внешний кварц. две нижние строчки PLL, SYSCLK все время 32МГц и не меняются при изменении коэффициента PLL.

  6. Странно. Я сегодня пробовал, все меняется. Пробовал изменять коэффициенты PLL на такие:
    RCC->CFGR |= RCC_CFGR_PLLMUL3;
    RCC->CFGR |= RCC_CFGR_PLLDIV2;
    и тоже вижу изменения частоты осциллографом.
    Можешь скинуть мне проект с изменениями на почту?
    Ящик mailbox@chipspace.ru

  7. проект ваш целиком без добавок. скину. IAR 6.50.2. еще вопрос: мой проект с лцд + вход i2c датчика с моим кодом при изменении частоты тактирования от разных источников, частота i2c не меняется. В коде есть функция задержки с пустыми операциями и все.
    Вывод PA8 подключен для наблюдения частоты осциллографом. меняется все кроме коэффициента PLL, а скорость программы не меняется.Что за чертовщина?

    • Получил архив, завтра погляжу осциллографом выход, отвечу вечером. Сразу глянул файл main.c, а почему внешний источник HSE выбирается для PLL
      RCC->CFGR |= RCC_CFGR_PLLSRC_HSE;
      но при этом источник HSE заранее не включен? Вот так
      RCC->CR |= RCC_CR_HSEON;
      while(!(RCC->CR&RCC_CR_HSERDY));

  8. загрузил в iar Ваш проект без вмешательства. PLL не меняется…

    • Вчера программу проверял в Keil, проблем не выявил.
      Скачал последнюю версию IAR 6.50.2. На работе активировать лицензию не удалось, не работал интернет.
      Нашел и установил «крякнутую» версию 6.30.

      Загружаю свой проект с сайта, запускаю в IAR 6.30 — все работает.
      Теперь запускаю проект, который был прислан по почте. При запуске появляются такие сообщения:
      «Broken options were detected in the project file. A backup copy will be made»
      «The project ‘mco_output’ contains the unknown tool ‘IJET_ID’
      Также в проекте «потерялись» пути к библиотечным файлам в настройках компилятора. Добавил.

      Затем при компиляции вываливает кучу сообщений, наподобие такого:
      «Diagnostics: ‘Settings ST-LINK’: unsupported version…»
      LOAD: Configuretion ‘Debug’ in the project ‘mco_output’ contains broken options for tool ‘C-SPY’:
      The format of this file is not supported by this version of the workbench. It appears to have been written by a newer version of the workbench.

      Запускаю проект, на выходе вижу 32 МГц. Источником для PLL выбрал HSI, поскольку на моей плате нет внешнего кварца.
      Пробую менять настройки, на выходе все равно 32 МГц, без изменений. Получается, что проект нормально не компилируется. Тот .hex файл, который был в проекте изначально, прошивается в контроллер и остается неизменным. Хотя визуально в программе этого не видно, вроде как бы все работает без ошибок. При этом проект, загруженный с сайта работает нормально.

      Наладили интернет. Сношу IAR 6.30, устанавливаю последнюю версию IAR 6.50.2, регистрирую лицензию Kickstart Edition.
      Снова поочередно проверяю оба проекта, оба работают. В настройках компилятора пути к файлам присутствуют сразу, никуда не теряются.
      В общем, я бы посоветовал переустановить IAR для начала. Надеюсь стояла версия Kickstart edition, а не «крякнутая»? Перед этим удалить все папки от предыдущей установки в Program Files, Common Files. Получить лицензию на эту версию, зарегистрировать ее.
      Почему в итоге так «испортился» проект, точно сказать не могу.

  9. Поставил на вин7 IAR 6.50.2 с лицензией 30 дней. Ваш проект и PLL не меняется. Вынул кварц из панели и чудо свершилось — при изменениии коэфициентов PLL частота меняется. Так а в чем дело то — внешний кварц ведь не включен?

  10. Сложно сказать. На моей плате проект работает без внешнего кварца.

  11. Открываем reference manual и находим раздел 4.1.5 Dynamic voltage scaling management. В нём есть таблица и график, исходя из которых для стабильной работы на частоте свыше 16МГц необходимо выбрать voltage range 1 (Vcore = 1.8V). Также, можно открыть system_stm32l1xx.c и найти функцию SetSysClock. Эта функция пытается настроить SYSCLK на HSE (по-умолчанию 8МГц) через PLL (*4) на нашу искомую 32МГц. В случае с STM32L-Discovery настройка не происходит, так как кварц отсутствует, но код настройки мы там посмотреть можем. В этом коде присутствует настройка flash аналогично той, что в статье, запуск HSE, настройки PLL, но также там есть следующие строки:

    /* Power enable */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;

    /* Select the Voltage Range 1 (1.8 V) */
    PWR->CR = PWR_CR_VOS_0;

    /* Wait Until the Voltage Regulator is ready */
    while((PWR->CSR & PWR_CSR_VOSF) != RESET)
    {
    }

    Собственно, желательно добавить эту настройку в статью. Не зря производитель рекомендации даёт. Чип и на voltage range 2 работает на цастоте 32МГц, но в каких-то условиях можно схлопотать неуловимые глюки, с которыми можно долго воевать не понимая, откуда ноги растут.

    • Честно сказать, я вроде на этом момент совсем и не обратил внимания. Сейчас заглянул в документацию, вроде бы типовое значение напряжения Vcore как раз и находится в range 1 и равно 1,8V, так? Но на всякий случай это надо учитывать, так что спасибо за уточнение!

      • По-умолчанию выставляется range 2. Можно удостовериться в reference manual в разделе 4.4.1 PWR power control register (PWR_CR), значение после ресета 0x00001000, значение битов VOS[12:11] — 10: 1.5 V (range 2). Приходится ручками менять на range 1 (VOS 01).

        • Еще раз спасибо. Даже не думал, что оно так по умолчанию.

          • Я тоже не думал, пока в мануале на табличку не наткнулся. Посмотрел на своей платке — действительно во втором режиме после старта. У меня, как и у большинства, и во втором работает, но фиг его знает где и как оно может взбрыкнуть, так что теперь выставляю первый, на всякий пожарный.

            Удач.