aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32h755cm4/src/bin/intercore.rs
diff options
context:
space:
mode:
authorragarnoy <[email protected]>2025-05-10 10:40:35 +0200
committerragarnoy <[email protected]>2025-05-10 10:40:35 +0200
commitf28934cb46bd18cf362b988471266e1b7bb9927e (patch)
tree68f0226806987fc000dfe85f15a7dc86f6775329 /examples/stm32h755cm4/src/bin/intercore.rs
parent04c0bd84e6043ac35d2a20f1f4a789ccf79bb316 (diff)
Rewrite documentation and generally improve it
Diffstat (limited to 'examples/stm32h755cm4/src/bin/intercore.rs')
-rw-r--r--examples/stm32h755cm4/src/bin/intercore.rs53
1 files changed, 31 insertions, 22 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
5mod shared { 22mod 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
86use core::mem::MaybeUninit; 98use core::mem::MaybeUninit;
87
88use defmt::*; 99use defmt::*;
89use embassy_executor::Spawner; 100use embassy_executor::Spawner;
90use embassy_stm32::gpio::{Level, Output, Speed}; 101use embassy_stm32::gpio::{Level, Output, Speed};
91use embassy_stm32::SharedData; 102use embassy_stm32::SharedData;
92use embassy_time::Timer; 103use embassy_time::Timer;
93// Use our shared state from the module
94use shared::SHARED_LED_STATE; 104use shared::SHARED_LED_STATE;
95use {defmt_rtt as _, panic_probe as _}; 105use {defmt_rtt as _, panic_probe as _};
96 106
97#[link_section = ".ram_d3"] 107#[link_section = ".ram_d3"]
98static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); 108static 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]
101async fn blink_heartbeat(mut led: Output<'static>) { 112async 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}