STM32 & Rust - RCC Система тактирования

Содержание


Как известно, система тактирования в микроконтроллерах STM32 достаточно сложная и разветвленная. При использовании библиотеки HAL у нас нет такого удобного инструмента конфигурирования RCC как CubeMX. Но зато имеется удобный API самой библиотеки, куда удобнее оригинального HAL от ST.

Разбираться с RCC будем на примере отладочной платы 32F723EDISCOVERY и библиотеки stm32f7xx_hal.

В мануале RM0431 на странице 130 приведено описание системы тактирования.

STM32F723 - Clock tree

В модуль RCC библиотеки HAL, имеется структура CFGR со следующими основными методами:

  • hse - конфигурирование HSE генератора. Варианты режимов могут быть или HSEClockMode::Bypass в случае внешнего тактового генератора или HSEClockMode::Oscillator в случае кварчевого резонатора;
  • hclk - установка частоты HCLK. Случится паника если задача частота выше 216МГц;
  • sysclk - установка частоты SYSCLK. Случится паника если частота меньше 12.5МГц или выше 216МГц;
  • pclk1 - установка частоты PCLK1, если частота не задана используется максимально поддерживаемая частоты. Случится паника если частота меньше 12.5МГц или выше 54МГц;
  • pclk2- установка частоты PCLK2, если частота не задана используется максимально поддерживаемая частоты. Случится паника если частота меньше 12.5МГц или выше 108МГц;
  • use_pll - включает PLL. Важно должна быть задача частота sysclk или использован метод use_pll48clk, иначе PLL не будет включён;
  • pllm - установка делителя PLL. Случится паника если делитель меньше 2 и больше 63;
  • plln - установка умножителя PLL. Случится паника если умножитель меньше 50 и больше 432;
  • pllp - установка делителя PLL;
  • pllq - установка делителя PLL для клоков на 48МГц. Случится паника если делитель меньше 2 и больше 15 (включительно);
  • mco1 - установка источника для MCO1. Возможны варианты MCO1 {Hsi, Lse, Hse, Pll};
  • mco1pre - установка делителя частоты для MCO1;
  • mco2- установка источника для MCO2. Возможны варианты MCO2 {Sysclk, Plli2s, Hse, Pll};
  • mco2pre- установка делителя частоты для MCO2;
  • set_default - конфигурация клоков по умолчанию. Частота SYSCLK устанавливается в 216МГц;
  • freeze - “заморозка” конфигурации, менять во время выполнения нельзя.

Ниже приведенный код конфигурирует систему тактирования как показано на диаграмме из CubeMX. CubeMX - Clock configuration

#![no_std]  
#![no_main]  
  
use cortex_m_rt::entry;  
use cortex_m_semihosting::hprintln;  
#[allow(unused_imports)]  
use panic_halt;  
use stm32f7xx_hal::{  
   gpio::Speed,  
   pac,  
   prelude::*,  
   rcc::{HSEClock, HSEClockMode, MCO1, MCO2, MCOPRE},  
};  
  
#[entry]  
fn main() -> ! {  
   let dp = pac::Peripherals::take().unwrap();  
   let rcc = dp.RCC.constrain();  
  
   let clocks = rcc  
       .cfgr  
       .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass))  
       .sysclk(108.MHz())  
       .hclk(54.MHz())  
       .pclk1(13500.kHz())  
       .pclk2(27.MHz())  
       .mco1(MCO1::Hsi)  
       .mco1pre(MCOPRE::Div4)  
       .mco2(MCO2::Hse)  
       .mco2pre(MCOPRE::Div5)  
       .freeze();  
  
   hprintln!("{:?}", clocks);  
  
   let gpioa = dp.GPIOA.split();  
   let gpioc = dp.GPIOC.split();  
  
   let _mco1 = gpioa.pa8.into_alternate::<0>().set_speed(Speed::VeryHigh);  
   let _mco2 = gpioc.pc9.into_alternate::<0>().set_speed(Speed::VeryHigh);  
  
   loop {}  
}

Отладочный вывод показывает, что всё сконфигурировано как ожидается

Подключение логического анализатора к пинам PA8 (MCO1) и PC9 (MCO2) показывает что-то странное. Частота PA8 соответствует ожиданиям в 4МГц, а частота PC9 5.333Мгц, вместо ожидаемых 5МГц и плавает (или 4МГц или 5.333МГц). PA8 - MCO1 / HSI

PC9 - MCO2 / HSE

Сейчас через STM32CubeProgrammer посмотрим конфигурацию RCC и сравним с RM0431. Регистр RCC - CR

RM0431 страница 140

Регистр RCC - CFGR

RM0431 страница 144

Конфигурация регистров соответствует тому исходному коду который приведен выше.