aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32h755cm4
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
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')
-rw-r--r--examples/stm32h755cm4/Cargo.toml17
-rw-r--r--examples/stm32h755cm4/src/bin/intercore.rs181
2 files changed, 186 insertions, 12 deletions
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml
index 7c17bc766..c6d4996f1 100644
--- a/examples/stm32h755cm4/Cargo.toml
+++ b/examples/stm32h755cm4/Cargo.toml
@@ -15,8 +15,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm
15embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
17 17
18defmt = "0.3" 18defmt = "1.0.1"
19defmt-rtt = "0.4" 19defmt-rtt = "1.0.0"
20 20
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 22cortex-m-rt = "0.7.0"
@@ -25,7 +25,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" } 25embedded-hal-async = { version = "1.0" }
26embedded-nal-async = "0.8.0" 26embedded-nal-async = "0.8.0"
27embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.6.1" }
28panic-probe = { version = "0.3", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30rand_core = "0.6.3" 30rand_core = "0.6.3"
31critical-section = "1.1" 31critical-section = "1.1"
@@ -37,13 +37,6 @@ chrono = { version = "^0.4", default-features = false }
37grounded = "0.2.0" 37grounded = "0.2.0"
38 38
39# cargo build/run 39# cargo build/run
40[profile.dev]
41codegen-units = 1
42debug = 2
43debug-assertions = true # <-
44incremental = false
45opt-level = 3 # <-
46overflow-checks = true # <-
47 40
48# cargo test 41# cargo test
49[profile.test] 42[profile.test]
@@ -60,8 +53,8 @@ codegen-units = 1
60debug = 2 53debug = 2
61debug-assertions = false # <- 54debug-assertions = false # <-
62incremental = false 55incremental = false
63lto = 'fat' 56#lto = 'fat'
64opt-level = 3 # <- 57#opt-level = 3 # <-
65overflow-checks = false # <- 58overflow-checks = false # <-
66 59
67# cargo test --release 60# cargo test --release
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