Перейти к содержанию

Включение тактирования периферии (clock gating)

Самая частая ошибка новичка в STM32 без HAL: порт настроен, а светодиод не горит. Причина — к блоку не подан тактовый сигнал. В STM32 каждый периферийный блок получает такт только после того, как программа включит его отдельным битом.

Обновлено Редакция GAW

Включение тактирования периферии (peripheral clock gating) — подача тактового сигнала на отдельный блок микроконтроллера битом в регистре управления тактированием. В STM32 это биты регистров RCC: у STM32F103 — RCC_AHBENR, RCC_APB2ENR и RCC_APB1ENR, по одному регистру на шину. Ключ — последнее звено дерева тактирования перед каждым блоком.

Почему периферия не работает «сама»

По RM0008 (разд. 3.1) после любого сброса тактирование всей периферии выключено — кроме SRAM и интерфейса флеш-памяти. Регистры RCC_APB2ENR и RCC_APB1ENR после сброса равны нулю. Пока бит блока не установлен, запись в его регистры ни на что не влияет, а чтение может вернуть 0 (RM0008, разд. 7.3.6–7.3.8). Отсюда классические симптомы: вывод не переключается, UART молчит, таймер не считает, хотя все его регистры «настроены».

Какие биты нужны

БлокSTM32F103STM32F407
Порт GPIOAIOPAEN в RCC_APB2ENRGPIOAEN в RCC_AHB1ENR
AFIO (ремап, выбор порта для EXTI)AFIOEN в RCC_APB2ENR— (у F4 вместо него SYSCFG)
USART1USART1EN в RCC_APB2ENRUSART1EN в RCC_APB2ENR
USART2, I²C1, TIM2биты в RCC_APB1ENRбиты в RCC_APB1ENR
DMA1DMA1EN в RCC_AHBENRDMA1EN в RCC_AHB1ENR

Пример включения тактирования портов на регистрах есть в статье о GPIO STM32, а готовый код с нужными битами выдаёт генератор кода инициализации STM32. В HAL то же делают макросы вида __HAL_RCC_GPIOA_CLK_ENABLE() — как они соотносятся с регистрами, показано в статье «HAL, LL и регистры».

Экономия энергии

Каждый тактируемый блок потребляет ток, поэтому выключенная по умолчанию периферия — это и экономия. В режиме Run такт любого блока можно снять в любой момент, а перед переходом в режим сна Sleep — отключить лишние блоки до команды WFI или WFE (RM0008, разд. 5.3.2). У STM32F4 для этого есть отдельные регистры RCC_xxxLPENR: они задают, какие блоки остаются тактируемыми в Sleep.

Не путать с битами сброса периферии в регистрах RCC_APB2RSTR и RCC_APB1RSTR (RM0008, разд. 7.3.4–7.3.5): они возвращают регистры блока к исходным значениям, но такт не включают.

Частые вопросы

Какие биты включить, чтобы мигать светодиодом на PC13 у STM32F103?

Бит IOPCEN в регистре RCC_APB2ENR — порты GPIO у STM32F1 висят на шине APB2. Для USART1 добавляют USART1EN в том же регистре, для USART2 — USART2EN в RCC_APB1ENR. Если используется ремап или внешние прерывания, нужен ещё AFIOEN. У STM32F4 порты включаются битами GPIOxEN в RCC_AHB1ENR.

Что будет, если обратиться к блоку без тактирования?

Запись в его регистры не подействует, а чтение, по RM0008, может вернуть 0. Программа при этом не падает и ошибку не сообщает — блок просто молчит, поэтому ошибку легко искать долго.

Зачем вообще выключать тактирование периферии?

Ради потребления: каждый блок с поданным тактом расходует ток, даже если ничего не делает. Поэтому после сброса всё выключено, а программа включает только нужное и может отключать блоки на ходу; в режиме сна такт периферии можно снять перед командой WFI (RM0008, разд. 5.3.2).

Источники

  1. STMicroelectronics. RM0008 Rev 21. Reference manual: STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx — разд. 3.1: после сброса тактирование всей периферии выключено, кроме SRAM и FLITF, перед использованием его включают в RCC_AHBENR, RCC_APB2ENR или RCC_APB1ENR; разд. 5.3.2: в режиме Run такт отдельных блоков можно остановить в любой момент для снижения потребления, в Sleep — выключить перед WFI или WFE; разд. 7.3.6–7.3.8: значения после сброса 0x0000 0014, 0x0000 0000, 0x0000 0000; без такта регистры блока могут не читаться и возвращают 0; биты IOPAEN, AFIOEN, USART1EN; разд. 9.4: перед обращением к регистрам AFIO нужен такт AFIO
  2. STMicroelectronics. RM0090 Rev 21 (June 2024). Reference manual: STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 — разд. 5.3.2: ключи тактирования в регистрах RCC_AHB1ENR, RCC_AHB2ENR, RCC_AHB3ENR и регистрах APB; отдельные регистры LPENR для режима Sleep; разд. 7.3.10–7.3.14: GPIOxEN и DMA1EN в RCC_AHB1ENR, TIM2EN, USART2EN, I2C1EN в RCC_APB1ENR, USART1EN и SYSCFGEN в RCC_APB2ENR

Нашли ошибку?