diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/stm32h755cm4/src/bin/intercore.rs | 53 | ||||
| -rw-r--r-- | examples/stm32h755cm7/src/bin/intercore.rs | 79 |
2 files changed, 71 insertions, 61 deletions
diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index 3a66a1ecd..715df28d6 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs | |||
| @@ -1,18 +1,32 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | // IMPORTANT: This must match EXACTLY the definition in CM7! | 4 | //! STM32H7 Secondary Core (CM4) Intercore Communication Example |
| 5 | //! | ||
| 6 | //! This example demonstrates reliable communication between the Cortex-M7 and | ||
| 7 | //! Cortex-M4 cores. This secondary core monitors shared memory for LED state | ||
| 8 | //! changes and updates the physical LEDs accordingly. | ||
| 9 | //! | ||
| 10 | //! The CM4 core handles: | ||
| 11 | //! - Responding to state changes from CM7 | ||
| 12 | //! - Controlling the physical green and yellow LEDs | ||
| 13 | //! - Providing visual feedback via a heartbeat on the red LED | ||
| 14 | //! | ||
| 15 | //! Usage: | ||
| 16 | //! 1. Flash this CM4 (secondary) core binary first | ||
| 17 | //! 2. Then flash the CM7 (primary) core binary | ||
| 18 | //! 3. The red LED should blink continuously as a heartbeat | ||
| 19 | //! 4. Green and yellow LEDs should toggle according to CM7 core signals | ||
| 20 | |||
| 21 | /// Module providing shared memory constructs for intercore communication | ||
| 5 | mod shared { | 22 | mod shared { |
| 6 | use core::sync::atomic::{AtomicU32, Ordering}; | 23 | use core::sync::atomic::{AtomicU32, Ordering}; |
| 7 | 24 | ||
| 8 | /// Shared LED state between CM7 and CM4 cores | 25 | /// State shared between CM7 and CM4 cores for LED control |
| 9 | #[repr(C, align(4))] | 26 | #[repr(C, align(4))] |
| 10 | pub struct SharedLedState { | 27 | pub struct SharedLedState { |
| 11 | // Magic number for validation | ||
| 12 | pub magic: AtomicU32, | 28 | pub magic: AtomicU32, |
| 13 | // Counter for synchronization testing | ||
| 14 | pub counter: AtomicU32, | 29 | pub counter: AtomicU32, |
| 15 | // LED states packed into a single atomic | ||
| 16 | pub led_states: AtomicU32, | 30 | pub led_states: AtomicU32, |
| 17 | } | 31 | } |
| 18 | 32 | ||
| @@ -23,19 +37,17 @@ mod shared { | |||
| 23 | impl SharedLedState { | 37 | impl SharedLedState { |
| 24 | pub const fn new() -> Self { | 38 | pub const fn new() -> Self { |
| 25 | Self { | 39 | Self { |
| 26 | magic: AtomicU32::new(0xDEADBEEF), // Magic number | 40 | magic: AtomicU32::new(0xDEADBEEF), |
| 27 | counter: AtomicU32::new(0), | 41 | counter: AtomicU32::new(0), |
| 28 | led_states: AtomicU32::new(0), | 42 | led_states: AtomicU32::new(0), |
| 29 | } | 43 | } |
| 30 | } | 44 | } |
| 31 | 45 | ||
| 32 | /// Set LED state using safe bit operations | 46 | /// Set LED state by manipulating the appropriate bit in the led_states field |
| 33 | #[inline(never)] | 47 | #[inline(never)] |
| 34 | #[allow(dead_code)] | 48 | #[allow(dead_code)] |
| 35 | pub fn set_led(&self, is_green: bool, state: bool) { | 49 | pub fn set_led(&self, is_green: bool, state: bool) { |
| 36 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; | 50 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; |
| 37 | |||
| 38 | // Use bit operations to avoid complex atomic operations | ||
| 39 | let current = self.led_states.load(Ordering::SeqCst); | 51 | let current = self.led_states.load(Ordering::SeqCst); |
| 40 | 52 | ||
| 41 | let new_value = if state { | 53 | let new_value = if state { |
| @@ -48,7 +60,7 @@ mod shared { | |||
| 48 | core::sync::atomic::fence(Ordering::SeqCst); | 60 | core::sync::atomic::fence(Ordering::SeqCst); |
| 49 | } | 61 | } |
| 50 | 62 | ||
| 51 | /// Get LED state using safe bit operations | 63 | /// Get current LED state |
| 52 | #[inline(never)] | 64 | #[inline(never)] |
| 53 | pub fn get_led(&self, is_green: bool) -> bool { | 65 | pub fn get_led(&self, is_green: bool) -> bool { |
| 54 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; | 66 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; |
| @@ -59,7 +71,7 @@ mod shared { | |||
| 59 | (value & (1 << bit)) != 0 | 71 | (value & (1 << bit)) != 0 |
| 60 | } | 72 | } |
| 61 | 73 | ||
| 62 | /// Increment counter safely | 74 | /// Increment counter and return new value |
| 63 | #[inline(never)] | 75 | #[inline(never)] |
| 64 | #[allow(dead_code)] | 76 | #[allow(dead_code)] |
| 65 | pub fn increment_counter(&self) -> u32 { | 77 | pub fn increment_counter(&self) -> u32 { |
| @@ -70,7 +82,7 @@ mod shared { | |||
| 70 | new_value | 82 | new_value |
| 71 | } | 83 | } |
| 72 | 84 | ||
| 73 | /// Get counter without incrementing | 85 | /// Get current counter value |
| 74 | #[inline(never)] | 86 | #[inline(never)] |
| 75 | pub fn get_counter(&self) -> u32 { | 87 | pub fn get_counter(&self) -> u32 { |
| 76 | let value = self.counter.load(Ordering::SeqCst); | 88 | let value = self.counter.load(Ordering::SeqCst); |
| @@ -84,19 +96,18 @@ mod shared { | |||
| 84 | } | 96 | } |
| 85 | 97 | ||
| 86 | use core::mem::MaybeUninit; | 98 | use core::mem::MaybeUninit; |
| 87 | |||
| 88 | use defmt::*; | 99 | use defmt::*; |
| 89 | use embassy_executor::Spawner; | 100 | use embassy_executor::Spawner; |
| 90 | use embassy_stm32::gpio::{Level, Output, Speed}; | 101 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 91 | use embassy_stm32::SharedData; | 102 | use embassy_stm32::SharedData; |
| 92 | use embassy_time::Timer; | 103 | use embassy_time::Timer; |
| 93 | // Use our shared state from the module | ||
| 94 | use shared::SHARED_LED_STATE; | 104 | use shared::SHARED_LED_STATE; |
| 95 | use {defmt_rtt as _, panic_probe as _}; | 105 | use {defmt_rtt as _, panic_probe as _}; |
| 96 | 106 | ||
| 97 | #[link_section = ".ram_d3"] | 107 | #[link_section = ".ram_d3"] |
| 98 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | 108 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); |
| 99 | 109 | ||
| 110 | /// Task that continuously blinks the red LED as a heartbeat indicator | ||
| 100 | #[embassy_executor::task] | 111 | #[embassy_executor::task] |
| 101 | async fn blink_heartbeat(mut led: Output<'static>) { | 112 | async fn blink_heartbeat(mut led: Output<'static>) { |
| 102 | loop { | 113 | loop { |
| @@ -112,11 +123,11 @@ async fn main(spawner: Spawner) -> ! { | |||
| 112 | let p = embassy_stm32::init_secondary(&SHARED_DATA); | 123 | let p = embassy_stm32::init_secondary(&SHARED_DATA); |
| 113 | info!("CM4 core initialized!"); | 124 | info!("CM4 core initialized!"); |
| 114 | 125 | ||
| 115 | // Read the magic value to ensure shared memory is accessible | 126 | // Verify shared memory is accessible |
| 116 | let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); | 127 | let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); |
| 117 | info!("CM4: Magic value = 0x{:X}", magic); | 128 | info!("CM4: Magic value = 0x{:X}", magic); |
| 118 | 129 | ||
| 119 | // Initialize LEDs | 130 | // Set up LEDs |
| 120 | let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1 | 131 | let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1 |
| 121 | let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2 | 132 | let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2 |
| 122 | let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat) | 133 | let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat) |
| @@ -124,31 +135,30 @@ async fn main(spawner: Spawner) -> ! { | |||
| 124 | // Start heartbeat task | 135 | // Start heartbeat task |
| 125 | unwrap!(spawner.spawn(blink_heartbeat(red_led))); | 136 | unwrap!(spawner.spawn(blink_heartbeat(red_led))); |
| 126 | 137 | ||
| 127 | // Previous values for detecting changes | 138 | // Track previous values to detect changes |
| 128 | let mut prev_green = false; | 139 | let mut prev_green = false; |
| 129 | let mut prev_yellow = false; | 140 | let mut prev_yellow = false; |
| 130 | let mut prev_counter = 0; | 141 | let mut prev_counter = 0; |
| 131 | 142 | ||
| 132 | info!("CM4: Starting main loop"); | 143 | info!("CM4: Starting main loop"); |
| 133 | loop { | 144 | loop { |
| 134 | // Read values from shared memory | 145 | // Read current values from shared memory |
| 135 | let green_state = SHARED_LED_STATE.get_led(true); | 146 | let green_state = SHARED_LED_STATE.get_led(true); |
| 136 | let yellow_state = SHARED_LED_STATE.get_led(false); | 147 | let yellow_state = SHARED_LED_STATE.get_led(false); |
| 137 | let counter = SHARED_LED_STATE.get_counter(); | 148 | let counter = SHARED_LED_STATE.get_counter(); |
| 138 | 149 | ||
| 139 | // Check for state changes | 150 | // Detect changes |
| 140 | let green_changed = green_state != prev_green; | 151 | let green_changed = green_state != prev_green; |
| 141 | let yellow_changed = yellow_state != prev_yellow; | 152 | let yellow_changed = yellow_state != prev_yellow; |
| 142 | let counter_changed = counter != prev_counter; | 153 | let counter_changed = counter != prev_counter; |
| 143 | 154 | ||
| 144 | // If any state changed, log it and update LEDs | 155 | // Update LEDs and logs when values change |
| 145 | if green_changed || yellow_changed || counter_changed { | 156 | if green_changed || yellow_changed || counter_changed { |
| 146 | if counter_changed { | 157 | if counter_changed { |
| 147 | info!("CM4: Counter = {}", counter); | 158 | info!("CM4: Counter = {}", counter); |
| 148 | prev_counter = counter; | 159 | prev_counter = counter; |
| 149 | } | 160 | } |
| 150 | 161 | ||
| 151 | // Update LED states | ||
| 152 | if green_changed { | 162 | if green_changed { |
| 153 | if green_state { | 163 | if green_state { |
| 154 | green_led.set_high(); | 164 | green_led.set_high(); |
| @@ -172,7 +182,6 @@ async fn main(spawner: Spawner) -> ! { | |||
| 172 | } | 182 | } |
| 173 | } | 183 | } |
| 174 | 184 | ||
| 175 | // Poll at a reasonable rate | ||
| 176 | Timer::after_millis(10).await; | 185 | Timer::after_millis(10).await; |
| 177 | } | 186 | } |
| 178 | } | 187 | } |
diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index f1fbd29bc..530e782ab 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs | |||
| @@ -1,6 +1,23 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | //! STM32H7 Primary Core (CM7) Intercore Communication Example | ||
| 5 | //! | ||
| 6 | //! This example demonstrates reliable communication between the Cortex-M7 and | ||
| 7 | //! Cortex-M4 cores using a shared memory region configured as non-cacheable | ||
| 8 | //! via MPU settings. | ||
| 9 | //! | ||
| 10 | //! The CM7 core handles: | ||
| 11 | //! - MPU configuration to make shared memory non-cacheable | ||
| 12 | //! - Clock initialization | ||
| 13 | //! - Toggling LED states in shared memory | ||
| 14 | //! | ||
| 15 | //! Usage: | ||
| 16 | //! 1. Flash the CM4 (secondary) core binary first | ||
| 17 | //! 2. Then flash this CM7 (primary) core binary | ||
| 18 | //! 3. The system will start with CM7 toggling LED states and CM4 responding by | ||
| 19 | //! physically toggling the LEDs | ||
| 20 | |||
| 4 | use core::mem::MaybeUninit; | 21 | use core::mem::MaybeUninit; |
| 5 | 22 | ||
| 6 | use cortex_m::asm; | 23 | use cortex_m::asm; |
| @@ -12,17 +29,15 @@ use embassy_time::Timer; | |||
| 12 | use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2}; | 29 | use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2}; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 30 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 31 | ||
| 32 | /// Module providing shared memory constructs for intercore communication | ||
| 15 | mod shared { | 33 | mod shared { |
| 16 | use core::sync::atomic::{AtomicU32, Ordering}; | 34 | use core::sync::atomic::{AtomicU32, Ordering}; |
| 17 | 35 | ||
| 18 | /// Shared LED state between CM7 and CM4 cores | 36 | /// State shared between CM7 and CM4 cores for LED control |
| 19 | #[repr(C, align(4))] | 37 | #[repr(C, align(4))] |
| 20 | pub struct SharedLedState { | 38 | pub struct SharedLedState { |
| 21 | // Magic number for validation | ||
| 22 | pub magic: AtomicU32, | 39 | pub magic: AtomicU32, |
| 23 | // Counter for synchronization testing | ||
| 24 | pub counter: AtomicU32, | 40 | pub counter: AtomicU32, |
| 25 | // LED states packed into a single atomic | ||
| 26 | pub led_states: AtomicU32, | 41 | pub led_states: AtomicU32, |
| 27 | } | 42 | } |
| 28 | 43 | ||
| @@ -33,18 +48,16 @@ mod shared { | |||
| 33 | impl SharedLedState { | 48 | impl SharedLedState { |
| 34 | pub const fn new() -> Self { | 49 | pub const fn new() -> Self { |
| 35 | Self { | 50 | Self { |
| 36 | magic: AtomicU32::new(0xDEADBEEF), // Magic number | 51 | magic: AtomicU32::new(0xDEADBEEF), |
| 37 | counter: AtomicU32::new(0), | 52 | counter: AtomicU32::new(0), |
| 38 | led_states: AtomicU32::new(0), | 53 | led_states: AtomicU32::new(0), |
| 39 | } | 54 | } |
| 40 | } | 55 | } |
| 41 | 56 | ||
| 42 | /// Set LED state using safe bit operations | 57 | /// Set LED state by manipulating the appropriate bit in the led_states field |
| 43 | #[inline(never)] | 58 | #[inline(never)] |
| 44 | pub fn set_led(&self, is_green: bool, state: bool) { | 59 | pub fn set_led(&self, is_green: bool, state: bool) { |
| 45 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; | 60 | let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; |
| 46 | |||
| 47 | // Use bit operations to avoid complex atomic operations | ||
| 48 | let current = self.led_states.load(Ordering::SeqCst); | 61 | let current = self.led_states.load(Ordering::SeqCst); |
| 49 | 62 | ||
| 50 | let new_value = if state { | 63 | let new_value = if state { |
| @@ -57,7 +70,7 @@ mod shared { | |||
| 57 | core::sync::atomic::compiler_fence(Ordering::SeqCst); | 70 | core::sync::atomic::compiler_fence(Ordering::SeqCst); |
| 58 | } | 71 | } |
| 59 | 72 | ||
| 60 | /// Get LED state using safe bit operations | 73 | /// Get current LED state |
| 61 | #[inline(never)] | 74 | #[inline(never)] |
| 62 | #[allow(dead_code)] | 75 | #[allow(dead_code)] |
| 63 | pub fn get_led(&self, is_green: bool) -> bool { | 76 | pub fn get_led(&self, is_green: bool) -> bool { |
| @@ -69,7 +82,7 @@ mod shared { | |||
| 69 | (value & (1 << bit)) != 0 | 82 | (value & (1 << bit)) != 0 |
| 70 | } | 83 | } |
| 71 | 84 | ||
| 72 | /// Increment counter safely | 85 | /// Increment counter and return new value |
| 73 | #[inline(never)] | 86 | #[inline(never)] |
| 74 | pub fn increment_counter(&self) -> u32 { | 87 | pub fn increment_counter(&self) -> u32 { |
| 75 | let current = self.counter.load(Ordering::SeqCst); | 88 | let current = self.counter.load(Ordering::SeqCst); |
| @@ -79,7 +92,7 @@ mod shared { | |||
| 79 | new_value | 92 | new_value |
| 80 | } | 93 | } |
| 81 | 94 | ||
| 82 | /// Get counter without incrementing | 95 | /// Get current counter value |
| 83 | #[inline(never)] | 96 | #[inline(never)] |
| 84 | #[allow(dead_code)] | 97 | #[allow(dead_code)] |
| 85 | pub fn get_counter(&self) -> u32 { | 98 | pub fn get_counter(&self) -> u32 { |
| @@ -92,37 +105,29 @@ mod shared { | |||
| 92 | #[link_section = ".ram_d3"] | 105 | #[link_section = ".ram_d3"] |
| 93 | pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); | 106 | pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); |
| 94 | 107 | ||
| 95 | // SRAM4 memory region constants for MPU configuration | 108 | // Memory region constants for MPU configuration |
| 96 | pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000; | 109 | pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000; |
| 97 | pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1) | 110 | pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1) |
| 98 | pub const SRAM4_REGION_NUMBER: u8 = 0; // MPU region number to use | 111 | pub const SRAM4_REGION_NUMBER: u8 = 0; |
| 99 | } | 112 | } |
| 100 | 113 | ||
| 101 | #[link_section = ".ram_d3"] | 114 | #[link_section = ".ram_d3"] |
| 102 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | 115 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); |
| 103 | 116 | ||
| 104 | // Function to configure MPU with your provided settings | 117 | /// Configure MPU to make SRAM4 region non-cacheable |
| 105 | fn configure_mpu_non_cacheable(mpu: &mut MPU) { | 118 | fn configure_mpu_non_cacheable(mpu: &mut MPU) { |
| 106 | // Ensure all operations complete before reconfiguring MPU/caches | ||
| 107 | asm::dmb(); | 119 | asm::dmb(); |
| 108 | unsafe { | 120 | unsafe { |
| 109 | // Disable MPU | 121 | // Disable MPU |
| 110 | mpu.ctrl.write(0); | 122 | mpu.ctrl.write(0); |
| 111 | 123 | ||
| 112 | // Configure SRAM4 as non-cacheable | 124 | // Configure SRAM4 as non-cacheable |
| 113 | // Set region number (0) | ||
| 114 | mpu.rnr.write(SRAM4_REGION_NUMBER as u32); | 125 | mpu.rnr.write(SRAM4_REGION_NUMBER as u32); |
| 115 | 126 | ||
| 116 | // Set base address (SRAM4 = 0x38000000) with VALID bit and region number | 127 | // Set base address with region number |
| 117 | mpu.rbar.write( | 128 | mpu.rbar.write(SRAM4_BASE_ADDRESS | (1 << 4)); |
| 118 | SRAM4_BASE_ADDRESS | (1 << 4), // Region number = 0 (explicit in RBAR) | ||
| 119 | ); | ||
| 120 | 129 | ||
| 121 | // Configure region attributes: | 130 | // Configure region attributes |
| 122 | // SIZE=15 (64KB = 2^(15+1)) | ||
| 123 | // ENABLE=1 | ||
| 124 | // AP=3 (Full access) | ||
| 125 | // TEX=1, S=1, C=0, B=0 (Normal memory, Non-cacheable, Shareable) | ||
| 126 | let rasr_value: u32 = (SRAM4_SIZE_LOG2 << 1) | // SIZE=15 (64KB) | 131 | let rasr_value: u32 = (SRAM4_SIZE_LOG2 << 1) | // SIZE=15 (64KB) |
| 127 | (1 << 0) | // ENABLE=1 | 132 | (1 << 0) | // ENABLE=1 |
| 128 | (3 << 24) | // AP=3 (Full access) | 133 | (3 << 24) | // AP=3 (Full access) |
| @@ -135,7 +140,6 @@ fn configure_mpu_non_cacheable(mpu: &mut MPU) { | |||
| 135 | mpu.ctrl.write(1 | (1 << 2)); // MPU_ENABLE | PRIVDEFENA | 140 | mpu.ctrl.write(1 | (1 << 2)); // MPU_ENABLE | PRIVDEFENA |
| 136 | } | 141 | } |
| 137 | 142 | ||
| 138 | // Ensure changes are committed | ||
| 139 | asm::dsb(); | 143 | asm::dsb(); |
| 140 | asm::isb(); | 144 | asm::isb(); |
| 141 | 145 | ||
| @@ -144,25 +148,26 @@ fn configure_mpu_non_cacheable(mpu: &mut MPU) { | |||
| 144 | 148 | ||
| 145 | #[embassy_executor::main] | 149 | #[embassy_executor::main] |
| 146 | async fn main(_spawner: Spawner) -> ! { | 150 | async fn main(_spawner: Spawner) -> ! { |
| 147 | // Configure MPU to make SRAM4 non-cacheable | 151 | // Set up MPU and cache configuration |
| 148 | { | 152 | { |
| 149 | let mut cp = cortex_m::Peripherals::take().unwrap(); | 153 | let mut cp = cortex_m::Peripherals::take().unwrap(); |
| 150 | let scb = &mut cp.SCB; | 154 | let scb = &mut cp.SCB; |
| 151 | 155 | ||
| 156 | // First disable caches | ||
| 152 | scb.disable_icache(); | 157 | scb.disable_icache(); |
| 153 | scb.disable_dcache(&mut cp.CPUID); | 158 | scb.disable_dcache(&mut cp.CPUID); |
| 154 | 159 | ||
| 155 | // 2. MPU setup | 160 | // Configure MPU |
| 156 | configure_mpu_non_cacheable(&mut cp.MPU); | 161 | configure_mpu_non_cacheable(&mut cp.MPU); |
| 157 | 162 | ||
| 158 | // 3. re-enable caches | 163 | // Re-enable caches |
| 159 | scb.enable_icache(); | 164 | scb.enable_icache(); |
| 160 | scb.enable_dcache(&mut cp.CPUID); | 165 | scb.enable_dcache(&mut cp.CPUID); |
| 161 | asm::dsb(); | 166 | asm::dsb(); |
| 162 | asm::isb(); | 167 | asm::isb(); |
| 163 | } | 168 | } |
| 164 | 169 | ||
| 165 | // Configure the clocks | 170 | // Configure the clock system |
| 166 | let mut config = Config::default(); | 171 | let mut config = Config::default(); |
| 167 | { | 172 | { |
| 168 | use embassy_stm32::rcc::*; | 173 | use embassy_stm32::rcc::*; |
| @@ -191,42 +196,38 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 191 | let _p = embassy_stm32::init_primary(config, &SHARED_DATA); | 196 | let _p = embassy_stm32::init_primary(config, &SHARED_DATA); |
| 192 | info!("CM7 core initialized with non-cacheable SRAM4!"); | 197 | info!("CM7 core initialized with non-cacheable SRAM4!"); |
| 193 | 198 | ||
| 194 | // Read the magic value to ensure shared memory is accessible | 199 | // Verify shared memory is accessible |
| 195 | let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); | 200 | let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); |
| 196 | info!("CM7: Magic value = 0x{:X}", magic); | 201 | info!("CM7: Magic value = 0x{:X}", magic); |
| 197 | 202 | ||
| 198 | // Initialize shared memory state | 203 | // Initialize LED states |
| 199 | SHARED_LED_STATE.set_led(true, false); // Green LED off | 204 | SHARED_LED_STATE.set_led(true, false); // Green LED off |
| 200 | SHARED_LED_STATE.set_led(false, false); // Yellow LED off | 205 | SHARED_LED_STATE.set_led(false, false); // Yellow LED off |
| 201 | 206 | ||
| 202 | // Main loop - update shared memory values | 207 | // Main loop - periodically toggle LED states |
| 203 | let mut green_state = false; | 208 | let mut green_state = false; |
| 204 | let mut yellow_state = false; | 209 | let mut yellow_state = false; |
| 205 | let mut loop_count = 0; | 210 | let mut loop_count = 0; |
| 206 | 211 | ||
| 207 | info!("CM7: Starting main loop"); | 212 | info!("CM7: Starting main loop"); |
| 208 | loop { | 213 | loop { |
| 209 | // Update loop counter | ||
| 210 | loop_count += 1; | 214 | loop_count += 1; |
| 211 | |||
| 212 | // Update shared counter | ||
| 213 | let counter = SHARED_LED_STATE.increment_counter(); | 215 | let counter = SHARED_LED_STATE.increment_counter(); |
| 214 | 216 | ||
| 215 | // Every second, toggle green LED state | 217 | // Toggle green LED every second |
| 216 | if loop_count % 10 == 0 { | 218 | if loop_count % 10 == 0 { |
| 217 | green_state = !green_state; | 219 | green_state = !green_state; |
| 218 | SHARED_LED_STATE.set_led(true, green_state); | 220 | SHARED_LED_STATE.set_led(true, green_state); |
| 219 | info!("CM7: Counter = {}, Set green LED to {}", counter, green_state); | 221 | info!("CM7: Counter = {}, Set green LED to {}", counter, green_state); |
| 220 | } | 222 | } |
| 221 | 223 | ||
| 222 | // Every 3 seconds, toggle yellow LED state | 224 | // Toggle yellow LED every 3 seconds |
| 223 | if loop_count % 30 == 0 { | 225 | if loop_count % 30 == 0 { |
| 224 | yellow_state = !yellow_state; | 226 | yellow_state = !yellow_state; |
| 225 | SHARED_LED_STATE.set_led(false, yellow_state); | 227 | SHARED_LED_STATE.set_led(false, yellow_state); |
| 226 | info!("CM7: Counter = {}, Set yellow LED to {}", counter, yellow_state); | 228 | info!("CM7: Counter = {}, Set yellow LED to {}", counter, yellow_state); |
| 227 | } | 229 | } |
| 228 | 230 | ||
| 229 | // Wait 100ms before next cycle | ||
| 230 | Timer::after_millis(100).await; | 231 | Timer::after_millis(100).await; |
| 231 | } | 232 | } |
| 232 | } | 233 | } |
