aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-05-21 21:34:50 +0000
committerGitHub <[email protected]>2024-05-21 21:34:50 +0000
commitae49e58993ff12ba3d4c9a8dc1140aa551f3c7c3 (patch)
tree52c2c9e164561659e2bc4fe11e7eb3d383574319
parent4b5026e197ae681ae2e3e5d9f4ce913a4d9ff7d9 (diff)
parentafd61ed610293b1f41bc926bf3a0fa35d78a8815 (diff)
Merge pull request #2777 from taunusflieger/feature/HSEM
HSEM support for embassy-stm32
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/hsem/mod.rs182
-rw-r--r--embassy-stm32/src/lib.rs2
3 files changed, 186 insertions, 2 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index a7137d132..5ef2366d9 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -72,7 +72,7 @@ rand_core = "0.6.3"
72sdio-host = "0.5.0" 72sdio-host = "0.5.0"
73critical-section = "1.1" 73critical-section = "1.1"
74#stm32-metapac = { version = "15" } 74#stm32-metapac = { version = "15" }
75stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f1297385e91f061fcb6134bb25f51e12d8abff93" } 75stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-34c0188a682b32c32ff147d377e0629b1ebe8318" }
76 76
77vcell = "0.1.3" 77vcell = "0.1.3"
78nb = "1.0.0" 78nb = "1.0.0"
@@ -97,7 +97,7 @@ proc-macro2 = "1.0.36"
97quote = "1.0.15" 97quote = "1.0.15"
98 98
99#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} 99#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
100stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f1297385e91f061fcb6134bb25f51e12d8abff93", default-features = false, features = ["metadata"]} 100stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-34c0188a682b32c32ff147d377e0629b1ebe8318", default-features = false, features = ["metadata"]}
101 101
102[features] 102[features]
103default = ["rt"] 103default = ["rt"]
diff --git a/embassy-stm32/src/hsem/mod.rs b/embassy-stm32/src/hsem/mod.rs
new file mode 100644
index 000000000..b77a3415b
--- /dev/null
+++ b/embassy-stm32/src/hsem/mod.rs
@@ -0,0 +1,182 @@
1//! Hardware Semaphore (HSEM)
2
3// TODO: This code works for all HSEM implemenations except for the STM32WBA52/4/5xx MCUs.
4// Those MCUs have a different HSEM implementation (Secure semaphore lock support,
5// Privileged / unprivileged semaphore lock support, Semaphore lock protection via semaphore attribute),
6// which is not yet supported by this code.
7use embassy_hal_internal::{into_ref, PeripheralRef};
8
9use crate::rcc::RccPeripheral;
10use crate::{pac, Peripheral};
11
12/// HSEM error.
13#[derive(Debug)]
14pub enum HsemError {
15 /// Locking the semaphore failed.
16 LockFailed,
17}
18
19/// CPU core.
20/// The enum values are identical to the bus master IDs / core Ids defined for each
21/// chip family (i.e. stm32h747 see rm0399 table 95)
22#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
23#[repr(u8)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub enum CoreId {
26 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
27 /// Cortex-M7, core 1.
28 Core0 = 0x3,
29
30 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
31 /// Cortex-M4, core 2.
32 Core1 = 0x1,
33
34 #[cfg(not(any(stm32h745, stm32h747, stm32h755, stm32h757)))]
35 /// Cortex-M4, core 1
36 Core0 = 0x4,
37
38 #[cfg(any(stm32wb, stm32wl))]
39 /// Cortex-M0+, core 2.
40 Core1 = 0x8,
41}
42
43/// Get the current core id
44/// This code assume that it is only executed on a Cortex-M M0+, M4 or M7 core.
45#[inline(always)]
46pub fn get_current_coreid() -> CoreId {
47 let cpuid = unsafe { cortex_m::peripheral::CPUID::PTR.read_volatile().base.read() };
48 match cpuid & 0x000000F0 {
49 #[cfg(any(stm32wb, stm32wl))]
50 0x0 => CoreId::Core1,
51
52 #[cfg(not(any(stm32h745, stm32h747, stm32h755, stm32h757)))]
53 0x4 => CoreId::Core0,
54
55 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
56 0x4 => CoreId::Core1,
57
58 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
59 0x7 => CoreId::Core0,
60 _ => panic!("Unknown Cortex-M core"),
61 }
62}
63
64/// Translates the core ID to an index into the interrupt registers.
65#[inline(always)]
66fn core_id_to_index(core: CoreId) -> usize {
67 match core {
68 CoreId::Core0 => 0,
69 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757, stm32wb, stm32wl))]
70 CoreId::Core1 => 1,
71 }
72}
73
74/// HSEM driver
75pub struct HardwareSemaphore<'d, T: Instance> {
76 _peri: PeripheralRef<'d, T>,
77}
78
79impl<'d, T: Instance> HardwareSemaphore<'d, T> {
80 /// Creates a new HardwareSemaphore instance.
81 pub fn new(peripheral: impl Peripheral<P = T> + 'd) -> Self {
82 into_ref!(peripheral);
83 HardwareSemaphore { _peri: peripheral }
84 }
85
86 /// Locks the semaphore.
87 /// The 2-step lock procedure consists in a write to lock the semaphore, followed by a read to
88 /// check if the lock has been successful, carried out from the HSEM_Rx register.
89 pub fn two_step_lock(&mut self, sem_id: u8, process_id: u8) -> Result<(), HsemError> {
90 T::regs().r(sem_id as usize).write(|w| {
91 w.set_procid(process_id);
92 w.set_coreid(get_current_coreid() as u8);
93 w.set_lock(true);
94 });
95 let reg = T::regs().r(sem_id as usize).read();
96 match (
97 reg.lock(),
98 reg.coreid() == get_current_coreid() as u8,
99 reg.procid() == process_id,
100 ) {
101 (true, true, true) => Ok(()),
102 _ => Err(HsemError::LockFailed),
103 }
104 }
105
106 /// Locks the semaphore.
107 /// The 1-step procedure consists in a read to lock and check the semaphore in a single step,
108 /// carried out from the HSEM_RLRx register.
109 pub fn one_step_lock(&mut self, sem_id: u8) -> Result<(), HsemError> {
110 let reg = T::regs().rlr(sem_id as usize).read();
111 match (reg.lock(), reg.coreid() == get_current_coreid() as u8, reg.procid()) {
112 (false, true, 0) => Ok(()),
113 _ => Err(HsemError::LockFailed),
114 }
115 }
116
117 /// Unlocks the semaphore.
118 /// Unlocking a semaphore is a protected process, to prevent accidental clearing by a AHB bus
119 /// core ID or by a process not having the semaphore lock right.
120 pub fn unlock(&mut self, sem_id: u8, process_id: u8) {
121 T::regs().r(sem_id as usize).write(|w| {
122 w.set_procid(process_id);
123 w.set_coreid(get_current_coreid() as u8);
124 w.set_lock(false);
125 });
126 }
127
128 /// Unlocks all semaphores.
129 /// All semaphores locked by a COREID can be unlocked at once by using the HSEM_CR
130 /// register. Write COREID and correct KEY value in HSEM_CR. All locked semaphores with a
131 /// matching COREID are unlocked, and may generate an interrupt when enabled.
132 pub fn unlock_all(&mut self, key: u16, core_id: u8) {
133 T::regs().cr().write(|w| {
134 w.set_key(key);
135 w.set_coreid(core_id);
136 });
137 }
138
139 /// Checks if the semaphore is locked.
140 pub fn is_semaphore_locked(&self, sem_id: u8) -> bool {
141 T::regs().r(sem_id as usize).read().lock()
142 }
143
144 /// Sets the clear (unlock) key
145 pub fn set_clear_key(&mut self, key: u16) {
146 T::regs().keyr().modify(|w| w.set_key(key));
147 }
148
149 /// Gets the clear (unlock) key
150 pub fn get_clear_key(&mut self) -> u16 {
151 T::regs().keyr().read().key()
152 }
153
154 /// Sets the interrupt enable bit for the semaphore.
155 pub fn enable_interrupt(&mut self, core_id: CoreId, sem_x: usize, enable: bool) {
156 T::regs()
157 .ier(core_id_to_index(core_id))
158 .modify(|w| w.set_ise(sem_x, enable));
159 }
160
161 /// Clears the interrupt flag for the semaphore.
162 pub fn clear_interrupt(&mut self, core_id: CoreId, sem_x: usize) {
163 T::regs()
164 .icr(core_id_to_index(core_id))
165 .write(|w| w.set_isc(sem_x, false));
166 }
167}
168
169trait SealedInstance {
170 fn regs() -> pac::hsem::Hsem;
171}
172
173/// HSEM instance trait.
174#[allow(private_bounds)]
175pub trait Instance: SealedInstance + RccPeripheral + Send + 'static {}
176
177impl SealedInstance for crate::peripherals::HSEM {
178 fn regs() -> crate::pac::hsem::Hsem {
179 crate::pac::HSEM
180 }
181}
182impl Instance for crate::peripherals::HSEM {}
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index b4b9d5d12..81ee60c1c 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -79,6 +79,8 @@ pub mod fmc;
79pub mod hash; 79pub mod hash;
80#[cfg(hrtim)] 80#[cfg(hrtim)]
81pub mod hrtim; 81pub mod hrtim;
82#[cfg(hsem)]
83pub mod hsem;
82#[cfg(i2c)] 84#[cfg(i2c)]
83pub mod i2c; 85pub mod i2c;
84#[cfg(all(spi_v1, rcc_f4))] 86#[cfg(all(spi_v1, rcc_f4))]