Merge branch 'main' into feat/stm32wba-rcc-pll-support

This commit is contained in:
leftger 2025-07-27 09:38:38 -07:00 committed by GitHub
commit b9e643d5c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 510 additions and 25 deletions

2
.github/ci/book.sh vendored
View File

@ -1,6 +1,6 @@
#!/bin/bash
## on push branch=main
## priority -9
## priority -100
## dedup dequeue
set -euxo pipefail

2
.github/ci/doc.sh vendored
View File

@ -1,6 +1,6 @@
#!/bin/bash
## on push branch=main
## priority -10
## priority -100
## dedup dequeue
set -euxo pipefail

View File

@ -24,7 +24,7 @@ features = ["defmt", "tcp", "udp", "raw", "dns", "icmp", "dhcpv4", "proto-ipv6",
[features]
## Enable defmt
defmt = ["dep:defmt", "smoltcp/defmt", "embassy-net-driver/defmt", "heapless/defmt-03", "defmt?/ip_in_core"]
defmt = ["dep:defmt", "smoltcp/defmt", "embassy-net-driver/defmt", "embassy-time/defmt", "heapless/defmt-03", "defmt?/ip_in_core"]
## Trace all raw received and transmitted packets using defmt or log.
packet-trace = []

View File

@ -106,6 +106,7 @@ impl<const SOCK: usize> StackResources<SOCK> {
/// Static IP address configuration.
#[cfg(feature = "proto-ipv4")]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct StaticConfigV4 {
/// IP address and subnet mask.
pub address: Ipv4Cidr,
@ -118,6 +119,7 @@ pub struct StaticConfigV4 {
/// Static IPv6 address configuration
#[cfg(feature = "proto-ipv6")]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct StaticConfigV6 {
/// IP address and subnet mask.
pub address: Ipv6Cidr,
@ -130,6 +132,7 @@ pub struct StaticConfigV6 {
/// DHCP configuration.
#[cfg(feature = "dhcpv4")]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub struct DhcpConfig {
/// Maximum lease duration.
@ -169,6 +172,7 @@ impl Default for DhcpConfig {
/// Network stack configuration.
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub struct Config {
/// IPv4 configuration
@ -220,6 +224,7 @@ impl Config {
/// Network stack IPv4 configuration.
#[cfg(feature = "proto-ipv4")]
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ConfigV4 {
/// Do not configure IPv4.
#[default]
@ -234,6 +239,7 @@ pub enum ConfigV4 {
/// Network stack IPv6 configuration.
#[cfg(feature = "proto-ipv6")]
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ConfigV6 {
/// Do not configure IPv6.
#[default]

View File

@ -1599,7 +1599,7 @@ fn main() {
for e in rcc_registers.ir.enums {
fn is_rcc_name(e: &str) -> bool {
match e {
"Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true,
"Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true,
"Timpre" | "Pllrclkpre" => false,
e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true,
_ => false,

View File

@ -95,6 +95,18 @@ cfg_if! {
}
}
/// Number of samples used for averaging.
pub enum Averaging {
Disabled,
Samples2,
Samples4,
Samples8,
Samples16,
Samples32,
Samples64,
Samples128,
Samples256,
}
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(adc: Peri<'d, T>) -> Self {
rcc::enable_and_reset::<T>();
@ -225,6 +237,30 @@ impl<'d, T: Instance> Adc<'d, T> {
T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
}
pub fn set_averaging(&mut self, averaging: Averaging) {
let (enable, samples, right_shift) = match averaging {
Averaging::Disabled => (false, 0, 0),
Averaging::Samples2 => (true, 0, 1),
Averaging::Samples4 => (true, 1, 2),
Averaging::Samples8 => (true, 2, 3),
Averaging::Samples16 => (true, 3, 4),
Averaging::Samples32 => (true, 4, 5),
Averaging::Samples64 => (true, 5, 6),
Averaging::Samples128 => (true, 6, 7),
Averaging::Samples256 => (true, 7, 8),
};
T::regs().cfgr2().modify(|reg| {
#[cfg(not(any(adc_g0, adc_u0)))]
reg.set_rovse(enable);
#[cfg(any(adc_g0, adc_u0))]
reg.set_ovse(enable);
#[cfg(any(adc_h5, adc_h7rs))]
reg.set_ovsr(samples.into());
#[cfg(not(any(adc_h5, adc_h7rs)))]
reg.set_ovsr(samples.into());
reg.set_ovss(right_shift.into());
})
}
/*
/// Convert a raw sample from the `Temperature` to deg C
pub fn to_degrees_centigrade(sample: u16) -> f32 {

View File

@ -1,5 +1,8 @@
use core::ops::RangeInclusive;
#[cfg(stm32h7rs)]
use stm32_metapac::rcc::vals::Plldivst;
use crate::pac;
pub use crate::pac::rcc::vals::{
Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk,
@ -78,6 +81,12 @@ pub struct Pll {
pub divq: Option<PllDiv>,
/// PLL R division factor. If None, PLL R output is disabled.
pub divr: Option<PllDiv>,
#[cfg(stm32h7rs)]
/// PLL S division factor. If None, PLL S output is disabled.
pub divs: Option<Plldivst>,
#[cfg(stm32h7rs)]
/// PLL T division factor. If None, PLL T output is disabled.
pub divt: Option<Plldivst>,
}
fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz {
@ -749,6 +758,12 @@ struct PllOutput {
q: Option<Hertz>,
#[allow(dead_code)]
r: Option<Hertz>,
#[cfg(stm32h7rs)]
#[allow(dead_code)]
s: Option<Hertz>,
#[cfg(stm32h7rs)]
#[allow(dead_code)]
t: Option<Hertz>,
}
fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
@ -767,6 +782,10 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
p: None,
q: None,
r: None,
#[cfg(stm32h7rs)]
s: None,
#[cfg(stm32h7rs)]
t: None,
};
};
@ -814,6 +833,10 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
});
let q = config.divq.map(|div| vco_clk / div);
let r = config.divr.map(|div| vco_clk / div);
#[cfg(stm32h7rs)]
let s = config.divs.map(|div| vco_clk / div);
#[cfg(stm32h7rs)]
let t = config.divt.map(|div| vco_clk / div);
#[cfg(stm32h5)]
RCC.pllcfgr(num).write(|w| {
@ -840,6 +863,10 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
w.set_divpen(num, p.is_some());
w.set_divqen(num, q.is_some());
w.set_divren(num, r.is_some());
#[cfg(stm32h7rs)]
w.set_divsen(num, s.is_some());
#[cfg(stm32h7rs)]
w.set_divten(num, t.is_some());
});
}
@ -850,10 +877,24 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
w.set_pllr(config.divr.unwrap_or(PllDiv::DIV2));
});
#[cfg(stm32h7rs)]
RCC.plldivr2(num).write(|w| {
w.set_plls(config.divs.unwrap_or(Plldivst::DIV2));
w.set_pllt(config.divt.unwrap_or(Plldivst::DIV2));
});
RCC.cr().modify(|w| w.set_pllon(num, true));
while !RCC.cr().read().pllrdy(num) {}
PllOutput { p, q, r }
PllOutput {
p,
q,
r,
#[cfg(stm32h7rs)]
s,
#[cfg(stm32h7rs)]
t,
}
}
fn flash_setup(clk: Hertz, vos: VoltageScale) {

View File

@ -36,13 +36,6 @@ chrono = { version = "^0.4", default-features = false }
grounded = "0.2.0"
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
@ -55,11 +48,10 @@ overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
codegen-units = 16
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,182 @@
#![no_std]
#![no_main]
//! STM32H7 Secondary Core (CM4) Intercore Communication Example
//!
//! This example demonstrates reliable communication between the Cortex-M7 and
//! Cortex-M4 cores. This secondary core monitors shared memory for LED state
//! changes and updates the physical LEDs accordingly.
//!
//! The CM4 core handles:
//! - Responding to state changes from CM7
//! - Controlling the physical green and yellow LEDs
//! - Providing visual feedback via a heartbeat on the red LED
//!
//! Usage:
//! 1. Flash this CM4 (secondary) core binary first
//! 2. Then flash the CM7 (primary) core binary
//! 3. The red LED should blink continuously as a heartbeat
//! 4. Green and yellow LEDs should toggle according to CM7 core signals
/// Module providing shared memory constructs for intercore communication
mod shared {
use core::sync::atomic::{AtomicU32, Ordering};
/// State shared between CM7 and CM4 cores for LED control
#[repr(C, align(4))]
pub struct SharedLedState {
pub magic: AtomicU32,
pub counter: AtomicU32,
pub led_states: AtomicU32,
}
// Bit positions in led_states
pub const GREEN_LED_BIT: u32 = 0;
pub const YELLOW_LED_BIT: u32 = 1;
impl SharedLedState {
pub const fn new() -> Self {
Self {
magic: AtomicU32::new(0xDEADBEEF),
counter: AtomicU32::new(0),
led_states: AtomicU32::new(0),
}
}
/// Set LED state by manipulating the appropriate bit in the led_states field
#[inline(never)]
#[allow(dead_code)]
pub fn set_led(&self, is_green: bool, state: bool) {
let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
let current = self.led_states.load(Ordering::SeqCst);
let new_value = if state {
current | (1 << bit) // Set bit
} else {
current & !(1 << bit) // Clear bit
};
self.led_states.store(new_value, Ordering::SeqCst);
}
/// Get current LED state
#[inline(never)]
pub fn get_led(&self, is_green: bool) -> bool {
let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
let value = self.led_states.load(Ordering::SeqCst);
(value & (1 << bit)) != 0
}
/// Increment counter and return new value
#[inline(never)]
#[allow(dead_code)]
pub fn increment_counter(&self) -> u32 {
let current = self.counter.load(Ordering::SeqCst);
let new_value = current.wrapping_add(1);
self.counter.store(new_value, Ordering::SeqCst);
new_value
}
/// Get current counter value
#[inline(never)]
pub fn get_counter(&self) -> u32 {
let value = self.counter.load(Ordering::SeqCst);
value
}
}
#[link_section = ".ram_d3"]
pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new();
}
use core::mem::MaybeUninit;
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::SharedData;
use embassy_time::Timer;
use shared::SHARED_LED_STATE;
use {defmt_rtt as _, panic_probe as _};
#[link_section = ".ram_d3"]
static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
/// Task that continuously blinks the red LED as a heartbeat indicator
#[embassy_executor::task]
async fn blink_heartbeat(mut led: Output<'static>) {
loop {
led.toggle();
info!("CM4 heartbeat");
Timer::after_millis(500).await;
}
}
#[embassy_executor::main]
async fn main(spawner: Spawner) -> ! {
// Initialize the secondary core
let p = embassy_stm32::init_secondary(&SHARED_DATA);
info!("CM4 core initialized!");
// Verify shared memory is accessible
let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst);
info!("CM4: Magic value = 0x{:X}", magic);
// Set up LEDs
let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1
let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2
let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat)
// Start heartbeat task
unwrap!(spawner.spawn(blink_heartbeat(red_led)));
// Track previous values to detect changes
let mut prev_green = false;
let mut prev_yellow = false;
let mut prev_counter = 0;
info!("CM4: Starting main loop");
loop {
// Read current values from shared memory
let green_state = SHARED_LED_STATE.get_led(true);
let yellow_state = SHARED_LED_STATE.get_led(false);
let counter = SHARED_LED_STATE.get_counter();
// Detect changes
let green_changed = green_state != prev_green;
let yellow_changed = yellow_state != prev_yellow;
let counter_changed = counter != prev_counter;
// Update LEDs and logs when values change
if green_changed || yellow_changed || counter_changed {
if counter_changed {
info!("CM4: Counter = {}", counter);
prev_counter = counter;
}
if green_changed {
if green_state {
green_led.set_high();
info!("CM4: Green LED ON");
} else {
green_led.set_low();
info!("CM4: Green LED OFF");
}
prev_green = green_state;
}
if yellow_changed {
if yellow_state {
yellow_led.set_high();
info!("CM4: Yellow LED ON");
} else {
yellow_led.set_low();
info!("CM4: Yellow LED OFF");
}
prev_yellow = yellow_state;
}
}
Timer::after_millis(10).await;
}
}

View File

@ -35,15 +35,6 @@ static_cell = "2"
chrono = { version = "^0.4", default-features = false }
grounded = "0.2.0"
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
@ -55,11 +46,10 @@ overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
codegen-units = 16
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,228 @@
#![no_std]
#![no_main]
//! STM32H7 Primary Core (CM7) Intercore Communication Example
//!
//! This example demonstrates reliable communication between the Cortex-M7 and
//! Cortex-M4 cores using a shared memory region configured as non-cacheable
//! via MPU settings.
//!
//! The CM7 core handles:
//! - MPU configuration to make shared memory non-cacheable
//! - Clock initialization
//! - Toggling LED states in shared memory
//!
//! Usage:
//! 1. Flash the CM4 (secondary) core binary first
//! 2. Then flash this CM7 (primary) core binary
//! 3. The system will start with CM7 toggling LED states and CM4 responding by
//! physically toggling the LEDs
use core::mem::MaybeUninit;
use cortex_m::asm;
use cortex_m::peripheral::MPU;
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::{Config, SharedData};
use embassy_time::Timer;
use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2};
use {defmt_rtt as _, panic_probe as _};
/// Module providing shared memory constructs for intercore communication
mod shared {
use core::sync::atomic::{AtomicU32, Ordering};
/// State shared between CM7 and CM4 cores for LED control
#[repr(C, align(4))]
pub struct SharedLedState {
pub magic: AtomicU32,
pub counter: AtomicU32,
pub led_states: AtomicU32,
}
// Bit positions in led_states
pub const GREEN_LED_BIT: u32 = 0;
pub const YELLOW_LED_BIT: u32 = 1;
impl SharedLedState {
pub const fn new() -> Self {
Self {
magic: AtomicU32::new(0xDEADBEEF),
counter: AtomicU32::new(0),
led_states: AtomicU32::new(0),
}
}
/// Set LED state by manipulating the appropriate bit in the led_states field
#[inline(never)]
pub fn set_led(&self, is_green: bool, state: bool) {
let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
let current = self.led_states.load(Ordering::SeqCst);
let new_value = if state {
current | (1 << bit) // Set bit
} else {
current & !(1 << bit) // Clear bit
};
self.led_states.store(new_value, Ordering::SeqCst);
}
/// Get current LED state
#[inline(never)]
#[allow(dead_code)]
pub fn get_led(&self, is_green: bool) -> bool {
let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
let value = self.led_states.load(Ordering::SeqCst);
(value & (1 << bit)) != 0
}
/// Increment counter and return new value
#[inline(never)]
pub fn increment_counter(&self) -> u32 {
let current = self.counter.load(Ordering::SeqCst);
let new_value = current.wrapping_add(1);
self.counter.store(new_value, Ordering::SeqCst);
new_value
}
/// Get current counter value
#[inline(never)]
#[allow(dead_code)]
pub fn get_counter(&self) -> u32 {
let value = self.counter.load(Ordering::SeqCst);
value
}
}
#[link_section = ".ram_d3"]
pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new();
// Memory region constants for MPU configuration
pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000;
pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1)
pub const SRAM4_REGION_NUMBER: u8 = 0;
}
#[link_section = ".ram_d3"]
static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
/// Configure MPU to make SRAM4 region non-cacheable
fn configure_mpu_non_cacheable(mpu: &mut MPU) {
asm::dmb();
unsafe {
// Disable MPU
mpu.ctrl.write(0);
// Configure SRAM4 as non-cacheable
mpu.rnr.write(SRAM4_REGION_NUMBER as u32);
// Set base address with region number
mpu.rbar.write(SRAM4_BASE_ADDRESS | (1 << 4));
// Configure region attributes
let rasr_value: u32 = (SRAM4_SIZE_LOG2 << 1) | // SIZE=15 (64KB)
(1 << 0) | // ENABLE=1
(3 << 24) | // AP=3 (Full access)
(1 << 19) | // TEX=1
(1 << 18); // S=1 (Shareable)
mpu.rasr.write(rasr_value);
// Enable MPU with default memory map as background
mpu.ctrl.write(1 | (1 << 2)); // MPU_ENABLE | PRIVDEFENA
}
asm::dsb();
asm::isb();
info!("MPU configured - SRAM4 set as non-cacheable");
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) -> ! {
// Set up MPU and cache configuration
{
let mut cp = cortex_m::Peripherals::take().unwrap();
let scb = &mut cp.SCB;
// First disable caches
scb.disable_icache();
scb.disable_dcache(&mut cp.CPUID);
// Configure MPU
configure_mpu_non_cacheable(&mut cp.MPU);
// Re-enable caches
scb.enable_icache();
scb.enable_dcache(&mut cp.CPUID);
asm::dsb();
asm::isb();
}
// Configure the clock system
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.hsi48 = Some(Default::default());
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8),
divr: None,
});
config.rcc.sys = Sysclk::PLL1_P;
config.rcc.ahb_pre = AHBPrescaler::DIV2;
config.rcc.apb1_pre = APBPrescaler::DIV2;
config.rcc.apb2_pre = APBPrescaler::DIV2;
config.rcc.apb3_pre = APBPrescaler::DIV2;
config.rcc.apb4_pre = APBPrescaler::DIV2;
config.rcc.voltage_scale = VoltageScale::Scale1;
config.rcc.supply_config = SupplyConfig::DirectSMPS;
}
// Initialize the CM7 core
let _p = embassy_stm32::init_primary(config, &SHARED_DATA);
info!("CM7 core initialized with non-cacheable SRAM4!");
// Verify shared memory is accessible
let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst);
info!("CM7: Magic value = 0x{:X}", magic);
// Initialize LED states
SHARED_LED_STATE.set_led(true, false); // Green LED off
SHARED_LED_STATE.set_led(false, false); // Yellow LED off
// Main loop - periodically toggle LED states
let mut green_state = false;
let mut yellow_state = false;
let mut loop_count = 0;
info!("CM7: Starting main loop");
loop {
loop_count += 1;
let counter = SHARED_LED_STATE.increment_counter();
// Toggle green LED every second
if loop_count % 10 == 0 {
green_state = !green_state;
SHARED_LED_STATE.set_led(true, green_state);
info!("CM7: Counter = {}, Set green LED to {}", counter, green_state);
}
// Toggle yellow LED every 3 seconds
if loop_count % 30 == 0 {
yellow_state = !yellow_state;
SHARED_LED_STATE.set_led(false, yellow_state);
info!("CM7: Counter = {}, Set yellow LED to {}", counter, yellow_state);
}
Timer::after_millis(100).await;
}
}

View File

@ -25,6 +25,8 @@ async fn main(_spawner: Spawner) {
divp: Some(PllDiv::DIV2),
divq: None,
divr: None,
divs: None,
divt: None,
});
config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz

View File

@ -41,6 +41,8 @@ async fn main(spawner: Spawner) -> ! {
divp: Some(PllDiv::DIV2),
divq: None,
divr: None,
divs: None,
divt: None,
});
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz

View File

@ -40,6 +40,8 @@ async fn main(_spawner: Spawner) {
divp: Some(PllDiv::DIV1), //600 MHz
divq: Some(PllDiv::DIV2), // 300 MHz
divr: Some(PllDiv::DIV2), // 300 MHz
divs: None,
divt: None,
});
config.rcc.sys = Sysclk::PLL1_P; // 600 MHz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 MHz

View File

@ -36,6 +36,8 @@ async fn main(_spawner: Spawner) {
divp: Some(PllDiv::DIV2),
divq: None,
divr: None,
divs: None,
divt: None,
});
config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz

View File

@ -681,6 +681,8 @@ pub fn config() -> Config {
divp: Some(PllDiv::DIV2), // 600Mhz
divq: Some(PllDiv::DIV25), // 48Mhz
divr: None,
divs: None,
divt: None,
});
config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz