diff --git a/.github/ci/book.sh b/.github/ci/book.sh index 2466f53f5..c91d10d16 100755 --- a/.github/ci/book.sh +++ b/.github/ci/book.sh @@ -1,6 +1,6 @@ #!/bin/bash ## on push branch=main -## priority -9 +## priority -100 ## dedup dequeue set -euxo pipefail diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 9162b37ae..26971afdc 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -1,6 +1,6 @@ #!/bin/bash ## on push branch=main -## priority -10 +## priority -100 ## dedup dequeue set -euxo pipefail diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 526c8a4b3..a2665c770 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -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 = [] diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 693a39ed5..2b1888170 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -106,6 +106,7 @@ impl StackResources { /// 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] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 73860c64a..753f94fa6 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -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" => true, + "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true, "Timpre" | "Pllrclkpre" => false, e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, _ => false, diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index fd74d5318..a2e42fe52 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -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::(); @@ -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 { diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 383f48874..837210b6a 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -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, /// PLL R division factor. If None, PLL R output is disabled. pub divr: Option, + #[cfg(stm32h7rs)] + /// PLL S division factor. If None, PLL S output is disabled. + pub divs: Option, + #[cfg(stm32h7rs)] + /// PLL T division factor. If None, PLL T output is disabled. + pub divt: Option, } fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz { @@ -749,6 +758,12 @@ struct PllOutput { q: Option, #[allow(dead_code)] r: Option, + #[cfg(stm32h7rs)] + #[allow(dead_code)] + s: Option, + #[cfg(stm32h7rs)] + #[allow(dead_code)] + t: Option, } fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { @@ -767,6 +782,10 @@ fn init_pll(num: usize, config: Option, 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, 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, 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, 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) { diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index eaaeb1ac0..cf324d3df 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -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 # <- diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs new file mode 100644 index 000000000..d5e3e7648 --- /dev/null +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -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 = 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; + } +} diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index e7fc05948..ac1429f30 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -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 # <- diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs new file mode 100644 index 000000000..a4e1b5ff4 --- /dev/null +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -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 = 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; + } +} diff --git a/examples/stm32h7rs/src/bin/blinky.rs b/examples/stm32h7rs/src/bin/blinky.rs index 137c585b7..5fd50fb15 100644 --- a/examples/stm32h7rs/src/bin/blinky.rs +++ b/examples/stm32h7rs/src/bin/blinky.rs @@ -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 diff --git a/examples/stm32h7rs/src/bin/eth.rs b/examples/stm32h7rs/src/bin/eth.rs index 6d246bb09..d8002e9ba 100644 --- a/examples/stm32h7rs/src/bin/eth.rs +++ b/examples/stm32h7rs/src/bin/eth.rs @@ -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 diff --git a/examples/stm32h7rs/src/bin/usb_serial.rs b/examples/stm32h7rs/src/bin/usb_serial.rs index 56a9884af..23abc3e2f 100644 --- a/examples/stm32h7rs/src/bin/usb_serial.rs +++ b/examples/stm32h7rs/src/bin/usb_serial.rs @@ -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 diff --git a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs index 59045ca2e..4c1b450b4 100644 --- a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs +++ b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs @@ -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 diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index a4d8048ce..cb63b3374 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -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