aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32h755cm4/src
diff options
context:
space:
mode:
authorragarnoy <[email protected]>2025-05-10 02:17:54 +0200
committerragarnoy <[email protected]>2025-05-10 02:17:54 +0200
commit90404a8e524a0d06ce35230dea7ff4d3e4d0375a (patch)
treeec9e17c3e2f18fe50ecdc7ce7d9182b443614872 /examples/stm32h755cm4/src
parentf9f20ae2174cb26d0f8926207d179041cfec2d2e (diff)
Add intercore communication examples for STM32H755CM4 and CM7, does not work in release for now (for some reason)
Diffstat (limited to 'examples/stm32h755cm4/src')
-rw-r--r--examples/stm32h755cm4/src/bin/intercore.rs181
1 files changed, 181 insertions, 0 deletions
diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs
new file mode 100644
index 000000000..08cf6c7b9
--- /dev/null
+++ b/examples/stm32h755cm4/src/bin/intercore.rs
@@ -0,0 +1,181 @@
1#![no_std]
2#![no_main]
3
4// IMPORTANT: This must match EXACTLY the definition in CM7!
5mod shared {
6 use core::sync::atomic::{AtomicU32, Ordering};
7
8 /// Shared LED state between CM7 and CM4 cores
9 #[repr(C, align(4))]
10 pub struct SharedLedState {
11 // Magic number for validation
12 pub magic: AtomicU32,
13 // Counter for synchronization testing
14 pub counter: AtomicU32,
15 // LED states packed into a single atomic
16 pub led_states: AtomicU32,
17 }
18
19 // Bit positions in led_states
20 pub const GREEN_LED_BIT: u32 = 0;
21 pub const YELLOW_LED_BIT: u32 = 1;
22
23 impl SharedLedState {
24 pub const fn new() -> Self {
25 Self {
26 magic: AtomicU32::new(0xDEADBEEF), // Magic number
27 counter: AtomicU32::new(0),
28 led_states: AtomicU32::new(0),
29 }
30 }
31
32 /// Set LED state using safe bit operations
33 #[inline(never)]
34 pub fn set_led(&self, is_green: bool, state: bool) {
35 let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
36
37 // Use bit operations to avoid complex atomic operations
38 let current = self.led_states.load(Ordering::SeqCst);
39
40 let new_value = if state {
41 current | (1 << bit) // Set bit
42 } else {
43 current & !(1 << bit) // Clear bit
44 };
45
46 self.led_states.store(new_value, Ordering::SeqCst);
47 core::sync::atomic::compiler_fence(Ordering::SeqCst);
48 }
49
50 /// Get LED state using safe bit operations
51 #[inline(never)]
52 pub fn get_led(&self, is_green: bool) -> bool {
53 let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
54
55 let value = self.led_states.load(Ordering::SeqCst);
56 core::sync::atomic::compiler_fence(Ordering::SeqCst);
57
58 (value & (1 << bit)) != 0
59 }
60
61 /// Increment counter safely
62 #[inline(never)]
63 pub fn increment_counter(&self) -> u32 {
64 let current = self.counter.load(Ordering::SeqCst);
65 let new_value = current.wrapping_add(1);
66 self.counter.store(new_value, Ordering::SeqCst);
67 core::sync::atomic::compiler_fence(Ordering::SeqCst);
68 new_value
69 }
70
71 /// Get counter without incrementing
72 #[inline(never)]
73 pub fn get_counter(&self) -> u32 {
74 let value = self.counter.load(Ordering::SeqCst);
75 core::sync::atomic::compiler_fence(Ordering::SeqCst);
76 value
77 }
78 }
79
80 #[link_section = ".ram_d3"]
81 pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new();
82
83 // SRAM4 memory region constants for MPU configuration
84 pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000;
85 pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1)
86 pub const SRAM4_REGION_NUMBER: u8 = 0; // MPU region number to use
87}
88
89use core::mem::MaybeUninit;
90use defmt::*;
91use embassy_executor::Spawner;
92use embassy_stm32::gpio::{Level, Output, Speed};
93use embassy_stm32::SharedData;
94use embassy_time::Timer;
95use {defmt_rtt as _, panic_probe as _};
96
97// Use our shared state from the module
98use shared::SHARED_LED_STATE;
99
100#[link_section = ".ram_d3"]
101static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
102
103#[embassy_executor::task]
104async fn blink_heartbeat(mut led: Output<'static>) {
105 loop {
106 led.toggle();
107 info!("CM4 heartbeat");
108 Timer::after_millis(500).await;
109 }
110}
111
112#[embassy_executor::main]
113async fn main(spawner: Spawner) -> ! {
114 // Initialize the secondary core
115 let p = embassy_stm32::init_secondary(&SHARED_DATA);
116 info!("CM4 core initialized!");
117
118 // Read the magic value to ensure shared memory is accessible
119 let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst);
120 info!("CM4: Magic value = 0x{:X}", magic);
121
122 // Initialize LEDs
123 let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1
124 let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2
125 let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat)
126
127 // Start heartbeat task
128 unwrap!(spawner.spawn(blink_heartbeat(red_led)));
129
130 // Previous values for detecting changes
131 let mut prev_green = false;
132 let mut prev_yellow = false;
133 let mut prev_counter = 0;
134
135 info!("CM4: Starting main loop");
136 loop {
137 // Read values from shared memory
138 let green_state = SHARED_LED_STATE.get_led(true);
139 let yellow_state = SHARED_LED_STATE.get_led(false);
140 let counter = SHARED_LED_STATE.get_counter();
141
142 // Check for state changes
143 let green_changed = green_state != prev_green;
144 let yellow_changed = yellow_state != prev_yellow;
145 let counter_changed = counter != prev_counter;
146
147 // If any state changed, log it and update LEDs
148 if green_changed || yellow_changed || counter_changed {
149 if counter_changed {
150 info!("CM4: Counter = {}", counter);
151 prev_counter = counter;
152 }
153
154 // Update LED states
155 if green_changed {
156 if green_state {
157 green_led.set_high();
158 info!("CM4: Green LED ON");
159 } else {
160 green_led.set_low();
161 info!("CM4: Green LED OFF");
162 }
163 prev_green = green_state;
164 }
165
166 if yellow_changed {
167 if yellow_state {
168 yellow_led.set_high();
169 info!("CM4: Yellow LED ON");
170 } else {
171 yellow_led.set_low();
172 info!("CM4: Yellow LED OFF");
173 }
174 prev_yellow = yellow_state;
175 }
176 }
177
178 // Poll at a reasonable rate
179 Timer::after_millis(10).await;
180 }
181} \ No newline at end of file