rcc stm32 что это
STM32L– Система тактирования (обзор)
Стоит обратить внимание на ограничение максимальных частот в зависимости от режима работы (напряжения питания ядра):
Пример 1 Как мы уже знаем после сброса в качестве системной тактовой частоты используется внутренний MSI генератор, с частотой по умолчанию 2,097 МГц. Воспользуемся выходом MCO для контроля частоты. Объявим вывод:
Выбор источников сигнала производится установкой соответствующих битов в регистре RCC_CFGR.
К сожалению в заголовочном файле stm32l1xx.h не описаны источники, поэтому опишем их сами (так как пока не используем стандартную библиотеку):
И выберем в качестве источника MSI генератор:
После компиляции и прошивки, на выводе PA8 получил частоту 2,102 МГц.
Попробуем изменить частоту MSI генератора.
Выбор частоты производится установкой соответствующих битов в регистре RCC_ICSCR
Повышаем частоту до 4,194 Мгц:
Компилируем, прошиваем и получаем 4,206 МГц.
Внимание! Так как сейчас после сброса мы “сразу” изменяем частоту генератора MSI, а он по умолчанию используется для системной тактовой частоты, то выбор диапазона 0 или 1 приведет к невозможности программирования мк. Если вы все таки попали в данное положение, то для восстановления работоспособности достаточно вывод Boot0 подключить к Vcc и выполнить сброс мк.
Пример 2
После сброса выключены все генераторы кроме MSI.
Попробуем включить HSI генератор.
Общая процедура такова:
Ожидаем окончания стабилизации работы (ожидание установки бита HSIRDY):
Выводим сигнал на вывод MCO:
После компиляции и прошивки, на выводе PA8 получил частоту 15,91 МГц.
На этом обзорная часть заканчивается.
Ещё раз обращаю внимание, что после сброса в качестве системной тактовой частоты используется внутренний MSI генератор (2,097 МГц).
Исходный код
Примеры базируются на проекте приведенном ранее:
с исправлениями в макросах для работы с линиями ввода-вывода:
STM32 тактирование.
Перед глазами вся система тактирования, что очень удобно и позволяет быстро разобраться какой коэффициент за, что отвечает.
Способ задания частоты системной шины, описанный выше, позволяет отлаживать программу только в железе потому, что при отладке в симуляторе флаг готовности того же HSE или PLL не кому установить.
Почему это я пишу про какие-то флаги?
Потому что на самом деле нет ни какой абракадабры и раскоментировав дефайн с нужной частотой тактирования, мы говорим препроцессору, что он должен включить в программу определенный участок кода. Если раскомментировать строку
#define SYSCLK_FREQ_56MHz 56000000
То препроцессор включит в программу следующий участок кода
Второе ограничение, к которому приводит такая настройка системной частоты — невозможно разогнать контроллер, потому как разгон производится с помощью настройки PLL, но в этом пока, что нужды не было.
PLL – это банальный умножитель, с регулируемым коэффициентом умножения. То есть на его вход можно подать 8MHz, а на выходе получить частоту кратную 8, например 56MHz. Этого понимания достаточно для настройки PLL, хотя надо сказать, что само устройство PLL достаточно интересно и статью по его работе планирую опубликовать тут.
Еще, изменять коэффициенты PLL можно только при выключенном PLL, при запущенном PLL изменять коэффициенты нельзя.
Также хотелось бы отметить, что у МК есть ножка через которую можно тактировать различные устройства или просто посмотреть на какой частоте запустился МК, называется она МСО.
Еще интересной фичей является система защиты от нестабильной работы и отказа генератора HSE, называется она CSS(Clock security system).
CSS способна отслеживать отказ или нестабильную работу генератора HSE, осуществлять автоматическое переключение тактирования на встроенный генератор HSI и вызывать немаскируемые прерывания — NMI (Non-Masked Interrupts). Напомню, что NMI – это прерывания, которые невозможно сбросить, не обработав, то есть их возникновение прерывают выполнение программы независимо от каких-либо условий.
Регистр управления RCC_CR :
PLLRDY(PLL clock ready flag) — флаг готовности PLL, устанавливается аппаратно.
PLLON( PLL enable) — установка единицы в этот бит разрешает работу PLL.
CSSON(Clock security system enable) — установка единицы в этот бит разрешает работу детектора тактового сигнала от HSE.
HSEBYP(External high-speed clock bypass) — установка единицы в этот бит разрешает использование внешнего генератора и возможна лишь когда HSEON сброшен.
HSERDY(External high-speed clock ready flag) — единица в этом бите говорит о том, что внешний генератор стабилизировался.
HSEON(HSE clock enable) — установка единицы в этом бит, позволяет принудительно переключиться на внешний генератор.
HSICAL[7:0](Internal high-speed clock calibration) — эти биты инициализируются при запуске.
HSITRIM[4:0](Internal high-speed clock trimming) — значение этих битов прибавляется к значению HSICAL, таким появляется возможность корректировать частоту МК, которая может «уходить» в зависимости от напряжения питания и температуры окружающей среды. Шаг подстройки между двумя значениями примерно равен 40KHz.
HSIRDY(Internal high-speed clock ready flag) – флаг устанавливается аппаратно когда внутренний RC генератор 8 МГц стабилизировался.
HSION(Internal high-speed clock enable) — установка этого бита в единицу принудительно запускает внутренний RC генератор 8 МГц. Этот бит не может быть сброшен если с помощью HSI, формируется системная частота.
Регистр конфигурации RCC_CFGR:
MCO(Microcontroller clock output) — значение этих битов определяют работу вывода MCO.
USBPRE(USB prescaler) — ноль в этом бите включает предделить с коэффициентом 1.5 для usb.Предделитель должен быть настроен до включения тактирования USB шины.
PLLMUL(PLL multiplication factor) — значение этих битов определяет коэффициент умножения PLL.
PLLXTPRE(HSE divider for PLL entry) — значение этого бита определяет будет ли HSE поделен на два, перед подачей на вход PLL. Устанавливать его нужно при отключенной PLL.
PLLSRC(PLL entry clock source) — значение этого бита определяет с какого источника будет подан сигнал на вход PLL.(0 – источник HSI/2, 1 – источник HSE)
ADCPRE(ADC prescaler) — значение этих битов определяет коэффициент деления тактовой частоты для АЦП.
PPRE2(APB high-speed prescaler (APB2)) — значение этих битов определяет коэффициент деления тактовой частоты для APB2.
PPRE1(APB low-speed prescaler (APB1)) — значение этих битов определяет коэффициент деления тактовой частоты для APB1.
HPRE(AHB prescaler) — значение этих битов определяет коэффициент деления тактовой частоты для AHB.
SWS(System clock switch status) — устанавливается аппаратно, показывая какой источник используется для тактирования системы.
SW(System clock switch) — с помощью этих битов можно выбрать источник для тактирования SYSCLK.
Регистр прерываний RCC_CIR:
CSSC(Clock security system interrupt clear) — установка этого бита в единицу позволяет очистить флаг CSSF.
PLLRDYC(PLL ready interrupt clear) — установка этого бита в единицу позволяет очистить флаг PLLRDYF.
HSERDYC(HSE ready interrupt clear) — установка этого бита в единицу позволяет очистить флаг HSERDYF.
HSIRDYC(HSI ready interrupt clear) — установка этого бита в единицу позволяет очистить флаг HSIRDYF.
LSERDYC(LSE ready interrupt clear) — установка этого бита в единицу позволяет очистить флаг LSERDYF.
LSIRDYC(LSI ready interrupt clear) — установка этого бита в единицу позволяет очистить флаг LSIRDYF
PLLRDYIE(PLL ready interrupt enable) — единица в этом бите разрешает прерывания при сцеплении PLL.
HSERDYIE(HSE ready interrupt enable) — единица в этом бите разрешает прерывания при сцеплении HSE.
HSIRDYIE(HSI ready interrupt enable) — единица в этом бите разрешает прерывания при сцеплении HSI.
LSERDYIE(LSE ready interrupt enable) — единица в этом бите разрешает прерывания при сцеплении LSE.
LSIRDYIE(LSI ready interrupt enable) — единица в этом бите разрешает прерывания при сцеплении LSI.
CSSF(Clock security system interrupt flag) — этот флаг устанавливается аппаратно при отказе HSE, очищается с помощью CSSC.
PLLRDYF(PLL ready interrupt flag) — этот флаг устанавливается аппаратно если произошло сцеплении с PLL и бит PLLRDYDIE установлен..
HSERDYF(HSE ready interrupt flag) — этот флаг устанавливается аппаратно если HSE стабилизировался и бит HSERDYDIE установлен.
HSIRDYF(HSI ready interrupt flag) — этот флаг устанавливается аппаратно если HSI стабилизировался и бит HSIRDYDIE установлен..
LSERDYF(LSE ready interrupt flag) — этот флаг устанавливается аппаратно если LSE стабилизировался и бит LSERDYDIE установлен..
LSIRDYF(LSI ready interrupt flag) — этот флаг устанавливается аппаратно если LSI стабилизировался и бит LSIRDYDIE установлен.
Регистр сброса RCC_APB2RSTR
При записи единицы в биты этого регистра происходит сброс соответствующей периферии, которая тактируется от шины APB2. Под сбросом понимается установка в регистры блока, например USART, значения по умолчанию.
Регистр сброса RCC_APB1RSTR
При записи единицы в биты этого регистра происходит сброс соответствующей периферии, которая тактируется от шины APB1. Под сбросом понимается установка в регистры блока, например USART, значения по умолчанию.
Регистр управления тактированием на шине AHB RCC_AHBENR
При записи единицы в биты этого регистра включается тактирование соответствующей периферии подключенной к шине AHB, при записи нуля отключается.
Регистр управления тактированием на шине APB2 RCC_APB2ENR
При записи единицы в биты этого регистра включается тактирование соответствующей периферии подключенной к шине APB1, при записи нуля отключается.
Регистр управления доменом BKP RCC_BDCR:
BDRST(Backup domain software reset) — установка единицы в этот бит сбрасывает значение битов регистра RCC_BDCR.
RTCEN(RTC clock enable) — установка единицы в этот бит включает тактирование RTC.
RTCSEL[1:0](RTC clock source selection) — значение этих битов определяет источник тактирования RTC.
LSEBYP(External low-speed oscillator bypass) — ставится и очищается программно, чтобы обойти LSE генератор в режиме отладки.
LSERDY(External low-speed oscillator ready) — единица в этом бите говорит о том, что LSE с частотой 32KHz стабилизировался.
LSEON(External low-speed oscillator enable) — установка единицы в этот бит разрешает работу LSE с частотой 32KHz.
Регистр управления/статуса RCC_CSR:
LPWRRSTF(Low-power reset flag) — этот флаг устанавливается аппаратно, когда происходит от контроллера пониженного потребления.
WWDGRSTF(Window watchdog reset flag) — этот флаг устанавливается аппаратно, когда происходит сброс от оконного WatchDog.
IWDGRSTF(Independent watchdog reset flag) — этот флаг устанавливается аппаратно, когда происходит сброс от независимого WatchDog.
SFTRSTF(Software reset flag) — этот флаг устанавливается аппаратно, когда происходит программный сброс.
PORRSTF(POR/PDR reset flag) — этот флаг устанавливается аппаратно при при включение/выключение питания.
PINRSTF(PIN reset flag) — этот флаг устанавливается аппаратно, когда происходит сброс от вывода NRST.
RMVF(Remove reset flag) — установка единицы в этот бит позволяет сбросить все, описанные выше флаги, в этот регистре.
LSIRDY(Internal low-speed oscillator ready) — единица в этом бите говорит о том, что LSI стабилизировался.
LSION(Internal low-speed oscillator enable) — установка единицы в этот бит разрешает работу внутреннего RC генератора 40 kHz.
Электроника для всех
Блог о электронике
ARM. Учебный курс. Тактовый генератор STM32
Нам разум дал стальные руки-крылья,
А вместо сердца — пламенный мотор.
В прошлых статьях, мы научились создавать проекты, настраивать их и даже научились моргать светодидом напрямую и с использованием функций стандартной библиотеки работы с периферией. Все это, конечно, хорошо но хочется чего-то большего… Но прежде чем приступить к более сложным примерам, хотелось бы поговорить об одной очень важной системе микроконтроллера. Речь идет о системе генерации тактовых частот, которая, выражаясь метафорически, является сердцем нашего микроконтроллера. Думаю, ни для кого не секрет, что работа всех остальных систем микроконтроллера зависит от того, получают они тактовые сигналы или нет и какой частоты эти сигналы. Если какие-то блоки не будут получать тактовых сигналов, то они просто не будут работать. Ну, а от частоты этих сигналов зависит скорость работы этих блоков.
В нашей программе управления светодиодом, мы практически не касались вопросов генерации тактовой частоты и микроконтроллер вроде бы работал а программа выполнялась, из сего некоторые могут сделать опрометчивый вывод, что раз работает, так не стоит туда и лезть.
Однако, это не так! Если внимательно посмотреть на ассемблеровский файл начальной низкоуровневой инициализации микроконтроллера (STM32F10x.s/startup_stm32f10x_hd.s или подобный, что присутствует в проекте), то можно увидеть, что перед вызовом функции main() нашей программы, идет вызов CMSIS’овской функции SystemInit():
Заголовок для Keil из поставки STM32
; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
А вот в том файле инициализации, что создает Keil’овский визард проекта при создании нового проекта вызова SystemInit нет!
; Reset Handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main LDR R0, =__main BX R0 ENDP
И его надо вручную дернуть из main. В общем, смотри в оба что там да как 🙂 Я (Di Halt) же предпочитаю вообще выпилить CMSISовский System Init и накатать свой. А то очень уж там все заморочено и заверчено. Тем более есть с чего взять пример 😉
Наш пытливый ум, может посмотреть на исходники функции SystemInit и увидеть, что она в сообществе с дополнительными функциями вида SetSysClock / SetSysClockХХХ как раз и настраивает для нас генераторы тактовых частот. Если мы решили заниматься программированием микроконтроллеров всерьез, то нам не пристало полагаться на какие-то там готовые функции и оставаться в неведении относительно их поведения, поэтому в данной статье я и постараюсь сорвать покровы тайны со столь важной системы нашего микроконтроллера 🙂
Для лучшего усвоения информации приведу структурную схему системы формирования тактовых частот, из документации на микроконтроллер (раздел reset and clock control (RCC)).
Как можно увидеть из данной схемы, практически все блоки микроконтроллера затактовываются от линии SYSCLK, что расшифровывается как System Clock (в моем вольном переводе это будет звучать как системная тактовая частота). Исключение составляют блоки USB, RTC и IWDG. Т.к. системная тактовая частота очень важна, то разберемся сначала с ее генерацией.
Как следует из документации и схемы, источниками для системной тактовой частоты могут служить 3 генератора:
На самом деле, IMHO, более правильно сказать, что источниками могут быть только HSI и HSE частота которых может умножаться а может и нет.
Разберемся с ними поподробнее.
Встроенный RC генератор (HSI)
Встроенный в микропроцессор генератор HSI вырабатывает тактовую частоту 8 МГц. Генератор автоматически запускается при появлении питания Vcc и при выходе в нормальный режим работы выставляет флаг HSIRDY в регистре RCC_CR. Первоначально процессорное ядро запускается на тактовой частоте HSI.
К преимуществам относится быстрое время начала генерации тактовой частоты после подачи питания и отсутствие необходимости в использовании дополнительных электронных компонентов для работы микроконтроллера.
Недостаток – низкая стабильность частоты генерируемого сигнала, а при умножении на PLL погрешность тоже умножается. Например, частота HSI при разных температурных условиях плавает от 7.3 до 8.7МГц. При множителе в 9 на выходе будет разброс уже от 65.7 до 78.3 МГЦ.
Производитель гарантирует стабильность частоты в 1% при температуре ядра 25C, для чего в процессе производства в регистр RCC_CR записываются биты HSICAL[7:0], отвечающие за его калибровку. Если этого недостаточно или необходимо откалибровать микроконтроллер для работы при другой температуре, то можно воспользоваться битами HSITRIM[4:0] этого же регистра. После ресета там находится число 16, т.е. середина диапазона регулировки.
Изменение одного младшего бита дает подстройку приблизительно в 40кГц. Тактовая частота с генератора HSI может подаваться на прямую как источник системной частоты, либо поступать в блок умножителя частоты предварительно деленная на 2.
Генератор HSI может быть включен/выключен управлением бита HSION регистра RCC_CR.
Внешний генератор (HSE)
В качестве внешнего генератора могут выступать:
Внешний генератор HSE по умолчанию выключен и его включение/выключение управляется битом HSEON регистра RCC_CR. После включения HSE и его выхода в рабочий режим устанавливается бит HSERDY кроме этого, может быть сгенерировано прерывание. Также как и сигнал с генератора HSI, сигнал HSE может быть подан напрямую в качестве системного тактового сигнала либо поступать в блок умножения. Но в отличие от HSI в блок умножения он может поступать напрямую, либо пройдя через делитель на 2.
PLL
Внутренний умножитель частоты может умножать вошедший тактовый сигнал с одного из трех источников, на выбор
на множитель от 2-х до 16-ти. По умолчанию умножитель выключен и его включение/выключение управляется битом PLLON регистра RCC_CR. После включения PLL и его выхода в рабочий режим устанавливается бит PLLRDY кроме этого, может быть сгенерировано прерывание.
Работа умножителя конфигурируется через регистр RCC_CFGR.
Все манипуляции над его режимами работы должны проводиться только при выключенном PLL!
С источниками системной тактовой частоты вроде разобрались. Теперь, прежде чем пройти дальше, куда там эта частота подается, отойдем немного в сторону и посмотрим, что у нас есть еще… 🙂
А есть у нас во первых блок USB. Особенностью его является то, что работать он может только на частоте 48МГц! Если частота будет отличной от 48МГц, то другие устройства на шине USB нас не поймут а мы их. Из схемы видно две вещи:
Из этого следует, что если нам нужна работа USB, то обязательно должен работать PLL и его выходная тактовая частота должна быть либо 48 (при делителе USB = 1) либо 72 (при делителе USB = 1.5) МГц! И все! Больше никаких вариантов.
Во вторых, есть у нас еще RTC (Real Time Clock – часы реального времени). Что такое часы реального времени, думаю знают все. Они могут работать, от батарейного питания, при выключенном микроконтроллере. Источником тактовой частоты для них могут являться:
Ну и в третьих, есть еще IWDG (Independent Watchdog – независимая сторожевая собака 🙂 Что это такое в данной статье вдаваться не будем). IWDG тактуется сугубо от LSI описанном чуть выше.
Ну вроде все, теперь можно перейти и к остальным блокам, которые тактуются от системной частоты SYSCLK.
Так же на схеме подписаны максимальные допустимые частоты для блоков. Все делители имеющие управляемые коэффициенты могут быть настроены, что в целом позволяет довольно гибко варьировать частоты отдельных блоков в различных пределах.
Кроме того, на схеме это не показано, очень важно знать и помнить 2 вещи:
Т.е., если нужна работа какого-то блока: GPIO, DMA, ADC, DAC, таймеров и т.д., то не забываем подавать на них тактовые сигналы, т.е. устанавливать соответствующие биты! Иначе работать ничего не будет!
Зачем же нужно такое разнообразие делителей, умножителей, источников синхронизации и т.д? А нужно это все для гибкой и точной настройки микроконтроллера под задачу, которую ему предстоит решать в том или ином проекте. Если не нужны какие-то блоки, то просто отключаем их от источников синхронизации, нечего им энергию потреблять вхолостую (что по умолчанию и сделано). Если не требуется в проекте высокая производительность, то можно сконфигурировать микроконтроллер на работу на частоте, например, 48, 36, 24 и т.д. МГц, что опять же понизит его энергопотребление и т.д.
Алгоритм ручной настройки частоты
Таким образом, микроконтроллер сохранит свою работоспособность, пусть и на пониженной и менее стабильной частоте, и проинформирует выполняющуюся программу об этом. А теперь представьте, что бы было, если бы этот микроконтроллер стоял в какой-то критически важной системе и просто бы остановился при проблеме с кварцем.
Ну и для того, чтобы эта прелесть заработала ее надо включить программно через установку бита CSSON регистра RCC_CR. По умолчанию он сброшен.
Код
Теперь, собственно, вернемся к коду настройки генераторов.
Вот как это сделано в CMSIS для STM32:
Сразу оговоримся, что это справедливо только для простой линейки STM32 для Connectivity Line все чуток по другому. Но очень похоже.
(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); /* Включаем PLL */ RCC->CR |= RCC_CR_PLLON; /* Ожидаем, пока PLL выставит бит готовности */ while((RCC->CR & RCC_CR_PLLRDY) == 0) < // Ждем >/* Выбираем PLL как источник системной частоты */ RCC->CFGR &= (uint32_t)((uint32_t)
В CMSIS@STM32 в файле system_stm32f10x.c есть штука вида:
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) /* #define SYSCLK_FREQ_HSE HSE_Value */ #define SYSCLK_FREQ_24MHz 24000000 #else /* #define SYSCLK_FREQ_HSE HSE_Value */ /* #define SYSCLK_FREQ_24MHz 24000000 */ /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */ #define SYSCLK_FREQ_72MHz 72000000 #endif
Как видишь, тут уже готовые макросы для разных частот. Остается только раскомментировать нужную строку.
Надо заметить, что CMSIS для STM32 имеет все макроопределения заточенны под кварц на 8МГц. Под другой кварц уже не покатит — придется пересчитывать заново все делители.
Пример
Скреативим программку, которая будет моргать диодиком и на ходу менять значения умножителя PLL каждые десять миганий. Также там будет активирована защита от сбоев тактового генератора. Сбить с копыт кварцевый генератор несложно, достаточно наслюнявить палец и коснуться обоих выводов кварца 🙂 Ну или, например, припаять проводочки к нему и коротнуть его выводы на резистор в 100ом.
Вот как она работает:
Ну вот, собственно и все, о чем мы хотели рассказать в данной статье. Если что-то упустили, или будут вопросы – пишите в комменты!
З.Ы.
На последок, хотел еще чуть чуть затронуть такую тему как «разгон» или работа на повышенных частотах. Была у меня одна задача, когда надо было получать и обрабатывать данные по одной достаточно высокоскоростной параллельной шине (порядка 40МГц). Так вот «родной» частоты в 72МГц не хватало для нормальной работы, что и не удивительно. И тогда я решил разогнать немного микроконтроллер. В общем, мой опыт показал, что частоту в 144МГц (т.е. в 2 раза. больше стандартной) они переваривают легко. Проверял на 3-х имеющихся в наличии контроллерах STM32F103RB, STM32F103RE и STM32F103VE. Все 3 работают стабильно, не греются. Частоту в 160МГц, уже не переваривают… Зависают через 10-15 секунд работы, но при этом также не греются. Для сравнения, имеющийся в наличии NXP LPC1768 с «родной» частотой 100МГц на 120 уже не завелся вообще.
Я никого ни к чему не призываю, это просто хинт, может быть кому-то когда-то будет полезен, как и мне в свое время… Ну и в даташите черным по белому написано НЕ ПРЕВЫШАЙТЕ максимально допустимых производителем частот работы блоков. Все, что выше — на ваш страх и риск, без гарантий и т.д. и т.п… Ну да на заборе тоже вон чего написано, а на самом деле там дрова 😀
Основной автор статьи — Владимир aka RtxOnAir
Редактирование и всякие дополнения уточнения — DI HALT
Спасибо. Вы потрясающие! Всего за месяц мы собрали нужную сумму в 500000 на хоккейную коробку для детского дома Аистенок. Из которых 125000+ было от вас, читателей EasyElectronics. Были даже переводы на 25000+ и просто поток платежей на 251 рубль. Это невероятно круто. Сейчас идет заключение договора и подготовка к строительству!
А я встрял на три года, как минимум, ежемесячной пахоты над статьями :)))))))))))) Спасибо вам за такой мощный пинок.