72 МГц от кварца и SysTick
После сброса STM32F103 работает от внутреннего RC-генератора на 8 МГц. Чтобы получить 72 МГц, нужно запустить кварц, настроить PLL, добавить такты ожидания флеш-памяти, ограничить шину APB1 и только потом переключить системную частоту. А для точных задержек заведём системный таймер ядра SysTick.
Обновлено Редакция GAW
STM32 с нуляурок 4 из 835 мин
Цель урока: Перевести STM32F103 на 72 МГц от кварца 8 МГц в правильном порядке и получить отсчёт миллисекунд от SysTick для функции delay_ms.
Частоты внутри STM32F103 расходятся по дереву тактирования (рисунок 8 RM0008): источник SYSCLK — HSI, HSE или PLL, — затем делитель AHB даёт HCLK для ядра, памяти и DMA, а делители APB1 и APB2 — частоты двух шин периферии. Общая идея дерева описана в статье глоссария «Дерево тактирования», а все варианты делителей для любого STM32 подберёт калькулятор тактирования STM32. Здесь — один конкретный путь до 72 МГц и почему шаги идут именно в таком порядке.
Что должно получиться
| Сигнал | Откуда | Частота | Предел (RM0008, разд. 7.2) |
|---|---|---|---|
| HSE | кварц Blue Pill | 8 МГц | 4–16 МГц для кварца (DS5319, табл. 22) |
| PLL | HSE × 9 | 72 МГц | 72 МГц (RCC_CFGR, поле PLLMUL) |
| SYSCLK, HCLK | PLL, AHB /1 | 72 МГц | 72 МГц |
| PCLK2 (APB2) | HCLK /1 | 72 МГц | 72 МГц |
| PCLK1 (APB1) | HCLK /2 | 36 МГц | 36 МГц |
| таймеры TIM2–TIM4 | PCLK1 × 2 | 72 МГц | — |
| ADCCLK | PCLK2 /6 | 12 МГц | 14 МГц (разд. 11.1) |
Последняя строка понадобится в уроке 8, а строка с таймерами — в уроке 7: если делитель APB не равен 1, таймеры на этой шине получают удвоенную частоту шины (разд. 7.2, с. 94).
Шаг за шагом
1. Запустить HSE. Бит HSEON регистра RCC_CR включает генератор, флаг HSERDY аппаратура ставит, когда колебания установились (разд. 7.2.1 и 7.3.1). По таблице 22 DS5319 типичное время запуска — 2 мс, но оно сильно зависит от кварца. Если кварц не запустился — оторван, не тот номинал, — бесконечное ожидание повесит программу, поэтому ждём с ограничением.
2. Такты ожидания флеш-памяти. Флеш-память не успевает выдавать команды на 72 МГц, и ядру нужны паузы. Поле LATENCY регистра FLASH_ACR (разд. 3.3.3, с. 60): 000 — до 24 МГц, 001 — от 24 до 48 МГц, 010 — от 48 до 72 МГц. Устанавливать его нужно до повышения частоты: на 8 МГц лишние такты ожидания безопасны, а на 72 МГц их нехватка — нет. Буфер предвыборки (PRFTBE) после сброса уже включён — значение FLASH_ACR при сбросе 0x0000 0030 — а включать и выключать его RM0008 разрешает только при SYSCLK ниже 24 МГц и без делителя AHB, так что трогать его можно только сейчас, пока мы на HSI. Сколько тактов нужно другим сериям, покажет калькулятор тактов ожидания STM32.
Здесь есть ловушка CMSIS. Макросы FLASH_ACR_LATENCY_0, _1 и _2 в stm32f103xb.h — это биты поля: 0x1, 0x2 и 0x4. Запись FLASH_ACR_LATENCY_2 даёт LATENCY = 100, а не «два такта»; два такта — это FLASH_ACR_LATENCY_1. Чтобы не путаться, пишем число со сдвигом: 2u << FLASH_ACR_LATENCY_Pos.
3. Делители и PLL. Поля RCC_CFGR (разд. 7.3.2, с. 101–103): PLLSRC = 1 — вход PLL от HSE, PLLXTPRE = 0 — без деления HSE на 2, PLLMUL = 0111 — умножение на 9, HPRE = 0 — AHB без деления, PPRE2 = 0 — APB2 без деления, PPRE1 = 100 — APB1 делится на 2, ADCPRE = 10 — АЦП получает PCLK2/6. Поля PLL можно менять, только пока PLL выключен (разд. 7.2.3), — после сброса так и есть.
4. Включить PLL битом PLLON и дождаться захвата частоты — флага PLLRDY.
5. Переключить SYSCLK. Поле SW = 10 выбирает PLL. Переключение происходит, только когда новый источник готов (разд. 7.2.6, с. 97), поэтому ждём, пока поле состояния SWS тоже станет 10.
clock.c и clock.h
Этот модуль пригодится во всех следующих уроках. Функция возвращает получившуюся частоту HCLK: 72 МГц или 8 МГц, если кварц не запустился.
/* clock.h */
#ifndef CLOCK_H
#define CLOCK_H
#include <stdint.h>
extern volatile uint32_t g_ticks; /* milliseconds since systick_init() */
uint32_t clock_init(void); /* returns HCLK in Hz */
void systick_init(uint32_t hclk_hz); /* 1 ms SysTick interrupt */
void delay_ms(uint32_t ms);
#endif
/* clock.c: SYSCLK = 72 MHz from the 8 MHz crystal, SysTick 1 ms */
#include "stm32f1xx.h"
#include "clock.h"
volatile uint32_t g_ticks;
uint32_t clock_init(void)
{
/* 1. Start HSE; give up after at least 62.5 ms (one cycle per try at 8 MHz) */
RCC->CR |= RCC_CR_HSEON;
for (uint32_t tries = 0; !(RCC->CR & RCC_CR_HSERDY); tries++) {
if (tries > 500000u) {
RCC->CR &= ~RCC_CR_HSEON;
return 8000000u; /* stay on HSI 8 MHz */
}
}
/* 2. Two wait states for 48 < SYSCLK <= 72 MHz, prefetch buffer on */
FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY)
| (2u << FLASH_ACR_LATENCY_Pos) | FLASH_ACR_PRFTBE;
/* 3. PLL = HSE x 9; AHB /1, APB2 /1, APB1 /2 (36 MHz max), ADC = PCLK2 / 6 */
RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL
| RCC_CFGR_HPRE | RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2
| RCC_CFGR_ADCPRE))
| RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9
| RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_ADCPRE_DIV6;
/* 4. Start the PLL and wait for the lock */
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY)) { }
/* 5. SYSCLK = PLL; the switch happens when the PLL is ready */
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) { }
return 72000000u;
}
void SysTick_Handler(void)
{
g_ticks++;
}
void systick_init(uint32_t hclk_hz)
{
SysTick->LOAD = hclk_hz / 1000u - 1u; /* N - 1 for a period of N clocks */
SysTick->VAL = 0u; /* clear the current value */
NVIC_SetPriority(SysTick_IRQn, 15u); /* lowest of 16 levels */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk /* processor clock, HCLK */
| SysTick_CTRL_TICKINT_Msk /* interrupt at zero */
| SysTick_CTRL_ENABLE_Msk;
}
void delay_ms(uint32_t ms)
{
uint32_t start = g_ticks;
while ((uint32_t)(g_ticks - start) < ms) { }
}
Оценка «не меньше 62,5 мс» в комментарии — наша: каждая проверка занимает хотя бы один такт, 500 000 тактов на 8 МГц — это 62,5 мс, в 30 с лишним раз больше типичных 2 мс запуска кварца. На деле каждая итерация дольше, так что запас ещё больше. Если clock_init() вернула 8 МГц, программа продолжит работать, просто медленнее, — это удобнее, чем зависание без объяснений.
SysTick: системный таймер ядра
SysTick — 24-битный счётчик внутри Cortex-M3, а не периферия ST: он описан в руководстве Arm DUI 0552A (разд. 4.4), его регистры лежат по адресам 0xE000E010–0xE000E01C, и включать его в RCC не нужно. Счётчик идёт вниз от значения RELOAD до нуля, на переходе из 1 в 0 ставит флаг COUNTFLAG и, если включён бит TICKINT, вызывает исключение SysTick, а затем перезагружается. Для периода в N тактов в RELOAD записывают N − 1 (разд. 4.4.2): на 72 МГц для 1 мс это 72 000 − 1 = 71 999 (расчёт наш).
Бит CLKSOURCE выбирает источник: 1 — тактовая частота процессора, то есть HCLK; 0 — «внешний» сигнал, которым у STM32F103 служит HCLK/8 (RM0008, разд. 7.2). Калибровочный регистр SysTick содержит 9000 — это 1 мс при HCLK/8 = 9 МГц (разд. 10.1.1). Мы берём HCLK: так период задаётся точнее.
Порядок записи в systick_init() — тот, что требует DUI 0552A (разд. 4.4.5): сначала RELOAD, потом обнуление текущего значения, и только затем регистр управления, потому что после сброса RELOAD и текущее значение не определены. Приоритет исключения ставим самый низкий: у STM32F1 реализованы 4 бита приоритета (__NVIC_PRIO_BITS = 4), уровни от 0 до 15, и меньшее число — более срочное прерывание. То же самое одной строкой делает функция CMSIS SysTick_Config(hclk_hz / 1000u) из core_cm3.h.
Переменная g_ticks объявлена volatile: её меняет обработчик прерывания, и без volatile компилятор вправе прочитать её один раз и крутить цикл delay_ms вечно. Разность g_ticks - start в беззнаковой арифметике остаётся правильной и при переполнении счётчика, которое случится через 2³² мс — примерно 49,7 суток (расчёт наш). Почему это так и как безопасно читать общие с прерыванием данные, объясняет статья «Прерывания и общие данные».
Программа
/* main.c, lesson 4: 1 Hz blink at 72 MHz */
#include "stm32f1xx.h"
#include "clock.h"
int main(void)
{
uint32_t hclk = clock_init();
systick_init(hclk);
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
GPIOC->CRH = (GPIOC->CRH & ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13))
| (0x2u << GPIO_CRH_MODE13_Pos);
for (;;) {
GPIOC->BSRR = GPIO_BSRR_BR13; /* LED on */
delay_ms(hclk == 72000000u ? 500u : 100u); /* fast blink: no crystal */
GPIOC->BSRR = GPIO_BSRR_BS13; /* LED off */
delay_ms(hclk == 72000000u ? 500u : 100u);
}
}
В Makefile допишите новый файл: SRCS = startup.c main.c clock.c. Светодиод должен мигать ровно раз в секунду, а если кварц не запустился — часто, и это сразу видно. Обработчик SysTick_Handler в clock.c заменяет слабый псевдоним из startup.c — так работает механизм из урока 2.
На STM32F4
На Black Pill с STM32F411 кварц — 25 МГц (см. страницу Black Pill). Дальше — по данным наших протестированных модулей калькулятора тактирования и калькулятора тактов ожидания, которые ссылаются на RM0383 Rev 4; сами таблицы RM0383 для этого урока мы заново не читали. У PLL STM32F411 вместо одного множителя несколько параметров — M, N, P и Q, — делители шин и поля переключения лежат в других регистрах, а для частоты выше 84 МГц регулятор нужно перевести в режим VOS scale 1. На 100 МГц при питании 2,7–3,6 В флеш-памяти нужно 3 такта ожидания (в модуле — ссылка на табл. 5 RM0383). Калькулятор тактирования выдаёт и готовый код настройки RCC. SysTick у Cortex-M4 тот же, и systick_init() переносится без изменений.
Задание
- Выведите на вывод PA8 сигнал MCO с частотой PLL/2 и измерьте её осциллографом или частотомером. Какую частоту вы ожидаете и почему нельзя вывести сам SYSCLK?
- Сколько в RELOAD нужно записать, чтобы при CLKSOURCE = 0 прерывание SysTick шло каждые 10 мс?
Ответ и решение
- Ожидаем 36 МГц — 72 МГц / 2. Сам SYSCLK на MCO выводить нельзя: RM0008 требует, чтобы частота на этом выводе не превышала 50 МГц — предел скорости выводов (поле MCO регистра RCC_CFGR, разд. 7.3.2). Вывод PA8 — альтернативная функция push-pull, 50 МГц (CNF = 10, MODE = 11):
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
GPIOA->CRH = (GPIOA->CRH & ~(GPIO_CRH_MODE8 | GPIO_CRH_CNF8))
| (0x2u << GPIO_CRH_CNF8_Pos) | (0x3u << GPIO_CRH_MODE8_Pos);
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_MCO) | RCC_CFGR_MCO_PLLCLK_DIV2;
- При CLKSOURCE = 0 счётчик тактируется HCLK/8 = 9 МГц. За 10 мс это 90 000 тактов, RELOAD = 90 000 − 1 = 89 999 (расчёт наш). Значение помещается в 24 бита: предел — 0xFFFFFF = 16 777 215.
Что дальше
В уроке 5 настроим USART1 на 115 200 бит/с — для этого и нужна точная частота PCLK2 = 72 МГц. Все регистры RCC STM32F1 с битами и значениями после сброса — на странице атласа регистров RCC STM32F1. Если плата зависает после включения PLL, разбор причин — в ответе «STM32 зависает после настройки 72 МГц», а если не запускается кварц — в ответе «HSE не запускается». Термины урока — в статьях глоссария SysTick, PLL, «Такты ожидания» и HSE и HSI.
Частые вопросы
Почему STM32F103 зависает сразу после переключения на 72 МГц?
Чаще всего забыли такты ожидания флеш-памяти: на частоте выше 48 МГц поле LATENCY регистра FLASH_ACR должно быть равно 010, иначе ядро читает команды быстрее, чем флеш-память успевает их выдать. Вторая причина — делитель APB1 оставлен равным 1, и шина работает на 72 МГц при пределе 36 МГц. Обе настройки делают до переключения SYSCLK на PLL.
Можно ли получить 72 МГц без кварца?
Нет. На вход PLL от внутреннего генератора HSI подаётся только HSI/2 = 4 МГц, а наибольший множитель — 16, поэтому RM0008 указывает предел 64 МГц при работе от HSI. Кроме того, точность HSI — около 1 % при 25 °C после заводской калибровки, а для USB и надёжного UART на высоких скоростях лучше кварц.
Почему SysTick, а не TIM2, для отсчёта миллисекунд?
SysTick входит в ядро Cortex-M и есть у любого STM32, его не нужно включать в RCC, а CMSIS даёт для него готовую функцию SysTick_Config. Таймеры общего назначения лучше оставить для ШИМ, захвата и измерения частоты. Но в отладочной остановке SysTick не считает, а его 24 бита при 72 МГц дают не больше 233 мс до перезагрузки.
Источники
- STMicroelectronics. RM0008 Rev 21. Reference manual STM32F101xx–STM32F107xx — разд. 3.3.3 (с. 59–60): предвыборку включают и выключают только при SYSCLK ниже 24 МГц и без делителя AHB; FLASH_ACR, сброс 0x0000 0030, LATENCY: 000 — до 24 МГц, 001 — 24–48 МГц, 010 — 48–72 МГц; разд. 7.2 (с. 92–94): максимум AHB и APB2 — 72 МГц, APB1 — 36 МГц; SysTick тактируется HCLK/8 или HCLK; таймеры получают частоту APB ×2, если делитель APB не равен 1; от HSI через PLL — не выше 64 МГц; разд. 7.2.1 (с. 95): кварц HSE 4–16 МГц, флаг HSERDY; разд. 7.2.3 (с. 96): параметры PLL задаются до включения и после не меняются; разд. 7.2.6 (с. 97): после сброса SYSCLK — HSI, переключение происходит, только когда новый источник готов; разд. 7.3.1 (с. 99): HSEON, HSERDY, PLLON, PLLRDY; разд. 7.3.2 (с. 101–103): RCC_CFGR — MCO, USBPRE, PLLMUL (0111 — ×9, выход PLL не выше 72 МГц), PLLXTPRE, PLLSRC, ADCPRE, PPRE2, PPRE1 (не превышать 36 МГц), HPRE, SWS, SW; MCO: SYSCLK на выводе не выше 50 МГц; разд. 10.1.1 (с. 197): калибровочное значение SysTick 9000 — 1 мс при 9 МГц (HCLK/8)
- STMicroelectronics. DS5319 Rev 20. STM32F103x8, STM32F103xB datasheet — табл. 22: кварцевый генератор HSE 4–16 МГц (типично 8 МГц), время запуска tSU(HSE) — типично 2 мс, зависит от кварца
- Arm. Cortex-M3 Devices Generic User Guide, DUI 0552A — разд. 4.4: 24-битный SysTick считает вниз до нуля и перезагружается из SYST_RVR; в отладочной остановке не считает; табл. 4-33: COUNTFLAG (бит 16), CLKSOURCE (2: 1 — тактовая частота процессора), TICKINT (1), ENABLE (0); разд. 4.4.2: RELOAD 0x000001–0xFFFFFF, для периода N тактов — N − 1; разд. 4.4.5: порядок запуска — RELOAD, обнуление текущего значения, затем CSR
- STMicroelectronics. cmsis-device-f1 v4.3.5 (stm32f103xb.h); Arm CMSIS_5 5.9.0 (core_cm3.h) — FLASH_ACR_LATENCY_0/_1/_2 — это биты 0, 1 и 2 поля (0x1, 0x2, 0x4), а не число тактов ожидания; RCC_CFGR_PLLMULL9, RCC_CFGR_PPRE1_DIV2 (0x400), RCC_CFGR_ADCPRE_DIV6, RCC_CFGR_SW_PLL (0x2), RCC_CFGR_SWS_PLL (0x8), RCC_CFGR_MCO_PLLCLK_DIV2; __NVIC_PRIO_BITS = 4; SysTick_Config записывает LOAD = ticks − 1, ставит SysTick низший приоритет, обнуляет VAL и включает CLKSOURCE, TICKINT, ENABLE
- Модули калькуляторов GAW src/lib/calc/stm32-clock.ts и stm32-flash-latency.ts с тестами (ссылаются на RM0383 Rev 4, STM32F411) — значения взяты из протестированных модулей, а не прочитаны в RM0383 для этого урока: на 100 МГц при 2,7–3,6 В — 3 такта ожидания (в модуле — ссылка на табл. 5 RM0383); выше 84 МГц — режим регулятора VOS scale 1; PLL F411 с параметрами M, N, P и Q
Нашли ошибку?
Смотрите также
- Тактирование STM32PLL под нужную частоту, шины, флеш-память, регистры RCC и код
- Такты ожидания флеш-памяти STM32LATENCY в FLASH_ACR по частоте и питанию, таблица и код
- Почему STM32 зависает после настройки частоты 72 МГц?Такты ожидания флеш, делитель APB1 и источник PLL
- SysTick24-битный таймер ядра Cortex-M для системного тика
- Дерево тактированияПуть тактового сигнала от генератора до периферии