aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh1
-rw-r--r--embassy-embedded-hal/Cargo.toml10
-rw-r--r--embassy-embedded-hal/src/adapter/blocking_async.rs (renamed from embassy-embedded-hal/src/adapter.rs)2
-rw-r--r--embassy-embedded-hal/src/adapter/mod.rs7
-rw-r--r--embassy-embedded-hal/src/adapter/yielding_async.rs232
-rw-r--r--embassy-embedded-hal/src/flash.rs286
-rw-r--r--embassy-embedded-hal/src/lib.rs2
-rw-r--r--embassy-lora/src/iv.rs36
-rw-r--r--embassy-stm32/build.rs4
-rw-r--r--embassy-stm32/src/dcmi.rs98
-rw-r--r--embassy-stm32/src/eth/mod.rs2
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs53
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs53
-rw-r--r--embassy-stm32/src/i2c/v1.rs13
-rw-r--r--embassy-stm32/src/i2c/v2.rs49
-rw-r--r--embassy-stm32/src/i2s.rs310
-rw-r--r--embassy-stm32/src/interrupt.rs4
-rw-r--r--embassy-stm32/src/lib.rs38
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs91
-rw-r--r--embassy-stm32/src/spi/mod.rs15
-rw-r--r--embassy-stm32/src/time_driver.rs3
-rw-r--r--embassy-stm32/src/tl_mbox/mod.rs58
-rw-r--r--embassy-stm32/src/usart/buffered.rs157
-rw-r--r--embassy-stm32/src/usart/mod.rs164
-rw-r--r--embassy-stm32/src/usb/usb.rs180
-rw-r--r--embassy-stm32/src/usb_otg/usb.rs317
-rw-r--r--embassy-stm32/src/wdg/mod.rs40
-rw-r--r--examples/stm32f1/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32f3/src/bin/usart_dma.rs9
-rw-r--r--examples/stm32f3/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32f4/src/bin/i2c.rs9
-rw-r--r--examples/stm32f4/src/bin/i2s_dma.rs36
-rw-r--r--examples/stm32f4/src/bin/sdmmc.rs10
-rw-r--r--examples/stm32f4/src/bin/usart.rs9
-rw-r--r--examples/stm32f4/src/bin/usart_buffered.rs9
-rw-r--r--examples/stm32f4/src/bin/usart_dma.rs9
-rw-r--r--examples/stm32f4/src/bin/usb_ethernet.rs9
-rw-r--r--examples/stm32f4/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32f7/src/bin/eth.rs9
-rw-r--r--examples/stm32f7/src/bin/sdmmc.rs10
-rw-r--r--examples/stm32f7/src/bin/usart_dma.rs9
-rw-r--r--examples/stm32f7/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32h5/src/bin/eth.rs9
-rw-r--r--examples/stm32h5/src/bin/i2c.rs9
-rw-r--r--examples/stm32h5/src/bin/usart.rs9
-rw-r--r--examples/stm32h5/src/bin/usart_dma.rs9
-rw-r--r--examples/stm32h5/src/bin/usart_split.rs9
-rw-r--r--examples/stm32h5/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32h7/src/bin/camera.rs14
-rw-r--r--examples/stm32h7/src/bin/eth.rs9
-rw-r--r--examples/stm32h7/src/bin/eth_client.rs9
-rw-r--r--examples/stm32h7/src/bin/i2c.rs9
-rw-r--r--examples/stm32h7/src/bin/sdmmc.rs10
-rw-r--r--examples/stm32h7/src/bin/usart.rs9
-rw-r--r--examples/stm32h7/src/bin/usart_dma.rs9
-rw-r--r--examples/stm32h7/src/bin/usart_split.rs9
-rw-r--r--examples/stm32h7/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32l0/src/bin/usart_dma.rs9
-rw-r--r--examples/stm32l0/src/bin/usart_irq.rs9
-rw-r--r--examples/stm32l4/src/bin/i2c.rs9
-rw-r--r--examples/stm32l4/src/bin/i2c_blocking_async.rs9
-rw-r--r--examples/stm32l4/src/bin/i2c_dma.rs9
-rw-r--r--examples/stm32l4/src/bin/usart.rs9
-rw-r--r--examples/stm32l4/src/bin/usart_dma.rs9
-rw-r--r--examples/stm32l4/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs9
-rw-r--r--examples/stm32l5/src/bin/usb_hid_mouse.rs9
-rw-r--r--examples/stm32l5/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32u5/src/bin/usb_serial.rs9
-rw-r--r--examples/stm32wb/src/bin/tl_mbox.rs12
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_tx_rx.rs12
-rw-r--r--examples/stm32wl/src/bin/lora_lorawan.rs12
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_receive.rs12
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_send.rs12
-rw-r--r--examples/stm32wl/src/bin/uart_async.rs15
-rw-r--r--tests/stm32/src/bin/sdmmc.rs23
-rw-r--r--tests/stm32/src/bin/usart.rs52
-rw-r--r--tests/stm32/src/bin/usart_dma.rs85
-rw-r--r--tests/stm32/src/bin/usart_rx_ringbuffered.rs79
79 files changed, 2060 insertions, 892 deletions
diff --git a/ci.sh b/ci.sh
index d2bf4df97..2c46dcc6b 100755
--- a/ci.sh
+++ b/ci.sh
@@ -143,6 +143,7 @@ cargo batch \
143 $BUILD_EXTRA 143 $BUILD_EXTRA
144 144
145 145
146
146function run_elf { 147function run_elf {
147 echo Running target=$1 elf=$2 148 echo Running target=$1 elf=$2
148 STATUSCODE=$( 149 STATUSCODE=$(
diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml
index 19d512585..ad2f14568 100644
--- a/embassy-embedded-hal/Cargo.toml
+++ b/embassy-embedded-hal/Cargo.toml
@@ -14,11 +14,14 @@ target = "x86_64-unknown-linux-gnu"
14[features] 14[features]
15std = [] 15std = []
16# Enable nightly-only features 16# Enable nightly-only features
17nightly = ["embedded-hal-async", "embedded-storage-async"] 17nightly = ["embassy-futures", "embedded-hal-async", "embedded-storage-async"]
18 18
19[dependencies] 19[dependencies]
20embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true }
20embassy-sync = { version = "0.2.0", path = "../embassy-sync" } 21embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
21embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 22embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [
23 "unproven",
24] }
22embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } 25embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" }
23embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true } 26embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true }
24embedded-storage = "0.3.0" 27embedded-storage = "0.3.0"
@@ -26,3 +29,6 @@ embedded-storage-async = { version = "0.4.0", optional = true }
26nb = "1.0.0" 29nb = "1.0.0"
27 30
28defmt = { version = "0.3", optional = true } 31defmt = { version = "0.3", optional = true }
32
33[dev-dependencies]
34futures-test = "0.3.17"
diff --git a/embassy-embedded-hal/src/adapter.rs b/embassy-embedded-hal/src/adapter/blocking_async.rs
index 171ff6c9f..b996d6a75 100644
--- a/embassy-embedded-hal/src/adapter.rs
+++ b/embassy-embedded-hal/src/adapter/blocking_async.rs
@@ -1,5 +1,3 @@
1//! Adapters between embedded-hal traits.
2
3use embedded_hal_02::{blocking, serial}; 1use embedded_hal_02::{blocking, serial};
4 2
5/// Wrapper that implements async traits using blocking implementations. 3/// Wrapper that implements async traits using blocking implementations.
diff --git a/embassy-embedded-hal/src/adapter/mod.rs b/embassy-embedded-hal/src/adapter/mod.rs
new file mode 100644
index 000000000..28da56137
--- /dev/null
+++ b/embassy-embedded-hal/src/adapter/mod.rs
@@ -0,0 +1,7 @@
1//! Adapters between embedded-hal traits.
2
3mod blocking_async;
4mod yielding_async;
5
6pub use blocking_async::BlockingAsync;
7pub use yielding_async::YieldingAsync;
diff --git a/embassy-embedded-hal/src/adapter/yielding_async.rs b/embassy-embedded-hal/src/adapter/yielding_async.rs
new file mode 100644
index 000000000..96d5cca8e
--- /dev/null
+++ b/embassy-embedded-hal/src/adapter/yielding_async.rs
@@ -0,0 +1,232 @@
1use embassy_futures::yield_now;
2
3/// Wrapper that yields for each operation to the wrapped instance
4///
5/// This can be used in combination with BlockingAsync<T> to enforce yields
6/// between long running blocking operations.
7pub struct YieldingAsync<T> {
8 wrapped: T,
9}
10
11impl<T> YieldingAsync<T> {
12 /// Create a new instance of a wrapper that yields after each operation.
13 pub fn new(wrapped: T) -> Self {
14 Self { wrapped }
15 }
16}
17
18//
19// I2C implementations
20//
21impl<T> embedded_hal_1::i2c::ErrorType for YieldingAsync<T>
22where
23 T: embedded_hal_1::i2c::ErrorType,
24{
25 type Error = T::Error;
26}
27
28impl<T> embedded_hal_async::i2c::I2c for YieldingAsync<T>
29where
30 T: embedded_hal_async::i2c::I2c,
31{
32 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
33 self.wrapped.read(address, read).await?;
34 yield_now().await;
35 Ok(())
36 }
37
38 async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
39 self.wrapped.write(address, write).await?;
40 yield_now().await;
41 Ok(())
42 }
43
44 async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
45 self.wrapped.write_read(address, write, read).await?;
46 yield_now().await;
47 Ok(())
48 }
49
50 async fn transaction(
51 &mut self,
52 address: u8,
53 operations: &mut [embedded_hal_1::i2c::Operation<'_>],
54 ) -> Result<(), Self::Error> {
55 self.wrapped.transaction(address, operations).await?;
56 yield_now().await;
57 Ok(())
58 }
59}
60
61//
62// SPI implementations
63//
64
65impl<T> embedded_hal_async::spi::ErrorType for YieldingAsync<T>
66where
67 T: embedded_hal_async::spi::ErrorType,
68{
69 type Error = T::Error;
70}
71
72impl<T> embedded_hal_async::spi::SpiBus<u8> for YieldingAsync<T>
73where
74 T: embedded_hal_async::spi::SpiBus,
75{
76 async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> {
77 self.wrapped.transfer(read, write).await?;
78 yield_now().await;
79 Ok(())
80 }
81
82 async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Result<(), Self::Error> {
83 self.wrapped.transfer_in_place(words).await?;
84 yield_now().await;
85 Ok(())
86 }
87}
88
89impl<T> embedded_hal_async::spi::SpiBusFlush for YieldingAsync<T>
90where
91 T: embedded_hal_async::spi::SpiBusFlush,
92{
93 async fn flush(&mut self) -> Result<(), Self::Error> {
94 self.wrapped.flush().await?;
95 yield_now().await;
96 Ok(())
97 }
98}
99
100impl<T> embedded_hal_async::spi::SpiBusWrite<u8> for YieldingAsync<T>
101where
102 T: embedded_hal_async::spi::SpiBusWrite<u8>,
103{
104 async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
105 self.wrapped.write(data).await?;
106 yield_now().await;
107 Ok(())
108 }
109}
110
111impl<T> embedded_hal_async::spi::SpiBusRead<u8> for YieldingAsync<T>
112where
113 T: embedded_hal_async::spi::SpiBusRead<u8>,
114{
115 async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
116 self.wrapped.read(data).await?;
117 yield_now().await;
118 Ok(())
119 }
120}
121
122///
123/// NOR flash implementations
124///
125impl<T: embedded_storage::nor_flash::ErrorType> embedded_storage::nor_flash::ErrorType for YieldingAsync<T> {
126 type Error = T::Error;
127}
128
129impl<T: embedded_storage_async::nor_flash::ReadNorFlash> embedded_storage_async::nor_flash::ReadNorFlash
130 for YieldingAsync<T>
131{
132 const READ_SIZE: usize = T::READ_SIZE;
133
134 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
135 self.wrapped.read(offset, bytes).await?;
136 Ok(())
137 }
138
139 fn capacity(&self) -> usize {
140 self.wrapped.capacity()
141 }
142}
143
144impl<T: embedded_storage_async::nor_flash::NorFlash> embedded_storage_async::nor_flash::NorFlash for YieldingAsync<T> {
145 const WRITE_SIZE: usize = T::WRITE_SIZE;
146 const ERASE_SIZE: usize = T::ERASE_SIZE;
147
148 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
149 self.wrapped.write(offset, bytes).await?;
150 yield_now().await;
151 Ok(())
152 }
153
154 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
155 // Yield between each actual erase
156 for from in (from..to).step_by(T::ERASE_SIZE) {
157 let to = core::cmp::min(from + T::ERASE_SIZE as u32, to);
158 self.wrapped.erase(from, to).await?;
159 yield_now().await;
160 }
161 Ok(())
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use embedded_storage_async::nor_flash::NorFlash;
168
169 use super::*;
170
171 extern crate std;
172
173 #[derive(Default)]
174 struct FakeFlash(Vec<(u32, u32)>);
175
176 impl embedded_storage::nor_flash::ErrorType for FakeFlash {
177 type Error = std::convert::Infallible;
178 }
179
180 impl embedded_storage_async::nor_flash::ReadNorFlash for FakeFlash {
181 const READ_SIZE: usize = 1;
182
183 async fn read(&mut self, _offset: u32, _bytes: &mut [u8]) -> Result<(), Self::Error> {
184 unimplemented!()
185 }
186
187 fn capacity(&self) -> usize {
188 unimplemented!()
189 }
190 }
191
192 impl embedded_storage_async::nor_flash::NorFlash for FakeFlash {
193 const WRITE_SIZE: usize = 4;
194 const ERASE_SIZE: usize = 128;
195
196 async fn write(&mut self, _offset: u32, _bytes: &[u8]) -> Result<(), Self::Error> {
197 unimplemented!()
198 }
199
200 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
201 self.0.push((from, to));
202 Ok(())
203 }
204 }
205
206 #[futures_test::test]
207 async fn can_erase() {
208 let fake = FakeFlash::default();
209 let mut yielding = YieldingAsync::new(fake);
210
211 yielding.erase(0, 256).await.unwrap();
212
213 let fake = yielding.wrapped;
214 assert_eq!(2, fake.0.len());
215 assert_eq!((0, 128), fake.0[0]);
216 assert_eq!((128, 256), fake.0[1]);
217 }
218
219 #[futures_test::test]
220 async fn can_erase_wrong_erase_size() {
221 let fake = FakeFlash::default();
222 let mut yielding = YieldingAsync::new(fake);
223
224 yielding.erase(0, 257).await.unwrap();
225
226 let fake = yielding.wrapped;
227 assert_eq!(3, fake.0.len());
228 assert_eq!((0, 128), fake.0[0]);
229 assert_eq!((128, 256), fake.0[1]);
230 assert_eq!((256, 257), fake.0[2]);
231 }
232}
diff --git a/embassy-embedded-hal/src/flash.rs b/embassy-embedded-hal/src/flash.rs
new file mode 100644
index 000000000..9a6e4bd92
--- /dev/null
+++ b/embassy-embedded-hal/src/flash.rs
@@ -0,0 +1,286 @@
1//! Utilities related to flash.
2
3use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, ReadNorFlash};
4#[cfg(feature = "nightly")]
5use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
6
7/// Convenience helper for concatenating two consecutive flashes into one.
8/// This is especially useful if used with "flash regions", where one may
9/// want to concatenate multiple regions into one larger region.
10pub struct ConcatFlash<First, Second>(First, Second);
11
12impl<First, Second> ConcatFlash<First, Second> {
13 /// Create a new flash that concatenates two consecutive flashes.
14 pub fn new(first: First, second: Second) -> Self {
15 Self(first, second)
16 }
17}
18
19const fn get_read_size(first_read_size: usize, second_read_size: usize) -> usize {
20 if first_read_size != second_read_size {
21 panic!("The read size for the concatenated flashes must be the same");
22 }
23 first_read_size
24}
25
26const fn get_write_size(first_write_size: usize, second_write_size: usize) -> usize {
27 if first_write_size != second_write_size {
28 panic!("The write size for the concatenated flashes must be the same");
29 }
30 first_write_size
31}
32
33const fn get_max_erase_size(first_erase_size: usize, second_erase_size: usize) -> usize {
34 let max_erase_size = if first_erase_size > second_erase_size {
35 first_erase_size
36 } else {
37 second_erase_size
38 };
39 if max_erase_size % first_erase_size != 0 || max_erase_size % second_erase_size != 0 {
40 panic!("The erase sizes for the concatenated flashes must have have a gcd equal to the max erase size");
41 }
42 max_erase_size
43}
44
45impl<First, Second, E> ErrorType for ConcatFlash<First, Second>
46where
47 First: ErrorType<Error = E>,
48 Second: ErrorType<Error = E>,
49 E: NorFlashError,
50{
51 type Error = E;
52}
53
54impl<First, Second, E> ReadNorFlash for ConcatFlash<First, Second>
55where
56 First: ReadNorFlash<Error = E>,
57 Second: ReadNorFlash<Error = E>,
58 E: NorFlashError,
59{
60 const READ_SIZE: usize = get_read_size(First::READ_SIZE, Second::READ_SIZE);
61
62 fn read(&mut self, mut offset: u32, mut bytes: &mut [u8]) -> Result<(), E> {
63 if offset < self.0.capacity() as u32 {
64 let len = core::cmp::min(self.0.capacity() - offset as usize, bytes.len());
65 self.0.read(offset, &mut bytes[..len])?;
66 offset += len as u32;
67 bytes = &mut bytes[len..];
68 }
69
70 if !bytes.is_empty() {
71 self.1.read(offset - self.0.capacity() as u32, bytes)?;
72 }
73
74 Ok(())
75 }
76
77 fn capacity(&self) -> usize {
78 self.0.capacity() + self.1.capacity()
79 }
80}
81
82impl<First, Second, E> NorFlash for ConcatFlash<First, Second>
83where
84 First: NorFlash<Error = E>,
85 Second: NorFlash<Error = E>,
86 E: NorFlashError,
87{
88 const WRITE_SIZE: usize = get_write_size(First::WRITE_SIZE, Second::WRITE_SIZE);
89 const ERASE_SIZE: usize = get_max_erase_size(First::ERASE_SIZE, Second::ERASE_SIZE);
90
91 fn write(&mut self, mut offset: u32, mut bytes: &[u8]) -> Result<(), E> {
92 if offset < self.0.capacity() as u32 {
93 let len = core::cmp::min(self.0.capacity() - offset as usize, bytes.len());
94 self.0.write(offset, &bytes[..len])?;
95 offset += len as u32;
96 bytes = &bytes[len..];
97 }
98
99 if !bytes.is_empty() {
100 self.1.write(offset - self.0.capacity() as u32, bytes)?;
101 }
102
103 Ok(())
104 }
105
106 fn erase(&mut self, mut from: u32, to: u32) -> Result<(), E> {
107 if from < self.0.capacity() as u32 {
108 let to = core::cmp::min(self.0.capacity() as u32, to);
109 self.0.erase(from, to)?;
110 from = self.0.capacity() as u32;
111 }
112
113 if from < to {
114 self.1
115 .erase(from - self.0.capacity() as u32, to - self.0.capacity() as u32)?;
116 }
117
118 Ok(())
119 }
120}
121
122#[cfg(feature = "nightly")]
123impl<First, Second, E> AsyncReadNorFlash for ConcatFlash<First, Second>
124where
125 First: AsyncReadNorFlash<Error = E>,
126 Second: AsyncReadNorFlash<Error = E>,
127 E: NorFlashError,
128{
129 const READ_SIZE: usize = get_read_size(First::READ_SIZE, Second::READ_SIZE);
130
131 async fn read(&mut self, mut offset: u32, mut bytes: &mut [u8]) -> Result<(), E> {
132 if offset < self.0.capacity() as u32 {
133 let len = core::cmp::min(self.0.capacity() - offset as usize, bytes.len());
134 self.0.read(offset, &mut bytes[..len]).await?;
135 offset += len as u32;
136 bytes = &mut bytes[len..];
137 }
138
139 if !bytes.is_empty() {
140 self.1.read(offset - self.0.capacity() as u32, bytes).await?;
141 }
142
143 Ok(())
144 }
145
146 fn capacity(&self) -> usize {
147 self.0.capacity() + self.1.capacity()
148 }
149}
150
151#[cfg(feature = "nightly")]
152impl<First, Second, E> AsyncNorFlash for ConcatFlash<First, Second>
153where
154 First: AsyncNorFlash<Error = E>,
155 Second: AsyncNorFlash<Error = E>,
156 E: NorFlashError,
157{
158 const WRITE_SIZE: usize = get_write_size(First::WRITE_SIZE, Second::WRITE_SIZE);
159 const ERASE_SIZE: usize = get_max_erase_size(First::ERASE_SIZE, Second::ERASE_SIZE);
160
161 async fn write(&mut self, mut offset: u32, mut bytes: &[u8]) -> Result<(), E> {
162 if offset < self.0.capacity() as u32 {
163 let len = core::cmp::min(self.0.capacity() - offset as usize, bytes.len());
164 self.0.write(offset, &bytes[..len]).await?;
165 offset += len as u32;
166 bytes = &bytes[len..];
167 }
168
169 if !bytes.is_empty() {
170 self.1.write(offset - self.0.capacity() as u32, bytes).await?;
171 }
172
173 Ok(())
174 }
175
176 async fn erase(&mut self, mut from: u32, to: u32) -> Result<(), E> {
177 if from < self.0.capacity() as u32 {
178 let to = core::cmp::min(self.0.capacity() as u32, to);
179 self.0.erase(from, to).await?;
180 from = self.0.capacity() as u32;
181 }
182
183 if from < to {
184 self.1
185 .erase(from - self.0.capacity() as u32, to - self.0.capacity() as u32)
186 .await?;
187 }
188
189 Ok(())
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn can_write_and_read_across_flashes() {
199 let first = MemFlash::<64, 16, 4>::new();
200 let second = MemFlash::<64, 64, 4>::new();
201 let mut f = ConcatFlash::new(first, second);
202
203 f.write(60, &[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]).unwrap();
204
205 assert_eq!(&[0x11, 0x22, 0x33, 0x44], &f.0 .0[60..]);
206 assert_eq!(&[0x55, 0x66, 0x77, 0x88], &f.1 .0[0..4]);
207
208 let mut read_buf = [0; 8];
209 f.read(60, &mut read_buf).unwrap();
210
211 assert_eq!(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], &read_buf);
212 }
213
214 #[test]
215 fn can_erase_across_flashes() {
216 let mut first = MemFlash::<128, 16, 4>::new();
217 let mut second = MemFlash::<128, 64, 4>::new();
218 first.0.fill(0x00);
219 second.0.fill(0x00);
220
221 let mut f = ConcatFlash::new(first, second);
222
223 f.erase(64, 192).unwrap();
224
225 assert_eq!(&[0x00; 64], &f.0 .0[0..64]);
226 assert_eq!(&[0xff; 64], &f.0 .0[64..128]);
227 assert_eq!(&[0xff; 64], &f.1 .0[0..64]);
228 assert_eq!(&[0x00; 64], &f.1 .0[64..128]);
229 }
230
231 pub struct MemFlash<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize>([u8; SIZE]);
232
233 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE> {
234 pub const fn new() -> Self {
235 Self([0xff; SIZE])
236 }
237 }
238
239 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> ErrorType
240 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
241 {
242 type Error = core::convert::Infallible;
243 }
244
245 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> ReadNorFlash
246 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
247 {
248 const READ_SIZE: usize = 1;
249
250 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
251 let len = bytes.len();
252 bytes.copy_from_slice(&self.0[offset as usize..offset as usize + len]);
253 Ok(())
254 }
255
256 fn capacity(&self) -> usize {
257 SIZE
258 }
259 }
260
261 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> NorFlash
262 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
263 {
264 const WRITE_SIZE: usize = WRITE_SIZE;
265 const ERASE_SIZE: usize = ERASE_SIZE;
266
267 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
268 let from = from as usize;
269 let to = to as usize;
270 assert_eq!(0, from % ERASE_SIZE);
271 assert_eq!(0, to % ERASE_SIZE);
272 self.0[from..to].fill(0xff);
273 Ok(())
274 }
275
276 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
277 let offset = offset as usize;
278 assert_eq!(0, bytes.len() % WRITE_SIZE);
279 assert_eq!(0, offset % WRITE_SIZE);
280 assert!(offset + bytes.len() <= SIZE);
281
282 self.0[offset..offset + bytes.len()].copy_from_slice(bytes);
283 Ok(())
284 }
285 }
286}
diff --git a/embassy-embedded-hal/src/lib.rs b/embassy-embedded-hal/src/lib.rs
index 73c81b465..3aad838bd 100644
--- a/embassy-embedded-hal/src/lib.rs
+++ b/embassy-embedded-hal/src/lib.rs
@@ -7,6 +7,8 @@
7#[cfg(feature = "nightly")] 7#[cfg(feature = "nightly")]
8pub mod adapter; 8pub mod adapter;
9 9
10pub mod flash;
11
10pub mod shared_bus; 12pub mod shared_bus;
11 13
12/// Set the configuration of a peripheral driver. 14/// Set the configuration of a peripheral driver.
diff --git a/embassy-lora/src/iv.rs b/embassy-lora/src/iv.rs
index f81134405..d515bc365 100644
--- a/embassy-lora/src/iv.rs
+++ b/embassy-lora/src/iv.rs
@@ -1,7 +1,9 @@
1#[cfg(feature = "stm32wl")] 1#[cfg(feature = "stm32wl")]
2use embassy_stm32::interrupt;
3#[cfg(feature = "stm32wl")]
2use embassy_stm32::interrupt::*; 4use embassy_stm32::interrupt::*;
3#[cfg(feature = "stm32wl")] 5#[cfg(feature = "stm32wl")]
4use embassy_stm32::{pac, PeripheralRef}; 6use embassy_stm32::pac;
5#[cfg(feature = "stm32wl")] 7#[cfg(feature = "stm32wl")]
6use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
7#[cfg(feature = "stm32wl")] 9#[cfg(feature = "stm32wl")]
@@ -13,47 +15,51 @@ use lora_phy::mod_params::RadioError::*;
13use lora_phy::mod_params::{BoardType, RadioError}; 15use lora_phy::mod_params::{BoardType, RadioError};
14use lora_phy::mod_traits::InterfaceVariant; 16use lora_phy::mod_traits::InterfaceVariant;
15 17
18/// Interrupt handler.
19#[cfg(feature = "stm32wl")]
20pub struct InterruptHandler {}
21
22#[cfg(feature = "stm32wl")]
23impl interrupt::Handler<interrupt::SUBGHZ_RADIO> for InterruptHandler {
24 unsafe fn on_interrupt() {
25 unsafe { SUBGHZ_RADIO::steal() }.disable();
26 IRQ_SIGNAL.signal(());
27 }
28}
29
16#[cfg(feature = "stm32wl")] 30#[cfg(feature = "stm32wl")]
17static IRQ_SIGNAL: Signal<CriticalSectionRawMutex, ()> = Signal::new(); 31static IRQ_SIGNAL: Signal<CriticalSectionRawMutex, ()> = Signal::new();
18 32
19#[cfg(feature = "stm32wl")] 33#[cfg(feature = "stm32wl")]
20/// Base for the InterfaceVariant implementation for an stm32wl/sx1262 combination 34/// Base for the InterfaceVariant implementation for an stm32wl/sx1262 combination
21pub struct Stm32wlInterfaceVariant<'a, CTRL> { 35pub struct Stm32wlInterfaceVariant<CTRL> {
22 board_type: BoardType, 36 board_type: BoardType,
23 irq: PeripheralRef<'a, SUBGHZ_RADIO>,
24 rf_switch_rx: Option<CTRL>, 37 rf_switch_rx: Option<CTRL>,
25 rf_switch_tx: Option<CTRL>, 38 rf_switch_tx: Option<CTRL>,
26} 39}
27 40
28#[cfg(feature = "stm32wl")] 41#[cfg(feature = "stm32wl")]
29impl<'a, CTRL> Stm32wlInterfaceVariant<'a, CTRL> 42impl<'a, CTRL> Stm32wlInterfaceVariant<CTRL>
30where 43where
31 CTRL: OutputPin, 44 CTRL: OutputPin,
32{ 45{
33 /// Create an InterfaceVariant instance for an stm32wl/sx1262 combination 46 /// Create an InterfaceVariant instance for an stm32wl/sx1262 combination
34 pub fn new( 47 pub fn new(
35 irq: PeripheralRef<'a, SUBGHZ_RADIO>, 48 _irq: impl interrupt::Binding<interrupt::SUBGHZ_RADIO, InterruptHandler>,
36 rf_switch_rx: Option<CTRL>, 49 rf_switch_rx: Option<CTRL>,
37 rf_switch_tx: Option<CTRL>, 50 rf_switch_tx: Option<CTRL>,
38 ) -> Result<Self, RadioError> { 51 ) -> Result<Self, RadioError> {
39 irq.disable(); 52 unsafe { interrupt::SUBGHZ_RADIO::steal() }.disable();
40 irq.set_handler(Self::on_interrupt);
41 Ok(Self { 53 Ok(Self {
42 board_type: BoardType::Stm32wlSx1262, // updated when associated with a specific LoRa board 54 board_type: BoardType::Stm32wlSx1262, // updated when associated with a specific LoRa board
43 irq,
44 rf_switch_rx, 55 rf_switch_rx,
45 rf_switch_tx, 56 rf_switch_tx,
46 }) 57 })
47 } 58 }
48
49 fn on_interrupt(_: *mut ()) {
50 unsafe { SUBGHZ_RADIO::steal() }.disable();
51 IRQ_SIGNAL.signal(());
52 }
53} 59}
54 60
55#[cfg(feature = "stm32wl")] 61#[cfg(feature = "stm32wl")]
56impl<CTRL> InterfaceVariant for Stm32wlInterfaceVariant<'_, CTRL> 62impl<CTRL> InterfaceVariant for Stm32wlInterfaceVariant<CTRL>
57where 63where
58 CTRL: OutputPin, 64 CTRL: OutputPin,
59{ 65{
@@ -89,7 +95,7 @@ where
89 } 95 }
90 96
91 async fn await_irq(&mut self) -> Result<(), RadioError> { 97 async fn await_irq(&mut self) -> Result<(), RadioError> {
92 self.irq.enable(); 98 unsafe { interrupt::SUBGHZ_RADIO::steal() }.enable();
93 IRQ_SIGNAL.wait().await; 99 IRQ_SIGNAL.wait().await;
94 Ok(()) 100 Ok(())
95 } 101 }
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index ca0c36c26..540981727 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -421,6 +421,10 @@ fn main() {
421 (("spi", "SCK"), quote!(crate::spi::SckPin)), 421 (("spi", "SCK"), quote!(crate::spi::SckPin)),
422 (("spi", "MOSI"), quote!(crate::spi::MosiPin)), 422 (("spi", "MOSI"), quote!(crate::spi::MosiPin)),
423 (("spi", "MISO"), quote!(crate::spi::MisoPin)), 423 (("spi", "MISO"), quote!(crate::spi::MisoPin)),
424 (("spi", "NSS"), quote!(crate::spi::CsPin)),
425 (("spi", "I2S_MCK"), quote!(crate::spi::MckPin)),
426 (("spi", "I2S_CK"), quote!(crate::spi::CkPin)),
427 (("spi", "I2S_WS"), quote!(crate::spi::WsPin)),
424 (("i2c", "SDA"), quote!(crate::i2c::SdaPin)), 428 (("i2c", "SDA"), quote!(crate::i2c::SdaPin)),
425 (("i2c", "SCL"), quote!(crate::i2c::SclPin)), 429 (("i2c", "SCL"), quote!(crate::i2c::SclPin)),
426 (("rcc", "MCO_1"), quote!(crate::rcc::McoPin)), 430 (("rcc", "MCO_1"), quote!(crate::rcc::McoPin)),
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index c19be86c6..5f3fc6a93 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -1,4 +1,5 @@
1use core::future::poll_fn; 1use core::future::poll_fn;
2use core::marker::PhantomData;
2use core::task::Poll; 3use core::task::Poll;
3 4
4use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_common::{into_ref, PeripheralRef};
@@ -8,7 +9,31 @@ use crate::dma::Transfer;
8use crate::gpio::sealed::AFType; 9use crate::gpio::sealed::AFType;
9use crate::gpio::Speed; 10use crate::gpio::Speed;
10use crate::interrupt::{Interrupt, InterruptExt}; 11use crate::interrupt::{Interrupt, InterruptExt};
11use crate::Peripheral; 12use crate::{interrupt, Peripheral};
13
14/// Interrupt handler.
15pub struct InterruptHandler<T: Instance> {
16 _phantom: PhantomData<T>,
17}
18
19impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
20 unsafe fn on_interrupt() {
21 let ris = crate::pac::DCMI.ris().read();
22 if ris.err_ris() {
23 trace!("DCMI IRQ: Error.");
24 crate::pac::DCMI.ier().modify(|ier| ier.set_err_ie(false));
25 }
26 if ris.ovr_ris() {
27 trace!("DCMI IRQ: Overrun.");
28 crate::pac::DCMI.ier().modify(|ier| ier.set_ovr_ie(false));
29 }
30 if ris.frame_ris() {
31 trace!("DCMI IRQ: Frame captured.");
32 crate::pac::DCMI.ier().modify(|ier| ier.set_frame_ie(false));
33 }
34 STATE.waker.wake();
35 }
36}
12 37
13/// The level on the VSync pin when the data is not valid on the parallel interface. 38/// The level on the VSync pin when the data is not valid on the parallel interface.
14#[derive(Clone, Copy, PartialEq)] 39#[derive(Clone, Copy, PartialEq)]
@@ -94,7 +119,7 @@ where
94 pub fn new_8bit( 119 pub fn new_8bit(
95 peri: impl Peripheral<P = T> + 'd, 120 peri: impl Peripheral<P = T> + 'd,
96 dma: impl Peripheral<P = Dma> + 'd, 121 dma: impl Peripheral<P = Dma> + 'd,
97 irq: impl Peripheral<P = T::Interrupt> + 'd, 122 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
98 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 123 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
99 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 124 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
100 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 125 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
@@ -108,17 +133,17 @@ where
108 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd, 133 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
109 config: Config, 134 config: Config,
110 ) -> Self { 135 ) -> Self {
111 into_ref!(peri, dma, irq); 136 into_ref!(peri, dma);
112 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7); 137 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7);
113 config_pins!(v_sync, h_sync, pixclk); 138 config_pins!(v_sync, h_sync, pixclk);
114 139
115 Self::new_inner(peri, dma, irq, config, false, 0b00) 140 Self::new_inner(peri, dma, config, false, 0b00)
116 } 141 }
117 142
118 pub fn new_10bit( 143 pub fn new_10bit(
119 peri: impl Peripheral<P = T> + 'd, 144 peri: impl Peripheral<P = T> + 'd,
120 dma: impl Peripheral<P = Dma> + 'd, 145 dma: impl Peripheral<P = Dma> + 'd,
121 irq: impl Peripheral<P = T::Interrupt> + 'd, 146 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
122 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 147 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
123 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 148 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
124 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 149 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
@@ -134,17 +159,17 @@ where
134 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd, 159 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
135 config: Config, 160 config: Config,
136 ) -> Self { 161 ) -> Self {
137 into_ref!(peri, dma, irq); 162 into_ref!(peri, dma);
138 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9); 163 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
139 config_pins!(v_sync, h_sync, pixclk); 164 config_pins!(v_sync, h_sync, pixclk);
140 165
141 Self::new_inner(peri, dma, irq, config, false, 0b01) 166 Self::new_inner(peri, dma, config, false, 0b01)
142 } 167 }
143 168
144 pub fn new_12bit( 169 pub fn new_12bit(
145 peri: impl Peripheral<P = T> + 'd, 170 peri: impl Peripheral<P = T> + 'd,
146 dma: impl Peripheral<P = Dma> + 'd, 171 dma: impl Peripheral<P = Dma> + 'd,
147 irq: impl Peripheral<P = T::Interrupt> + 'd, 172 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
148 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 173 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
149 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 174 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
150 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 175 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
@@ -162,17 +187,17 @@ where
162 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd, 187 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
163 config: Config, 188 config: Config,
164 ) -> Self { 189 ) -> Self {
165 into_ref!(peri, dma, irq); 190 into_ref!(peri, dma);
166 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11); 191 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
167 config_pins!(v_sync, h_sync, pixclk); 192 config_pins!(v_sync, h_sync, pixclk);
168 193
169 Self::new_inner(peri, dma, irq, config, false, 0b10) 194 Self::new_inner(peri, dma, config, false, 0b10)
170 } 195 }
171 196
172 pub fn new_14bit( 197 pub fn new_14bit(
173 peri: impl Peripheral<P = T> + 'd, 198 peri: impl Peripheral<P = T> + 'd,
174 dma: impl Peripheral<P = Dma> + 'd, 199 dma: impl Peripheral<P = Dma> + 'd,
175 irq: impl Peripheral<P = T::Interrupt> + 'd, 200 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
176 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 201 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
177 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 202 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
178 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 203 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
@@ -192,17 +217,17 @@ where
192 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd, 217 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
193 config: Config, 218 config: Config,
194 ) -> Self { 219 ) -> Self {
195 into_ref!(peri, dma, irq); 220 into_ref!(peri, dma);
196 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13); 221 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
197 config_pins!(v_sync, h_sync, pixclk); 222 config_pins!(v_sync, h_sync, pixclk);
198 223
199 Self::new_inner(peri, dma, irq, config, false, 0b11) 224 Self::new_inner(peri, dma, config, false, 0b11)
200 } 225 }
201 226
202 pub fn new_es_8bit( 227 pub fn new_es_8bit(
203 peri: impl Peripheral<P = T> + 'd, 228 peri: impl Peripheral<P = T> + 'd,
204 dma: impl Peripheral<P = Dma> + 'd, 229 dma: impl Peripheral<P = Dma> + 'd,
205 irq: impl Peripheral<P = T::Interrupt> + 'd, 230 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
206 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 231 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
207 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 232 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
208 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 233 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
@@ -214,17 +239,17 @@ where
214 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd, 239 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
215 config: Config, 240 config: Config,
216 ) -> Self { 241 ) -> Self {
217 into_ref!(peri, dma, irq); 242 into_ref!(peri, dma);
218 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7); 243 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7);
219 config_pins!(pixclk); 244 config_pins!(pixclk);
220 245
221 Self::new_inner(peri, dma, irq, config, true, 0b00) 246 Self::new_inner(peri, dma, config, true, 0b00)
222 } 247 }
223 248
224 pub fn new_es_10bit( 249 pub fn new_es_10bit(
225 peri: impl Peripheral<P = T> + 'd, 250 peri: impl Peripheral<P = T> + 'd,
226 dma: impl Peripheral<P = Dma> + 'd, 251 dma: impl Peripheral<P = Dma> + 'd,
227 irq: impl Peripheral<P = T::Interrupt> + 'd, 252 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
228 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 253 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
229 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 254 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
230 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 255 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
@@ -238,17 +263,17 @@ where
238 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd, 263 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
239 config: Config, 264 config: Config,
240 ) -> Self { 265 ) -> Self {
241 into_ref!(peri, dma, irq); 266 into_ref!(peri, dma);
242 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9); 267 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
243 config_pins!(pixclk); 268 config_pins!(pixclk);
244 269
245 Self::new_inner(peri, dma, irq, config, true, 0b01) 270 Self::new_inner(peri, dma, config, true, 0b01)
246 } 271 }
247 272
248 pub fn new_es_12bit( 273 pub fn new_es_12bit(
249 peri: impl Peripheral<P = T> + 'd, 274 peri: impl Peripheral<P = T> + 'd,
250 dma: impl Peripheral<P = Dma> + 'd, 275 dma: impl Peripheral<P = Dma> + 'd,
251 irq: impl Peripheral<P = T::Interrupt> + 'd, 276 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
252 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 277 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
253 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 278 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
254 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 279 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
@@ -264,17 +289,17 @@ where
264 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd, 289 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
265 config: Config, 290 config: Config,
266 ) -> Self { 291 ) -> Self {
267 into_ref!(peri, dma, irq); 292 into_ref!(peri, dma);
268 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11); 293 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
269 config_pins!(pixclk); 294 config_pins!(pixclk);
270 295
271 Self::new_inner(peri, dma, irq, config, true, 0b10) 296 Self::new_inner(peri, dma, config, true, 0b10)
272 } 297 }
273 298
274 pub fn new_es_14bit( 299 pub fn new_es_14bit(
275 peri: impl Peripheral<P = T> + 'd, 300 peri: impl Peripheral<P = T> + 'd,
276 dma: impl Peripheral<P = Dma> + 'd, 301 dma: impl Peripheral<P = Dma> + 'd,
277 irq: impl Peripheral<P = T::Interrupt> + 'd, 302 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
278 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 303 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
279 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 304 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
280 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 305 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
@@ -292,17 +317,16 @@ where
292 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd, 317 pixclk: impl Peripheral<P = impl PixClkPin<T>> + 'd,
293 config: Config, 318 config: Config,
294 ) -> Self { 319 ) -> Self {
295 into_ref!(peri, dma, irq); 320 into_ref!(peri, dma);
296 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13); 321 config_pins!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
297 config_pins!(pixclk); 322 config_pins!(pixclk);
298 323
299 Self::new_inner(peri, dma, irq, config, true, 0b11) 324 Self::new_inner(peri, dma, config, true, 0b11)
300 } 325 }
301 326
302 fn new_inner( 327 fn new_inner(
303 peri: PeripheralRef<'d, T>, 328 peri: PeripheralRef<'d, T>,
304 dma: PeripheralRef<'d, Dma>, 329 dma: PeripheralRef<'d, Dma>,
305 irq: PeripheralRef<'d, T::Interrupt>,
306 config: Config, 330 config: Config,
307 use_embedded_synchronization: bool, 331 use_embedded_synchronization: bool,
308 edm: u8, 332 edm: u8,
@@ -322,30 +346,12 @@ where
322 }); 346 });
323 } 347 }
324 348
325 irq.set_handler(Self::on_interrupt); 349 unsafe { T::Interrupt::steal() }.unpend();
326 irq.unpend(); 350 unsafe { T::Interrupt::steal() }.enable();
327 irq.enable();
328 351
329 Self { inner: peri, dma } 352 Self { inner: peri, dma }
330 } 353 }
331 354
332 unsafe fn on_interrupt(_: *mut ()) {
333 let ris = crate::pac::DCMI.ris().read();
334 if ris.err_ris() {
335 trace!("DCMI IRQ: Error.");
336 crate::pac::DCMI.ier().modify(|ier| ier.set_err_ie(false));
337 }
338 if ris.ovr_ris() {
339 trace!("DCMI IRQ: Overrun.");
340 crate::pac::DCMI.ier().modify(|ier| ier.set_ovr_ie(false));
341 }
342 if ris.frame_ris() {
343 trace!("DCMI IRQ: Frame captured.");
344 crate::pac::DCMI.ier().modify(|ier| ier.set_frame_ie(false));
345 }
346 STATE.waker.wake();
347 }
348
349 unsafe fn toggle(enable: bool) { 355 unsafe fn toggle(enable: bool) {
350 crate::pac::DCMI.cr().modify(|r| { 356 crate::pac::DCMI.cr().modify(|r| {
351 r.set_enable(enable); 357 r.set_enable(enable);
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index e1d7a09b4..4989e17c7 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -11,7 +11,7 @@ use core::task::Context;
11use embassy_net_driver::{Capabilities, LinkState}; 11use embassy_net_driver::{Capabilities, LinkState};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13 13
14pub use self::_version::*; 14pub use self::_version::{InterruptHandler, *};
15 15
16#[allow(unused)] 16#[allow(unused)]
17const MTU: usize = 1514; 17const MTU: usize = 1514;
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 9c0f4d66d..8ef2c3584 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -5,7 +5,7 @@ mod tx_desc;
5 5
6use core::sync::atomic::{fence, Ordering}; 6use core::sync::atomic::{fence, Ordering};
7 7
8use embassy_cortex_m::interrupt::InterruptExt; 8use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
9use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
10use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf}; 10use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf};
11 11
@@ -19,7 +19,30 @@ use crate::pac::AFIO;
19#[cfg(any(eth_v1b, eth_v1c))] 19#[cfg(any(eth_v1b, eth_v1c))]
20use crate::pac::SYSCFG; 20use crate::pac::SYSCFG;
21use crate::pac::{ETH, RCC}; 21use crate::pac::{ETH, RCC};
22use crate::Peripheral; 22use crate::{interrupt, Peripheral};
23
24/// Interrupt handler.
25pub struct InterruptHandler {}
26
27impl interrupt::Handler<interrupt::ETH> for InterruptHandler {
28 unsafe fn on_interrupt() {
29 WAKER.wake();
30
31 // TODO: Check and clear more flags
32 unsafe {
33 let dma = ETH.ethernet_dma();
34
35 dma.dmasr().modify(|w| {
36 w.set_ts(true);
37 w.set_rs(true);
38 w.set_nis(true);
39 });
40 // Delay two peripheral's clock
41 dma.dmasr().read();
42 dma.dmasr().read();
43 }
44 }
45}
23 46
24pub struct Ethernet<'d, T: Instance, P: PHY> { 47pub struct Ethernet<'d, T: Instance, P: PHY> {
25 _peri: PeripheralRef<'d, T>, 48 _peri: PeripheralRef<'d, T>,
@@ -77,7 +100,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
77 pub fn new<const TX: usize, const RX: usize>( 100 pub fn new<const TX: usize, const RX: usize>(
78 queue: &'d mut PacketQueue<TX, RX>, 101 queue: &'d mut PacketQueue<TX, RX>,
79 peri: impl Peripheral<P = T> + 'd, 102 peri: impl Peripheral<P = T> + 'd,
80 interrupt: impl Peripheral<P = crate::interrupt::ETH> + 'd, 103 _irq: impl interrupt::Binding<interrupt::ETH, InterruptHandler> + 'd,
81 ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd, 104 ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd,
82 mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd, 105 mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd,
83 mdc: impl Peripheral<P = impl MDCPin<T>> + 'd, 106 mdc: impl Peripheral<P = impl MDCPin<T>> + 'd,
@@ -91,7 +114,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
91 mac_addr: [u8; 6], 114 mac_addr: [u8; 6],
92 phy_addr: u8, 115 phy_addr: u8,
93 ) -> Self { 116 ) -> Self {
94 into_ref!(peri, interrupt, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 117 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
95 118
96 unsafe { 119 unsafe {
97 // Enable the necessary Clocks 120 // Enable the necessary Clocks
@@ -244,30 +267,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
244 P::phy_reset(&mut this); 267 P::phy_reset(&mut this);
245 P::phy_init(&mut this); 268 P::phy_init(&mut this);
246 269
247 interrupt.set_handler(Self::on_interrupt); 270 interrupt::ETH::steal().unpend();
248 interrupt.enable(); 271 interrupt::ETH::steal().enable();
249 272
250 this 273 this
251 } 274 }
252 } 275 }
253
254 fn on_interrupt(_cx: *mut ()) {
255 WAKER.wake();
256
257 // TODO: Check and clear more flags
258 unsafe {
259 let dma = ETH.ethernet_dma();
260
261 dma.dmasr().modify(|w| {
262 w.set_ts(true);
263 w.set_rs(true);
264 w.set_nis(true);
265 });
266 // Delay two peripheral's clock
267 dma.dmasr().read();
268 dma.dmasr().read();
269 }
270 }
271} 276}
272 277
273unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { 278unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> {
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index d49b1f767..b56c3e8ab 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -2,7 +2,7 @@ mod descriptors;
2 2
3use core::sync::atomic::{fence, Ordering}; 3use core::sync::atomic::{fence, Ordering};
4 4
5use embassy_cortex_m::interrupt::InterruptExt; 5use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use embassy_hal_common::{into_ref, PeripheralRef};
7 7
8pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; 8pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing};
@@ -10,7 +10,30 @@ use super::*;
10use crate::gpio::sealed::{AFType, Pin as _}; 10use crate::gpio::sealed::{AFType, Pin as _};
11use crate::gpio::{AnyPin, Speed}; 11use crate::gpio::{AnyPin, Speed};
12use crate::pac::ETH; 12use crate::pac::ETH;
13use crate::Peripheral; 13use crate::{interrupt, Peripheral};
14
15/// Interrupt handler.
16pub struct InterruptHandler {}
17
18impl interrupt::Handler<interrupt::ETH> for InterruptHandler {
19 unsafe fn on_interrupt() {
20 WAKER.wake();
21
22 // TODO: Check and clear more flags
23 unsafe {
24 let dma = ETH.ethernet_dma();
25
26 dma.dmacsr().modify(|w| {
27 w.set_ti(true);
28 w.set_ri(true);
29 w.set_nis(true);
30 });
31 // Delay two peripheral's clock
32 dma.dmacsr().read();
33 dma.dmacsr().read();
34 }
35 }
36}
14 37
15const MTU: usize = 1514; // 14 Ethernet header + 1500 IP packet 38const MTU: usize = 1514; // 14 Ethernet header + 1500 IP packet
16 39
@@ -41,7 +64,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
41 pub fn new<const TX: usize, const RX: usize>( 64 pub fn new<const TX: usize, const RX: usize>(
42 queue: &'d mut PacketQueue<TX, RX>, 65 queue: &'d mut PacketQueue<TX, RX>,
43 peri: impl Peripheral<P = T> + 'd, 66 peri: impl Peripheral<P = T> + 'd,
44 interrupt: impl Peripheral<P = crate::interrupt::ETH> + 'd, 67 _irq: impl interrupt::Binding<interrupt::ETH, InterruptHandler> + 'd,
45 ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd, 68 ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd,
46 mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd, 69 mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd,
47 mdc: impl Peripheral<P = impl MDCPin<T>> + 'd, 70 mdc: impl Peripheral<P = impl MDCPin<T>> + 'd,
@@ -55,7 +78,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
55 mac_addr: [u8; 6], 78 mac_addr: [u8; 6],
56 phy_addr: u8, 79 phy_addr: u8,
57 ) -> Self { 80 ) -> Self {
58 into_ref!(peri, interrupt, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 81 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
59 82
60 unsafe { 83 unsafe {
61 // Enable the necessary Clocks 84 // Enable the necessary Clocks
@@ -215,30 +238,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
215 P::phy_reset(&mut this); 238 P::phy_reset(&mut this);
216 P::phy_init(&mut this); 239 P::phy_init(&mut this);
217 240
218 interrupt.set_handler(Self::on_interrupt); 241 interrupt::ETH::steal().unpend();
219 interrupt.enable(); 242 interrupt::ETH::steal().enable();
220 243
221 this 244 this
222 } 245 }
223 } 246 }
224
225 fn on_interrupt(_cx: *mut ()) {
226 WAKER.wake();
227
228 // TODO: Check and clear more flags
229 unsafe {
230 let dma = ETH.ethernet_dma();
231
232 dma.dmacsr().modify(|w| {
233 w.set_ti(true);
234 w.set_ri(true);
235 w.set_nis(true);
236 });
237 // Delay two peripheral's clock
238 dma.dmacsr().read();
239 dma.dmacsr().read();
240 }
241 }
242} 247}
243 248
244unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { 249unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> {
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 4b47f0eb1..b9be2e587 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -9,7 +9,16 @@ use crate::gpio::Pull;
9use crate::i2c::{Error, Instance, SclPin, SdaPin}; 9use crate::i2c::{Error, Instance, SclPin, SdaPin};
10use crate::pac::i2c; 10use crate::pac::i2c;
11use crate::time::Hertz; 11use crate::time::Hertz;
12use crate::Peripheral; 12use crate::{interrupt, Peripheral};
13
14/// Interrupt handler.
15pub struct InterruptHandler<T: Instance> {
16 _phantom: PhantomData<T>,
17}
18
19impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
20 unsafe fn on_interrupt() {}
21}
13 22
14#[non_exhaustive] 23#[non_exhaustive]
15#[derive(Copy, Clone)] 24#[derive(Copy, Clone)]
@@ -48,7 +57,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
48 _peri: impl Peripheral<P = T> + 'd, 57 _peri: impl Peripheral<P = T> + 'd,
49 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 58 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
50 sda: impl Peripheral<P = impl SdaPin<T>> + 'd, 59 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
51 _irq: impl Peripheral<P = T::Interrupt> + 'd, 60 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
52 tx_dma: impl Peripheral<P = TXDMA> + 'd, 61 tx_dma: impl Peripheral<P = TXDMA> + 'd,
53 rx_dma: impl Peripheral<P = RXDMA> + 'd, 62 rx_dma: impl Peripheral<P = RXDMA> + 'd,
54 freq: Hertz, 63 freq: Hertz,
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 853bc128f..642ddc18c 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -1,7 +1,9 @@
1use core::cmp; 1use core::cmp;
2use core::future::poll_fn; 2use core::future::poll_fn;
3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
4 5
6use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
5use embassy_embedded_hal::SetConfig; 7use embassy_embedded_hal::SetConfig;
6use embassy_hal_common::drop::OnDrop; 8use embassy_hal_common::drop::OnDrop;
7use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
@@ -11,10 +13,30 @@ use crate::dma::{NoDma, Transfer};
11use crate::gpio::sealed::AFType; 13use crate::gpio::sealed::AFType;
12use crate::gpio::Pull; 14use crate::gpio::Pull;
13use crate::i2c::{Error, Instance, SclPin, SdaPin}; 15use crate::i2c::{Error, Instance, SclPin, SdaPin};
14use crate::interrupt::InterruptExt;
15use crate::pac::i2c; 16use crate::pac::i2c;
16use crate::time::Hertz; 17use crate::time::Hertz;
17use crate::Peripheral; 18use crate::{interrupt, Peripheral};
19
20/// Interrupt handler.
21pub struct InterruptHandler<T: Instance> {
22 _phantom: PhantomData<T>,
23}
24
25impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
26 unsafe fn on_interrupt() {
27 let regs = T::regs();
28 let isr = regs.isr().read();
29
30 if isr.tcr() || isr.tc() {
31 T::state().waker.wake();
32 }
33 // The flag can only be cleared by writting to nbytes, we won't do that here, so disable
34 // the interrupt
35 critical_section::with(|_| {
36 regs.cr1().modify(|w| w.set_tcie(false));
37 });
38 }
39}
18 40
19#[non_exhaustive] 41#[non_exhaustive]
20#[derive(Copy, Clone)] 42#[derive(Copy, Clone)]
@@ -56,13 +78,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
56 peri: impl Peripheral<P = T> + 'd, 78 peri: impl Peripheral<P = T> + 'd,
57 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 79 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
58 sda: impl Peripheral<P = impl SdaPin<T>> + 'd, 80 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
59 irq: impl Peripheral<P = T::Interrupt> + 'd, 81 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
60 tx_dma: impl Peripheral<P = TXDMA> + 'd, 82 tx_dma: impl Peripheral<P = TXDMA> + 'd,
61 rx_dma: impl Peripheral<P = RXDMA> + 'd, 83 rx_dma: impl Peripheral<P = RXDMA> + 'd,
62 freq: Hertz, 84 freq: Hertz,
63 config: Config, 85 config: Config,
64 ) -> Self { 86 ) -> Self {
65 into_ref!(peri, irq, scl, sda, tx_dma, rx_dma); 87 into_ref!(peri, scl, sda, tx_dma, rx_dma);
66 88
67 T::enable(); 89 T::enable();
68 T::reset(); 90 T::reset();
@@ -111,9 +133,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
111 }); 133 });
112 } 134 }
113 135
114 irq.set_handler(Self::on_interrupt); 136 unsafe { T::Interrupt::steal() }.unpend();
115 irq.unpend(); 137 unsafe { T::Interrupt::steal() }.enable();
116 irq.enable();
117 138
118 Self { 139 Self {
119 _peri: peri, 140 _peri: peri,
@@ -122,20 +143,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
122 } 143 }
123 } 144 }
124 145
125 unsafe fn on_interrupt(_: *mut ()) {
126 let regs = T::regs();
127 let isr = regs.isr().read();
128
129 if isr.tcr() || isr.tc() {
130 T::state().waker.wake();
131 }
132 // The flag can only be cleared by writting to nbytes, we won't do that here, so disable
133 // the interrupt
134 critical_section::with(|_| {
135 regs.cr1().modify(|w| w.set_tcie(false));
136 });
137 }
138
139 fn master_stop(&mut self) { 146 fn master_stop(&mut self) {
140 unsafe { 147 unsafe {
141 T::regs().cr2().write(|w| w.set_stop(true)); 148 T::regs().cr2().write(|w| w.set_stop(true));
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
new file mode 100644
index 000000000..2bb199f68
--- /dev/null
+++ b/embassy-stm32/src/i2s.rs
@@ -0,0 +1,310 @@
1use embassy_hal_common::into_ref;
2
3use crate::gpio::sealed::{AFType, Pin as _};
4use crate::gpio::AnyPin;
5use crate::pac::spi::vals;
6use crate::rcc::get_freqs;
7use crate::spi::{Config as SpiConfig, *};
8use crate::time::Hertz;
9use crate::{Peripheral, PeripheralRef};
10
11#[derive(Copy, Clone)]
12pub enum Mode {
13 Master,
14 Slave,
15}
16
17#[derive(Copy, Clone)]
18pub enum Function {
19 Transmit,
20 Receive,
21}
22
23#[derive(Copy, Clone)]
24pub enum Standard {
25 Philips,
26 MsbFirst,
27 LsbFirst,
28 PcmLongSync,
29 PcmShortSync,
30}
31
32impl Standard {
33 #[cfg(any(spi_v1, spi_f1))]
34 pub const fn i2sstd(&self) -> vals::I2sstd {
35 match self {
36 Standard::Philips => vals::I2sstd::PHILIPS,
37 Standard::MsbFirst => vals::I2sstd::MSB,
38 Standard::LsbFirst => vals::I2sstd::LSB,
39 Standard::PcmLongSync => vals::I2sstd::PCM,
40 Standard::PcmShortSync => vals::I2sstd::PCM,
41 }
42 }
43
44 #[cfg(any(spi_v1, spi_f1))]
45 pub const fn pcmsync(&self) -> vals::Pcmsync {
46 match self {
47 Standard::PcmLongSync => vals::Pcmsync::LONG,
48 _ => vals::Pcmsync::SHORT,
49 }
50 }
51}
52
53#[derive(Copy, Clone)]
54pub enum Format {
55 /// 16 bit data length on 16 bit wide channel
56 Data16Channel16,
57 /// 16 bit data length on 32 bit wide channel
58 Data16Channel32,
59 /// 24 bit data length on 32 bit wide channel
60 Data24Channel32,
61 /// 32 bit data length on 32 bit wide channel
62 Data32Channel32,
63}
64
65impl Format {
66 #[cfg(any(spi_v1, spi_f1))]
67 pub const fn datlen(&self) -> vals::Datlen {
68 match self {
69 Format::Data16Channel16 => vals::Datlen::SIXTEENBIT,
70 Format::Data16Channel32 => vals::Datlen::SIXTEENBIT,
71 Format::Data24Channel32 => vals::Datlen::TWENTYFOURBIT,
72 Format::Data32Channel32 => vals::Datlen::THIRTYTWOBIT,
73 }
74 }
75
76 #[cfg(any(spi_v1, spi_f1))]
77 pub const fn chlen(&self) -> vals::Chlen {
78 match self {
79 Format::Data16Channel16 => vals::Chlen::SIXTEENBIT,
80 Format::Data16Channel32 => vals::Chlen::THIRTYTWOBIT,
81 Format::Data24Channel32 => vals::Chlen::THIRTYTWOBIT,
82 Format::Data32Channel32 => vals::Chlen::THIRTYTWOBIT,
83 }
84 }
85}
86
87#[derive(Copy, Clone)]
88pub enum ClockPolarity {
89 IdleLow,
90 IdleHigh,
91}
92
93impl ClockPolarity {
94 #[cfg(any(spi_v1, spi_f1))]
95 pub const fn ckpol(&self) -> vals::Ckpol {
96 match self {
97 ClockPolarity::IdleHigh => vals::Ckpol::IDLEHIGH,
98 ClockPolarity::IdleLow => vals::Ckpol::IDLELOW,
99 }
100 }
101}
102
103/// [`I2S`] configuration.
104///
105/// - `MS`: `Master` or `Slave`
106/// - `TR`: `Transmit` or `Receive`
107/// - `STD`: I2S standard, eg `Philips`
108/// - `FMT`: Frame Format marker, eg `Data16Channel16`
109#[non_exhaustive]
110#[derive(Copy, Clone)]
111pub struct Config {
112 pub mode: Mode,
113 pub function: Function,
114 pub standard: Standard,
115 pub format: Format,
116 pub clock_polarity: ClockPolarity,
117 pub master_clock: bool,
118}
119
120impl Default for Config {
121 fn default() -> Self {
122 Self {
123 mode: Mode::Master,
124 function: Function::Transmit,
125 standard: Standard::Philips,
126 format: Format::Data16Channel16,
127 clock_polarity: ClockPolarity::IdleLow,
128 master_clock: true,
129 }
130 }
131}
132
133pub struct I2S<'d, T: Instance, Tx, Rx> {
134 _peri: Spi<'d, T, Tx, Rx>,
135 sd: Option<PeripheralRef<'d, AnyPin>>,
136 ws: Option<PeripheralRef<'d, AnyPin>>,
137 ck: Option<PeripheralRef<'d, AnyPin>>,
138 mck: Option<PeripheralRef<'d, AnyPin>>,
139}
140
141impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
142 /// Note: Full-Duplex modes are not supported at this time
143 pub fn new(
144 peri: impl Peripheral<P = T> + 'd,
145 sd: impl Peripheral<P = impl MosiPin<T>> + 'd,
146 ws: impl Peripheral<P = impl WsPin<T>> + 'd,
147 ck: impl Peripheral<P = impl CkPin<T>> + 'd,
148 mck: impl Peripheral<P = impl MckPin<T>> + 'd,
149 txdma: impl Peripheral<P = Tx> + 'd,
150 rxdma: impl Peripheral<P = Rx> + 'd,
151 freq: Hertz,
152 config: Config,
153 ) -> Self {
154 into_ref!(sd, ws, ck, mck);
155
156 unsafe {
157 sd.set_as_af(sd.af_num(), AFType::OutputPushPull);
158 sd.set_speed(crate::gpio::Speed::VeryHigh);
159
160 ws.set_as_af(ws.af_num(), AFType::OutputPushPull);
161 ws.set_speed(crate::gpio::Speed::VeryHigh);
162
163 ck.set_as_af(ck.af_num(), AFType::OutputPushPull);
164 ck.set_speed(crate::gpio::Speed::VeryHigh);
165
166 mck.set_as_af(mck.af_num(), AFType::OutputPushPull);
167 mck.set_speed(crate::gpio::Speed::VeryHigh);
168 }
169
170 let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default());
171
172 #[cfg(all(rcc_f4, not(stm32f410)))]
173 let pclk = unsafe { get_freqs() }.plli2s.unwrap();
174
175 #[cfg(stm32f410)]
176 let pclk = T::frequency();
177
178 let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format);
179
180 #[cfg(any(spi_v1, spi_f1))]
181 unsafe {
182 use stm32_metapac::spi::vals::{I2scfg, Odd};
183
184 // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR register to define the serial clock baud
185 // rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR
186 // register also has to be defined.
187
188 T::REGS.i2spr().modify(|w| {
189 w.set_i2sdiv(div);
190 w.set_odd(match odd {
191 true => Odd::ODD,
192 false => Odd::EVEN,
193 });
194
195 w.set_mckoe(config.master_clock);
196 });
197
198 // 2. Select the CKPOL bit to define the steady level for the communication clock. Set the
199 // MCKOE bit in the SPI_I2SPR register if the master clock MCK needs to be provided to
200 // the external DAC/ADC audio component (the I2SDIV and ODD values should be
201 // computed depending on the state of the MCK output, for more details refer to
202 // Section 28.4.4: Clock generator).
203
204 // 3. Set the I2SMOD bit in SPI_I2SCFGR to activate the I2S functionalities and choose the
205 // I2S standard through the I2SSTD[1:0] and PCMSYNC bits, the data length through the
206 // DATLEN[1:0] bits and the number of bits per channel by configuring the CHLEN bit.
207 // Select also the I2S master mode and direction (Transmitter or Receiver) through the
208 // I2SCFG[1:0] bits in the SPI_I2SCFGR register.
209
210 // 4. If needed, select all the potential interruption sources and the DMA capabilities by
211 // writing the SPI_CR2 register.
212
213 // 5. The I2SE bit in SPI_I2SCFGR register must be set.
214
215 T::REGS.i2scfgr().modify(|w| {
216 w.set_ckpol(config.clock_polarity.ckpol());
217
218 w.set_i2smod(true);
219 w.set_i2sstd(config.standard.i2sstd());
220 w.set_pcmsync(config.standard.pcmsync());
221
222 w.set_datlen(config.format.datlen());
223 w.set_chlen(config.format.chlen());
224
225 w.set_i2scfg(match (config.mode, config.function) {
226 (Mode::Master, Function::Transmit) => I2scfg::MASTERTX,
227 (Mode::Master, Function::Receive) => I2scfg::MASTERRX,
228 (Mode::Slave, Function::Transmit) => I2scfg::SLAVETX,
229 (Mode::Slave, Function::Receive) => I2scfg::SLAVERX,
230 });
231
232 w.set_i2se(true)
233 });
234 }
235 #[cfg(spi_v2)]
236 unsafe {}
237 #[cfg(any(spi_v3, spi_v4))]
238 unsafe {}
239
240 Self {
241 _peri: spi,
242 sd: Some(sd.map_into()),
243 ws: Some(ws.map_into()),
244 ck: Some(ck.map_into()),
245 mck: Some(mck.map_into()),
246 }
247 }
248
249 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
250 where
251 Tx: TxDma<T>,
252 {
253 self._peri.write(data).await
254 }
255
256 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
257 where
258 Tx: TxDma<T>,
259 Rx: RxDma<T>,
260 {
261 self._peri.read(data).await
262 }
263}
264
265impl<'d, T: Instance, Tx, Rx> Drop for I2S<'d, T, Tx, Rx> {
266 fn drop(&mut self) {
267 unsafe {
268 self.sd.as_ref().map(|x| x.set_as_disconnected());
269 self.ws.as_ref().map(|x| x.set_as_disconnected());
270 self.ck.as_ref().map(|x| x.set_as_disconnected());
271 self.mck.as_ref().map(|x| x.set_as_disconnected());
272 }
273 }
274}
275
276// Note, calculation details:
277// Fs = i2s_clock / [256 * ((2 * div) + odd)] when master clock is enabled
278// Fs = i2s_clock / [(channel_length * 2) * ((2 * div) + odd)]` when master clock is disabled
279// channel_length is 16 or 32
280//
281// can be rewritten as
282// Fs = i2s_clock / (coef * division)
283// where coef is a constant equal to 256, 64 or 32 depending channel length and master clock
284// and where division = (2 * div) + odd
285//
286// Equation can be rewritten as
287// division = i2s_clock/ (coef * Fs)
288//
289// note: division = (2 * div) + odd = (div << 1) + odd
290// in other word, from bits point of view, division[8:1] = div[7:0] and division[0] = odd
291fn compute_baud_rate(i2s_clock: Hertz, request_freq: Hertz, mclk: bool, data_format: Format) -> (bool, u8) {
292 let coef = if mclk {
293 256
294 } else if let Format::Data16Channel16 = data_format {
295 32
296 } else {
297 64
298 };
299
300 let (n, d) = (i2s_clock.0, coef * request_freq.0);
301 let division = (n + (d >> 1)) / d;
302
303 if division < 4 {
304 (false, 2)
305 } else if division > 511 {
306 (true, 255)
307 } else {
308 ((division & 1) == 1, (division >> 1) as u8)
309 }
310}
diff --git a/embassy-stm32/src/interrupt.rs b/embassy-stm32/src/interrupt.rs
deleted file mode 100644
index b66e4c7ef..000000000
--- a/embassy-stm32/src/interrupt.rs
+++ /dev/null
@@ -1,4 +0,0 @@
1pub use critical_section::{CriticalSection, Mutex};
2pub use embassy_cortex_m::interrupt::*;
3
4pub use crate::_generated::interrupt::*;
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 1920e2642..c9df5c1b2 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -6,7 +6,6 @@ pub mod fmt;
6include!(concat!(env!("OUT_DIR"), "/_macros.rs")); 6include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
7 7
8// Utilities 8// Utilities
9pub mod interrupt;
10pub mod time; 9pub mod time;
11mod traits; 10mod traits;
12 11
@@ -40,6 +39,8 @@ pub mod i2c;
40#[cfg(crc)] 39#[cfg(crc)]
41pub mod crc; 40pub mod crc;
42pub mod flash; 41pub mod flash;
42#[cfg(all(spi_v1, rcc_f4))]
43pub mod i2s;
43#[cfg(stm32wb)] 44#[cfg(stm32wb)]
44pub mod ipcc; 45pub mod ipcc;
45pub mod pwm; 46pub mod pwm;
@@ -73,6 +74,41 @@ pub(crate) mod _generated {
73 include!(concat!(env!("OUT_DIR"), "/_generated.rs")); 74 include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
74} 75}
75 76
77pub mod interrupt {
78 //! Interrupt definitions and macros to bind them.
79 pub use cortex_m::interrupt::{CriticalSection, Mutex};
80 pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, InterruptExt, Priority};
81
82 pub use crate::_generated::interrupt::*;
83
84 /// Macro to bind interrupts to handlers.
85 ///
86 /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
87 /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
88 /// prove at compile-time that the right interrupts have been bound.
89 // developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`.
90 #[macro_export]
91 macro_rules! bind_interrupts {
92 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
93 $vis struct $name;
94
95 $(
96 #[allow(non_snake_case)]
97 #[no_mangle]
98 unsafe extern "C" fn $irq() {
99 $(
100 <$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt();
101 )*
102 }
103
104 $(
105 unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {}
106 )*
107 )*
108 };
109 }
110}
111
76// Reexports 112// Reexports
77pub use _generated::{peripherals, Peripherals}; 113pub use _generated::{peripherals, Peripherals};
78pub use embassy_cortex_m::executor; 114pub use embassy_cortex_m::executor;
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index be788f1b0..be03a1bac 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -2,6 +2,7 @@
2 2
3use core::default::Default; 3use core::default::Default;
4use core::future::poll_fn; 4use core::future::poll_fn;
5use core::marker::PhantomData;
5use core::ops::{Deref, DerefMut}; 6use core::ops::{Deref, DerefMut};
6use core::task::Poll; 7use core::task::Poll;
7 8
@@ -17,7 +18,36 @@ use crate::interrupt::{Interrupt, InterruptExt};
17use crate::pac::sdmmc::Sdmmc as RegBlock; 18use crate::pac::sdmmc::Sdmmc as RegBlock;
18use crate::rcc::RccPeripheral; 19use crate::rcc::RccPeripheral;
19use crate::time::Hertz; 20use crate::time::Hertz;
20use crate::{peripherals, Peripheral}; 21use crate::{interrupt, peripherals, Peripheral};
22
23/// Interrupt handler.
24pub struct InterruptHandler<T: Instance> {
25 _phantom: PhantomData<T>,
26}
27
28impl<T: Instance> InterruptHandler<T> {
29 fn data_interrupts(enable: bool) {
30 let regs = T::regs();
31 // NOTE(unsafe) Atomic write
32 unsafe {
33 regs.maskr().write(|w| {
34 w.set_dcrcfailie(enable);
35 w.set_dtimeoutie(enable);
36 w.set_dataendie(enable);
37
38 #[cfg(sdmmc_v2)]
39 w.set_dabortie(enable);
40 });
41 }
42 }
43}
44
45impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
46 unsafe fn on_interrupt() {
47 Self::data_interrupts(false);
48 T::state().wake();
49 }
50}
21 51
22/// Frequency used for SD Card initialization. Must be no higher than 400 kHz. 52/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
23const SD_INIT_FREQ: Hertz = Hertz(400_000); 53const SD_INIT_FREQ: Hertz = Hertz(400_000);
@@ -223,7 +253,6 @@ impl Default for Config {
223/// Sdmmc device 253/// Sdmmc device
224pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { 254pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
225 _peri: PeripheralRef<'d, T>, 255 _peri: PeripheralRef<'d, T>,
226 irq: PeripheralRef<'d, T::Interrupt>,
227 #[allow(unused)] 256 #[allow(unused)]
228 dma: PeripheralRef<'d, Dma>, 257 dma: PeripheralRef<'d, Dma>,
229 258
@@ -247,7 +276,7 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
247impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { 276impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
248 pub fn new_1bit( 277 pub fn new_1bit(
249 sdmmc: impl Peripheral<P = T> + 'd, 278 sdmmc: impl Peripheral<P = T> + 'd,
250 irq: impl Peripheral<P = T::Interrupt> + 'd, 279 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
251 dma: impl Peripheral<P = Dma> + 'd, 280 dma: impl Peripheral<P = Dma> + 'd,
252 clk: impl Peripheral<P = impl CkPin<T>> + 'd, 281 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
253 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, 282 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
@@ -268,7 +297,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
268 297
269 Self::new_inner( 298 Self::new_inner(
270 sdmmc, 299 sdmmc,
271 irq,
272 dma, 300 dma,
273 clk.map_into(), 301 clk.map_into(),
274 cmd.map_into(), 302 cmd.map_into(),
@@ -282,7 +310,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
282 310
283 pub fn new_4bit( 311 pub fn new_4bit(
284 sdmmc: impl Peripheral<P = T> + 'd, 312 sdmmc: impl Peripheral<P = T> + 'd,
285 irq: impl Peripheral<P = T::Interrupt> + 'd, 313 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
286 dma: impl Peripheral<P = Dma> + 'd, 314 dma: impl Peripheral<P = Dma> + 'd,
287 clk: impl Peripheral<P = impl CkPin<T>> + 'd, 315 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
288 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, 316 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
@@ -312,7 +340,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
312 340
313 Self::new_inner( 341 Self::new_inner(
314 sdmmc, 342 sdmmc,
315 irq,
316 dma, 343 dma,
317 clk.map_into(), 344 clk.map_into(),
318 cmd.map_into(), 345 cmd.map_into(),
@@ -329,7 +356,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
329impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { 356impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
330 pub fn new_1bit( 357 pub fn new_1bit(
331 sdmmc: impl Peripheral<P = T> + 'd, 358 sdmmc: impl Peripheral<P = T> + 'd,
332 irq: impl Peripheral<P = T::Interrupt> + 'd, 359 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
333 clk: impl Peripheral<P = impl CkPin<T>> + 'd, 360 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
334 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, 361 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
335 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 362 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
@@ -349,7 +376,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
349 376
350 Self::new_inner( 377 Self::new_inner(
351 sdmmc, 378 sdmmc,
352 irq,
353 NoDma.into_ref(), 379 NoDma.into_ref(),
354 clk.map_into(), 380 clk.map_into(),
355 cmd.map_into(), 381 cmd.map_into(),
@@ -363,7 +389,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
363 389
364 pub fn new_4bit( 390 pub fn new_4bit(
365 sdmmc: impl Peripheral<P = T> + 'd, 391 sdmmc: impl Peripheral<P = T> + 'd,
366 irq: impl Peripheral<P = T::Interrupt> + 'd, 392 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
367 clk: impl Peripheral<P = impl CkPin<T>> + 'd, 393 clk: impl Peripheral<P = impl CkPin<T>> + 'd,
368 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, 394 cmd: impl Peripheral<P = impl CmdPin<T>> + 'd,
369 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 395 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
@@ -392,7 +418,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
392 418
393 Self::new_inner( 419 Self::new_inner(
394 sdmmc, 420 sdmmc,
395 irq,
396 NoDma.into_ref(), 421 NoDma.into_ref(),
397 clk.map_into(), 422 clk.map_into(),
398 cmd.map_into(), 423 cmd.map_into(),
@@ -408,7 +433,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
408impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { 433impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
409 fn new_inner( 434 fn new_inner(
410 sdmmc: impl Peripheral<P = T> + 'd, 435 sdmmc: impl Peripheral<P = T> + 'd,
411 irq: impl Peripheral<P = T::Interrupt> + 'd,
412 dma: impl Peripheral<P = Dma> + 'd, 436 dma: impl Peripheral<P = Dma> + 'd,
413 clk: PeripheralRef<'d, AnyPin>, 437 clk: PeripheralRef<'d, AnyPin>,
414 cmd: PeripheralRef<'d, AnyPin>, 438 cmd: PeripheralRef<'d, AnyPin>,
@@ -418,14 +442,13 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
418 d3: Option<PeripheralRef<'d, AnyPin>>, 442 d3: Option<PeripheralRef<'d, AnyPin>>,
419 config: Config, 443 config: Config,
420 ) -> Self { 444 ) -> Self {
421 into_ref!(sdmmc, irq, dma); 445 into_ref!(sdmmc, dma);
422 446
423 T::enable(); 447 T::enable();
424 T::reset(); 448 T::reset();
425 449
426 irq.set_handler(Self::on_interrupt); 450 unsafe { T::Interrupt::steal() }.unpend();
427 irq.unpend(); 451 unsafe { T::Interrupt::steal() }.enable();
428 irq.enable();
429 452
430 let regs = T::regs(); 453 let regs = T::regs();
431 unsafe { 454 unsafe {
@@ -451,7 +474,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
451 474
452 Self { 475 Self {
453 _peri: sdmmc, 476 _peri: sdmmc,
454 irq,
455 dma, 477 dma,
456 478
457 clk, 479 clk,
@@ -691,7 +713,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
691 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 713 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
692 714
693 let transfer = self.prepare_datapath_read(&mut status, 64, 6); 715 let transfer = self.prepare_datapath_read(&mut status, 64, 6);
694 Self::data_interrupts(true); 716 InterruptHandler::<T>::data_interrupts(true);
695 Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6 717 Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6
696 718
697 let res = poll_fn(|cx| { 719 let res = poll_fn(|cx| {
@@ -767,7 +789,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
767 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 789 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
768 790
769 let transfer = self.prepare_datapath_read(&mut status, 64, 6); 791 let transfer = self.prepare_datapath_read(&mut status, 64, 6);
770 Self::data_interrupts(true); 792 InterruptHandler::<T>::data_interrupts(true);
771 Self::cmd(Cmd::card_status(0), true)?; 793 Self::cmd(Cmd::card_status(0), true)?;
772 794
773 let res = poll_fn(|cx| { 795 let res = poll_fn(|cx| {
@@ -849,23 +871,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
849 } 871 }
850 } 872 }
851 873
852 /// Enables the interrupts for data transfer
853 #[inline(always)]
854 fn data_interrupts(enable: bool) {
855 let regs = T::regs();
856 // NOTE(unsafe) Atomic write
857 unsafe {
858 regs.maskr().write(|w| {
859 w.set_dcrcfailie(enable);
860 w.set_dtimeoutie(enable);
861 w.set_dataendie(enable);
862
863 #[cfg(sdmmc_v2)]
864 w.set_dabortie(enable);
865 });
866 }
867 }
868
869 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { 874 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
870 // Read the the 64-bit SCR register 875 // Read the the 64-bit SCR register
871 Self::cmd(Cmd::set_block_length(8), false)?; // CMD16 876 Self::cmd(Cmd::set_block_length(8), false)?; // CMD16
@@ -878,7 +883,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
878 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 883 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
879 884
880 let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3); 885 let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3);
881 Self::data_interrupts(true); 886 InterruptHandler::<T>::data_interrupts(true);
882 Self::cmd(Cmd::cmd51(), true)?; 887 Self::cmd(Cmd::cmd51(), true)?;
883 888
884 let res = poll_fn(|cx| { 889 let res = poll_fn(|cx| {
@@ -996,7 +1001,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
996 // Wait for the abort 1001 // Wait for the abort
997 while Self::data_active() {} 1002 while Self::data_active() {}
998 } 1003 }
999 Self::data_interrupts(false); 1004 InterruptHandler::<T>::data_interrupts(false);
1000 Self::clear_interrupt_flags(); 1005 Self::clear_interrupt_flags();
1001 Self::stop_datapath(); 1006 Self::stop_datapath();
1002 } 1007 }
@@ -1170,7 +1175,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1170 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 1175 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() });
1171 1176
1172 let transfer = self.prepare_datapath_read(buffer, 512, 9); 1177 let transfer = self.prepare_datapath_read(buffer, 512, 9);
1173 Self::data_interrupts(true); 1178 InterruptHandler::<T>::data_interrupts(true);
1174 Self::cmd(Cmd::read_single_block(address), true)?; 1179 Self::cmd(Cmd::read_single_block(address), true)?;
1175 1180
1176 let res = poll_fn(|cx| { 1181 let res = poll_fn(|cx| {
@@ -1219,7 +1224,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1219 Self::cmd(Cmd::write_single_block(address), true)?; 1224 Self::cmd(Cmd::write_single_block(address), true)?;
1220 1225
1221 let transfer = self.prepare_datapath_write(buffer, 512, 9); 1226 let transfer = self.prepare_datapath_write(buffer, 512, 9);
1222 Self::data_interrupts(true); 1227 InterruptHandler::<T>::data_interrupts(true);
1223 1228
1224 #[cfg(sdmmc_v2)] 1229 #[cfg(sdmmc_v2)]
1225 Self::cmd(Cmd::write_single_block(address), true)?; 1230 Self::cmd(Cmd::write_single_block(address), true)?;
@@ -1279,17 +1284,11 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1279 pub fn clock(&self) -> Hertz { 1284 pub fn clock(&self) -> Hertz {
1280 self.clock 1285 self.clock
1281 } 1286 }
1282
1283 #[inline(always)]
1284 fn on_interrupt(_: *mut ()) {
1285 Self::data_interrupts(false);
1286 T::state().wake();
1287 }
1288} 1287}
1289 1288
1290impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { 1289impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> {
1291 fn drop(&mut self) { 1290 fn drop(&mut self) {
1292 self.irq.disable(); 1291 unsafe { T::Interrupt::steal() }.disable();
1293 unsafe { Self::on_drop() }; 1292 unsafe { Self::on_drop() };
1294 1293
1295 critical_section::with(|_| unsafe { 1294 critical_section::with(|_| unsafe {
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 7390830dc..580971e45 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -212,6 +212,17 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
212 Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config) 212 Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config)
213 } 213 }
214 214
215 #[allow(dead_code)]
216 pub(crate) fn new_internal(
217 peri: impl Peripheral<P = T> + 'd,
218 txdma: impl Peripheral<P = Tx> + 'd,
219 rxdma: impl Peripheral<P = Rx> + 'd,
220 freq: Hertz,
221 config: Config,
222 ) -> Self {
223 Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config)
224 }
225
215 fn new_inner( 226 fn new_inner(
216 peri: impl Peripheral<P = T> + 'd, 227 peri: impl Peripheral<P = T> + 'd,
217 sck: Option<PeripheralRef<'d, AnyPin>>, 228 sck: Option<PeripheralRef<'d, AnyPin>>,
@@ -1044,6 +1055,10 @@ pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
1044pin_trait!(SckPin, Instance); 1055pin_trait!(SckPin, Instance);
1045pin_trait!(MosiPin, Instance); 1056pin_trait!(MosiPin, Instance);
1046pin_trait!(MisoPin, Instance); 1057pin_trait!(MisoPin, Instance);
1058pin_trait!(CsPin, Instance);
1059pin_trait!(MckPin, Instance);
1060pin_trait!(CkPin, Instance);
1061pin_trait!(WsPin, Instance);
1047dma_trait!(RxDma, Instance); 1062dma_trait!(RxDma, Instance);
1048dma_trait!(TxDma, Instance); 1063dma_trait!(TxDma, Instance);
1049 1064
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index d45c90dd8..2236fde28 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -4,13 +4,14 @@ use core::sync::atomic::{compiler_fence, Ordering};
4use core::{mem, ptr}; 4use core::{mem, ptr};
5 5
6use atomic_polyfill::{AtomicU32, AtomicU8}; 6use atomic_polyfill::{AtomicU32, AtomicU8};
7use critical_section::CriticalSection;
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::blocking_mutex::Mutex; 9use embassy_sync::blocking_mutex::Mutex;
9use embassy_time::driver::{AlarmHandle, Driver}; 10use embassy_time::driver::{AlarmHandle, Driver};
10use embassy_time::TICK_HZ; 11use embassy_time::TICK_HZ;
11use stm32_metapac::timer::regs; 12use stm32_metapac::timer::regs;
12 13
13use crate::interrupt::{CriticalSection, InterruptExt}; 14use crate::interrupt::InterruptExt;
14use crate::pac::timer::vals; 15use crate::pac::timer::vals;
15use crate::rcc::sealed::RccPeripheral; 16use crate::rcc::sealed::RccPeripheral;
16use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance}; 17use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance};
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs
index 3651b8ea5..dc6104cc3 100644
--- a/embassy-stm32/src/tl_mbox/mod.rs
+++ b/embassy-stm32/src/tl_mbox/mod.rs
@@ -1,7 +1,6 @@
1use core::mem::MaybeUninit; 1use core::mem::MaybeUninit;
2 2
3use bit_field::BitField; 3use bit_field::BitField;
4use embassy_cortex_m::interrupt::InterruptExt;
5use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 4use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
6use embassy_sync::channel::Channel; 5use embassy_sync::channel::Channel;
7 6
@@ -12,7 +11,7 @@ use self::mm::MemoryManager;
12use self::shci::{shci_ble_init, ShciBleInitCmdParam}; 11use self::shci::{shci_ble_init, ShciBleInitCmdParam};
13use self::sys::Sys; 12use self::sys::Sys;
14use self::unsafe_linked_list::LinkedListNode; 13use self::unsafe_linked_list::LinkedListNode;
15use crate::_generated::interrupt::{IPCC_C1_RX, IPCC_C1_TX}; 14use crate::interrupt;
16use crate::ipcc::Ipcc; 15use crate::ipcc::Ipcc;
17 16
18mod ble; 17mod ble;
@@ -55,6 +54,19 @@ pub struct FusInfoTable {
55 fus_info: u32, 54 fus_info: u32,
56} 55}
57 56
57/// Interrupt handler.
58pub struct ReceiveInterruptHandler {}
59
60impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler {
61 unsafe fn on_interrupt() {}
62}
63
64pub struct TransmitInterruptHandler {}
65
66impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler {
67 unsafe fn on_interrupt() {}
68}
69
58/// # Version 70/// # Version
59/// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version 71/// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version
60/// - 4 -> 7 = branch - 0: Mass Market - x: ... 72/// - 4 -> 7 = branch - 0: Mass Market - x: ...
@@ -285,7 +297,11 @@ pub struct TlMbox {
285 297
286impl TlMbox { 298impl TlMbox {
287 /// initializes low-level transport between CPU1 and BLE stack on CPU2 299 /// initializes low-level transport between CPU1 and BLE stack on CPU2
288 pub fn init(ipcc: &mut Ipcc, rx_irq: IPCC_C1_RX, tx_irq: IPCC_C1_TX) -> TlMbox { 300 pub fn init(
301 ipcc: &mut Ipcc,
302 _irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler>
303 + interrupt::Binding<interrupt::IPCC_C1_TX, TransmitInterruptHandler>,
304 ) -> TlMbox {
289 unsafe { 305 unsafe {
290 TL_REF_TABLE = MaybeUninit::new(RefTable { 306 TL_REF_TABLE = MaybeUninit::new(RefTable {
291 device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), 307 device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(),
@@ -326,23 +342,23 @@ impl TlMbox {
326 let _ble = Ble::new(ipcc); 342 let _ble = Ble::new(ipcc);
327 let _mm = MemoryManager::new(); 343 let _mm = MemoryManager::new();
328 344
329 rx_irq.disable(); 345 // rx_irq.disable();
330 tx_irq.disable(); 346 // tx_irq.disable();
331 347 //
332 rx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ()); 348 // rx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ());
333 tx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ()); 349 // tx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ());
334 350 //
335 rx_irq.set_handler(|ipcc| { 351 // rx_irq.set_handler(|ipcc| {
336 let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() }; 352 // let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() };
337 Self::interrupt_ipcc_rx_handler(ipcc); 353 // Self::interrupt_ipcc_rx_handler(ipcc);
338 }); 354 // });
339 tx_irq.set_handler(|ipcc| { 355 // tx_irq.set_handler(|ipcc| {
340 let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() }; 356 // let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() };
341 Self::interrupt_ipcc_tx_handler(ipcc); 357 // Self::interrupt_ipcc_tx_handler(ipcc);
342 }); 358 // });
343 359 //
344 rx_irq.enable(); 360 // rx_irq.enable();
345 tx_irq.enable(); 361 // tx_irq.enable();
346 362
347 TlMbox { _sys, _ble, _mm } 363 TlMbox { _sys, _ble, _mm }
348 } 364 }
@@ -374,6 +390,7 @@ impl TlMbox {
374 TL_CHANNEL.recv().await 390 TL_CHANNEL.recv().await
375 } 391 }
376 392
393 #[allow(dead_code)]
377 fn interrupt_ipcc_rx_handler(ipcc: &mut Ipcc) { 394 fn interrupt_ipcc_rx_handler(ipcc: &mut Ipcc) {
378 if ipcc.is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { 395 if ipcc.is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) {
379 sys::Sys::evt_handler(ipcc); 396 sys::Sys::evt_handler(ipcc);
@@ -384,6 +401,7 @@ impl TlMbox {
384 } 401 }
385 } 402 }
386 403
404 #[allow(dead_code)]
387 fn interrupt_ipcc_tx_handler(ipcc: &mut Ipcc) { 405 fn interrupt_ipcc_tx_handler(ipcc: &mut Ipcc) {
388 if ipcc.is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { 406 if ipcc.is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) {
389 // TODO: handle this case 407 // TODO: handle this case
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 12cf8b0fc..9f1da3583 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -8,6 +8,78 @@ use embassy_sync::waitqueue::AtomicWaker;
8 8
9use super::*; 9use super::*;
10 10
11/// Interrupt handler.
12pub struct InterruptHandler<T: BasicInstance> {
13 _phantom: PhantomData<T>,
14}
15
16impl<T: BasicInstance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
17 unsafe fn on_interrupt() {
18 let r = T::regs();
19 let state = T::buffered_state();
20
21 // RX
22 unsafe {
23 let sr = sr(r).read();
24 clear_interrupt_flags(r, sr);
25
26 if sr.rxne() {
27 if sr.pe() {
28 warn!("Parity error");
29 }
30 if sr.fe() {
31 warn!("Framing error");
32 }
33 if sr.ne() {
34 warn!("Noise error");
35 }
36 if sr.ore() {
37 warn!("Overrun error");
38 }
39
40 let mut rx_writer = state.rx_buf.writer();
41 let buf = rx_writer.push_slice();
42 if !buf.is_empty() {
43 // This read also clears the error and idle interrupt flags on v1.
44 buf[0] = rdr(r).read_volatile();
45 rx_writer.push_done(1);
46 } else {
47 // FIXME: Should we disable any further RX interrupts when the buffer becomes full.
48 }
49
50 if state.rx_buf.is_full() {
51 state.rx_waker.wake();
52 }
53 }
54
55 if sr.idle() {
56 state.rx_waker.wake();
57 };
58 }
59
60 // TX
61 unsafe {
62 if sr(r).read().txe() {
63 let mut tx_reader = state.tx_buf.reader();
64 let buf = tx_reader.pop_slice();
65 if !buf.is_empty() {
66 r.cr1().modify(|w| {
67 w.set_txeie(true);
68 });
69 tdr(r).write_volatile(buf[0].into());
70 tx_reader.pop_done(1);
71 state.tx_waker.wake();
72 } else {
73 // Disable interrupt until we have something to transmit again
74 r.cr1().modify(|w| {
75 w.set_txeie(false);
76 });
77 }
78 }
79 }
80 }
81}
82
11pub struct State { 83pub struct State {
12 rx_waker: AtomicWaker, 84 rx_waker: AtomicWaker,
13 rx_buf: RingBuffer, 85 rx_buf: RingBuffer,
@@ -43,7 +115,7 @@ pub struct BufferedUartRx<'d, T: BasicInstance> {
43impl<'d, T: BasicInstance> BufferedUart<'d, T> { 115impl<'d, T: BasicInstance> BufferedUart<'d, T> {
44 pub fn new( 116 pub fn new(
45 peri: impl Peripheral<P = T> + 'd, 117 peri: impl Peripheral<P = T> + 'd,
46 irq: impl Peripheral<P = T::Interrupt> + 'd, 118 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
47 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 119 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
48 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 120 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
49 tx_buffer: &'d mut [u8], 121 tx_buffer: &'d mut [u8],
@@ -53,12 +125,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
53 T::enable(); 125 T::enable();
54 T::reset(); 126 T::reset();
55 127
56 Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config) 128 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
57 } 129 }
58 130
59 pub fn new_with_rtscts( 131 pub fn new_with_rtscts(
60 peri: impl Peripheral<P = T> + 'd, 132 peri: impl Peripheral<P = T> + 'd,
61 irq: impl Peripheral<P = T::Interrupt> + 'd, 133 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
62 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 134 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
63 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 135 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
64 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 136 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
@@ -81,13 +153,13 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
81 }); 153 });
82 } 154 }
83 155
84 Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config) 156 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
85 } 157 }
86 158
87 #[cfg(not(any(usart_v1, usart_v2)))] 159 #[cfg(not(any(usart_v1, usart_v2)))]
88 pub fn new_with_de( 160 pub fn new_with_de(
89 peri: impl Peripheral<P = T> + 'd, 161 peri: impl Peripheral<P = T> + 'd,
90 irq: impl Peripheral<P = T::Interrupt> + 'd, 162 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
91 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 163 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
92 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 164 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
93 de: impl Peripheral<P = impl DePin<T>> + 'd, 165 de: impl Peripheral<P = impl DePin<T>> + 'd,
@@ -107,19 +179,18 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
107 }); 179 });
108 } 180 }
109 181
110 Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config) 182 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
111 } 183 }
112 184
113 fn new_inner( 185 fn new_inner(
114 _peri: impl Peripheral<P = T> + 'd, 186 _peri: impl Peripheral<P = T> + 'd,
115 irq: impl Peripheral<P = T::Interrupt> + 'd,
116 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 187 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
117 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 188 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
118 tx_buffer: &'d mut [u8], 189 tx_buffer: &'d mut [u8],
119 rx_buffer: &'d mut [u8], 190 rx_buffer: &'d mut [u8],
120 config: Config, 191 config: Config,
121 ) -> BufferedUart<'d, T> { 192 ) -> BufferedUart<'d, T> {
122 into_ref!(_peri, rx, tx, irq); 193 into_ref!(_peri, rx, tx);
123 194
124 let state = T::buffered_state(); 195 let state = T::buffered_state();
125 let len = tx_buffer.len(); 196 let len = tx_buffer.len();
@@ -145,9 +216,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
145 }); 216 });
146 } 217 }
147 218
148 irq.set_handler(on_interrupt::<T>); 219 unsafe { T::Interrupt::steal() }.unpend();
149 irq.unpend(); 220 unsafe { T::Interrupt::steal() }.enable();
150 irq.enable();
151 221
152 Self { 222 Self {
153 rx: BufferedUartRx { phantom: PhantomData }, 223 rx: BufferedUartRx { phantom: PhantomData },
@@ -336,71 +406,6 @@ impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> {
336 } 406 }
337} 407}
338 408
339unsafe fn on_interrupt<T: BasicInstance>(_: *mut ()) {
340 let r = T::regs();
341 let state = T::buffered_state();
342
343 // RX
344 unsafe {
345 let sr = sr(r).read();
346 clear_interrupt_flags(r, sr);
347
348 if sr.rxne() {
349 if sr.pe() {
350 warn!("Parity error");
351 }
352 if sr.fe() {
353 warn!("Framing error");
354 }
355 if sr.ne() {
356 warn!("Noise error");
357 }
358 if sr.ore() {
359 warn!("Overrun error");
360 }
361
362 let mut rx_writer = state.rx_buf.writer();
363 let buf = rx_writer.push_slice();
364 if !buf.is_empty() {
365 // This read also clears the error and idle interrupt flags on v1.
366 buf[0] = rdr(r).read_volatile();
367 rx_writer.push_done(1);
368 } else {
369 // FIXME: Should we disable any further RX interrupts when the buffer becomes full.
370 }
371
372 if state.rx_buf.is_full() {
373 state.rx_waker.wake();
374 }
375 }
376
377 if sr.idle() {
378 state.rx_waker.wake();
379 };
380 }
381
382 // TX
383 unsafe {
384 if sr(r).read().txe() {
385 let mut tx_reader = state.tx_buf.reader();
386 let buf = tx_reader.pop_slice();
387 if !buf.is_empty() {
388 r.cr1().modify(|w| {
389 w.set_txeie(true);
390 });
391 tdr(r).write_volatile(buf[0].into());
392 tx_reader.pop_done(1);
393 state.tx_waker.wake();
394 } else {
395 // Disable interrupt until we have something to transmit again
396 r.cr1().modify(|w| {
397 w.set_txeie(false);
398 });
399 }
400 }
401 }
402}
403
404impl embedded_io::Error for Error { 409impl embedded_io::Error for Error {
405 fn kind(&self) -> embedded_io::ErrorKind { 410 fn kind(&self) -> embedded_io::ErrorKind {
406 embedded_io::ErrorKind::Other 411 embedded_io::ErrorKind::Other
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index b4373529c..0f3e9412e 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -5,7 +5,7 @@ use core::marker::PhantomData;
5use core::sync::atomic::{compiler_fence, Ordering}; 5use core::sync::atomic::{compiler_fence, Ordering};
6use core::task::Poll; 6use core::task::Poll;
7 7
8use embassy_cortex_m::interrupt::InterruptExt; 8use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
9use embassy_hal_common::drop::OnDrop; 9use embassy_hal_common::drop::OnDrop;
10use embassy_hal_common::{into_ref, PeripheralRef}; 10use embassy_hal_common::{into_ref, PeripheralRef};
11use futures::future::{select, Either}; 11use futures::future::{select, Either};
@@ -18,7 +18,71 @@ use crate::pac::usart::Lpuart as Regs;
18use crate::pac::usart::Usart as Regs; 18use crate::pac::usart::Usart as Regs;
19use crate::pac::usart::{regs, vals}; 19use crate::pac::usart::{regs, vals};
20use crate::time::Hertz; 20use crate::time::Hertz;
21use crate::{peripherals, Peripheral}; 21use crate::{interrupt, peripherals, Peripheral};
22
23/// Interrupt handler.
24pub struct InterruptHandler<T: BasicInstance> {
25 _phantom: PhantomData<T>,
26}
27
28impl<T: BasicInstance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
29 unsafe fn on_interrupt() {
30 let r = T::regs();
31 let s = T::state();
32
33 let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) };
34
35 let mut wake = false;
36 let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
37 if has_errors {
38 // clear all interrupts and DMA Rx Request
39 unsafe {
40 r.cr1().modify(|w| {
41 // disable RXNE interrupt
42 w.set_rxneie(false);
43 // disable parity interrupt
44 w.set_peie(false);
45 // disable idle line interrupt
46 w.set_idleie(false);
47 });
48 r.cr3().modify(|w| {
49 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
50 w.set_eie(false);
51 // disable DMA Rx Request
52 w.set_dmar(false);
53 });
54 }
55
56 wake = true;
57 } else {
58 if cr1.idleie() && sr.idle() {
59 // IDLE detected: no more data will come
60 unsafe {
61 r.cr1().modify(|w| {
62 // disable idle line detection
63 w.set_idleie(false);
64 });
65 }
66
67 wake = true;
68 }
69
70 if cr1.rxneie() {
71 // We cannot check the RXNE flag as it is auto-cleared by the DMA controller
72
73 // It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection
74
75 wake = true;
76 }
77 }
78
79 if wake {
80 compiler_fence(Ordering::SeqCst);
81
82 s.rx_waker.wake();
83 }
84 }
85}
22 86
23#[derive(Clone, Copy, PartialEq, Eq, Debug)] 87#[derive(Clone, Copy, PartialEq, Eq, Debug)]
24pub enum DataBits { 88pub enum DataBits {
@@ -215,7 +279,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
215 /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. 279 /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
216 pub fn new( 280 pub fn new(
217 peri: impl Peripheral<P = T> + 'd, 281 peri: impl Peripheral<P = T> + 'd,
218 irq: impl Peripheral<P = T::Interrupt> + 'd, 282 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
219 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 283 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
220 rx_dma: impl Peripheral<P = RxDma> + 'd, 284 rx_dma: impl Peripheral<P = RxDma> + 'd,
221 config: Config, 285 config: Config,
@@ -223,12 +287,12 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
223 T::enable(); 287 T::enable();
224 T::reset(); 288 T::reset();
225 289
226 Self::new_inner(peri, irq, rx, rx_dma, config) 290 Self::new_inner(peri, rx, rx_dma, config)
227 } 291 }
228 292
229 pub fn new_with_rts( 293 pub fn new_with_rts(
230 peri: impl Peripheral<P = T> + 'd, 294 peri: impl Peripheral<P = T> + 'd,
231 irq: impl Peripheral<P = T::Interrupt> + 'd, 295 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
232 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 296 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
233 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 297 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
234 rx_dma: impl Peripheral<P = RxDma> + 'd, 298 rx_dma: impl Peripheral<P = RxDma> + 'd,
@@ -246,17 +310,16 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
246 }); 310 });
247 } 311 }
248 312
249 Self::new_inner(peri, irq, rx, rx_dma, config) 313 Self::new_inner(peri, rx, rx_dma, config)
250 } 314 }
251 315
252 fn new_inner( 316 fn new_inner(
253 peri: impl Peripheral<P = T> + 'd, 317 peri: impl Peripheral<P = T> + 'd,
254 irq: impl Peripheral<P = T::Interrupt> + 'd,
255 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 318 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
256 rx_dma: impl Peripheral<P = RxDma> + 'd, 319 rx_dma: impl Peripheral<P = RxDma> + 'd,
257 config: Config, 320 config: Config,
258 ) -> Self { 321 ) -> Self {
259 into_ref!(peri, irq, rx, rx_dma); 322 into_ref!(peri, rx, rx_dma);
260 323
261 let r = T::regs(); 324 let r = T::regs();
262 325
@@ -266,9 +329,8 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
266 329
267 configure(r, &config, T::frequency(), T::KIND, true, false); 330 configure(r, &config, T::frequency(), T::KIND, true, false);
268 331
269 irq.set_handler(Self::on_interrupt); 332 unsafe { T::Interrupt::steal() }.unpend();
270 irq.unpend(); 333 unsafe { T::Interrupt::steal() }.enable();
271 irq.enable();
272 334
273 // create state once! 335 // create state once!
274 let _s = T::state(); 336 let _s = T::state();
@@ -282,63 +344,6 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
282 } 344 }
283 } 345 }
284 346
285 fn on_interrupt(_: *mut ()) {
286 let r = T::regs();
287 let s = T::state();
288
289 let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) };
290
291 let mut wake = false;
292 let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
293 if has_errors {
294 // clear all interrupts and DMA Rx Request
295 unsafe {
296 r.cr1().modify(|w| {
297 // disable RXNE interrupt
298 w.set_rxneie(false);
299 // disable parity interrupt
300 w.set_peie(false);
301 // disable idle line interrupt
302 w.set_idleie(false);
303 });
304 r.cr3().modify(|w| {
305 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
306 w.set_eie(false);
307 // disable DMA Rx Request
308 w.set_dmar(false);
309 });
310 }
311
312 wake = true;
313 } else {
314 if cr1.idleie() && sr.idle() {
315 // IDLE detected: no more data will come
316 unsafe {
317 r.cr1().modify(|w| {
318 // disable idle line detection
319 w.set_idleie(false);
320 });
321 }
322
323 wake = true;
324 }
325
326 if cr1.rxneie() {
327 // We cannot check the RXNE flag as it is auto-cleared by the DMA controller
328
329 // It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection
330
331 wake = true;
332 }
333 }
334
335 if wake {
336 compiler_fence(Ordering::SeqCst);
337
338 s.rx_waker.wake();
339 }
340 }
341
342 #[cfg(any(usart_v1, usart_v2))] 347 #[cfg(any(usart_v1, usart_v2))]
343 unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> { 348 unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> {
344 let r = T::regs(); 349 let r = T::regs();
@@ -643,7 +648,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
643 peri: impl Peripheral<P = T> + 'd, 648 peri: impl Peripheral<P = T> + 'd,
644 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 649 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
645 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 650 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
646 irq: impl Peripheral<P = T::Interrupt> + 'd, 651 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
647 tx_dma: impl Peripheral<P = TxDma> + 'd, 652 tx_dma: impl Peripheral<P = TxDma> + 'd,
648 rx_dma: impl Peripheral<P = RxDma> + 'd, 653 rx_dma: impl Peripheral<P = RxDma> + 'd,
649 config: Config, 654 config: Config,
@@ -651,14 +656,14 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
651 T::enable(); 656 T::enable();
652 T::reset(); 657 T::reset();
653 658
654 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config) 659 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
655 } 660 }
656 661
657 pub fn new_with_rtscts( 662 pub fn new_with_rtscts(
658 peri: impl Peripheral<P = T> + 'd, 663 peri: impl Peripheral<P = T> + 'd,
659 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 664 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
660 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 665 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
661 irq: impl Peripheral<P = T::Interrupt> + 'd, 666 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
662 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 667 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
663 cts: impl Peripheral<P = impl CtsPin<T>> + 'd, 668 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
664 tx_dma: impl Peripheral<P = TxDma> + 'd, 669 tx_dma: impl Peripheral<P = TxDma> + 'd,
@@ -678,7 +683,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
678 w.set_ctse(true); 683 w.set_ctse(true);
679 }); 684 });
680 } 685 }
681 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config) 686 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
682 } 687 }
683 688
684 #[cfg(not(any(usart_v1, usart_v2)))] 689 #[cfg(not(any(usart_v1, usart_v2)))]
@@ -686,7 +691,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
686 peri: impl Peripheral<P = T> + 'd, 691 peri: impl Peripheral<P = T> + 'd,
687 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 692 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
688 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 693 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
689 irq: impl Peripheral<P = T::Interrupt> + 'd, 694 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
690 de: impl Peripheral<P = impl DePin<T>> + 'd, 695 de: impl Peripheral<P = impl DePin<T>> + 'd,
691 tx_dma: impl Peripheral<P = TxDma> + 'd, 696 tx_dma: impl Peripheral<P = TxDma> + 'd,
692 rx_dma: impl Peripheral<P = RxDma> + 'd, 697 rx_dma: impl Peripheral<P = RxDma> + 'd,
@@ -703,19 +708,18 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
703 w.set_dem(true); 708 w.set_dem(true);
704 }); 709 });
705 } 710 }
706 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config) 711 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
707 } 712 }
708 713
709 fn new_inner( 714 fn new_inner(
710 peri: impl Peripheral<P = T> + 'd, 715 peri: impl Peripheral<P = T> + 'd,
711 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 716 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
712 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 717 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
713 irq: impl Peripheral<P = T::Interrupt> + 'd,
714 tx_dma: impl Peripheral<P = TxDma> + 'd, 718 tx_dma: impl Peripheral<P = TxDma> + 'd,
715 rx_dma: impl Peripheral<P = RxDma> + 'd, 719 rx_dma: impl Peripheral<P = RxDma> + 'd,
716 config: Config, 720 config: Config,
717 ) -> Self { 721 ) -> Self {
718 into_ref!(peri, rx, tx, irq, tx_dma, rx_dma); 722 into_ref!(peri, rx, tx, tx_dma, rx_dma);
719 723
720 let r = T::regs(); 724 let r = T::regs();
721 725
@@ -726,9 +730,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
726 730
727 configure(r, &config, T::frequency(), T::KIND, true, true); 731 configure(r, &config, T::frequency(), T::KIND, true, true);
728 732
729 irq.set_handler(UartRx::<T, RxDma>::on_interrupt); 733 unsafe { T::Interrupt::steal() }.unpend();
730 irq.unpend(); 734 unsafe { T::Interrupt::steal() }.enable();
731 irq.enable();
732 735
733 // create state once! 736 // create state once!
734 let _s = T::state(); 737 let _s = T::state();
@@ -1068,6 +1071,9 @@ mod eio {
1068 1071
1069#[cfg(feature = "nightly")] 1072#[cfg(feature = "nightly")]
1070pub use buffered::*; 1073pub use buffered::*;
1074
1075#[cfg(feature = "nightly")]
1076pub use crate::usart::buffered::InterruptHandler as BufferedInterruptHandler;
1071#[cfg(feature = "nightly")] 1077#[cfg(feature = "nightly")]
1072mod buffered; 1078mod buffered;
1073 1079
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 56c46476c..a9ff284ae 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -14,12 +14,99 @@ use embassy_usb_driver::{
14 14
15use super::{DmPin, DpPin, Instance}; 15use super::{DmPin, DpPin, Instance};
16use crate::gpio::sealed::AFType; 16use crate::gpio::sealed::AFType;
17use crate::interrupt::InterruptExt; 17use crate::interrupt::{Interrupt, InterruptExt};
18use crate::pac::usb::regs; 18use crate::pac::usb::regs;
19use crate::pac::usb::vals::{EpType, Stat}; 19use crate::pac::usb::vals::{EpType, Stat};
20use crate::pac::USBRAM; 20use crate::pac::USBRAM;
21use crate::rcc::sealed::RccPeripheral; 21use crate::rcc::sealed::RccPeripheral;
22use crate::Peripheral; 22use crate::{interrupt, Peripheral};
23
24/// Interrupt handler.
25pub struct InterruptHandler<T: Instance> {
26 _phantom: PhantomData<T>,
27}
28
29impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
30 unsafe fn on_interrupt() {
31 unsafe {
32 let regs = T::regs();
33 //let x = regs.istr().read().0;
34 //trace!("USB IRQ: {:08x}", x);
35
36 let istr = regs.istr().read();
37
38 if istr.susp() {
39 //trace!("USB IRQ: susp");
40 IRQ_SUSPEND.store(true, Ordering::Relaxed);
41 regs.cntr().modify(|w| {
42 w.set_fsusp(true);
43 w.set_lpmode(true);
44 });
45
46 // Write 0 to clear.
47 let mut clear = regs::Istr(!0);
48 clear.set_susp(false);
49 regs.istr().write_value(clear);
50
51 // Wake main thread.
52 BUS_WAKER.wake();
53 }
54
55 if istr.wkup() {
56 //trace!("USB IRQ: wkup");
57 IRQ_RESUME.store(true, Ordering::Relaxed);
58 regs.cntr().modify(|w| {
59 w.set_fsusp(false);
60 w.set_lpmode(false);
61 });
62
63 // Write 0 to clear.
64 let mut clear = regs::Istr(!0);
65 clear.set_wkup(false);
66 regs.istr().write_value(clear);
67
68 // Wake main thread.
69 BUS_WAKER.wake();
70 }
71
72 if istr.reset() {
73 //trace!("USB IRQ: reset");
74 IRQ_RESET.store(true, Ordering::Relaxed);
75
76 // Write 0 to clear.
77 let mut clear = regs::Istr(!0);
78 clear.set_reset(false);
79 regs.istr().write_value(clear);
80
81 // Wake main thread.
82 BUS_WAKER.wake();
83 }
84
85 if istr.ctr() {
86 let index = istr.ep_id() as usize;
87 let mut epr = regs.epr(index).read();
88 if epr.ctr_rx() {
89 if index == 0 && epr.setup() {
90 EP0_SETUP.store(true, Ordering::Relaxed);
91 }
92 //trace!("EP {} RX, setup={}", index, epr.setup());
93 EP_OUT_WAKERS[index].wake();
94 }
95 if epr.ctr_tx() {
96 //trace!("EP {} TX", index);
97 EP_IN_WAKERS[index].wake();
98 }
99 epr.set_dtog_rx(false);
100 epr.set_dtog_tx(false);
101 epr.set_stat_rx(Stat(0));
102 epr.set_stat_tx(Stat(0));
103 epr.set_ctr_rx(!epr.ctr_rx());
104 epr.set_ctr_tx(!epr.ctr_tx());
105 regs.epr(index).write_value(epr);
106 }
107 }
108 }
109}
23 110
24const EP_COUNT: usize = 8; 111const EP_COUNT: usize = 8;
25 112
@@ -168,14 +255,13 @@ pub struct Driver<'d, T: Instance> {
168impl<'d, T: Instance> Driver<'d, T> { 255impl<'d, T: Instance> Driver<'d, T> {
169 pub fn new( 256 pub fn new(
170 _usb: impl Peripheral<P = T> + 'd, 257 _usb: impl Peripheral<P = T> + 'd,
171 irq: impl Peripheral<P = T::Interrupt> + 'd, 258 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
172 dp: impl Peripheral<P = impl DpPin<T>> + 'd, 259 dp: impl Peripheral<P = impl DpPin<T>> + 'd,
173 dm: impl Peripheral<P = impl DmPin<T>> + 'd, 260 dm: impl Peripheral<P = impl DmPin<T>> + 'd,
174 ) -> Self { 261 ) -> Self {
175 into_ref!(irq, dp, dm); 262 into_ref!(dp, dm);
176 irq.set_handler(Self::on_interrupt); 263 unsafe { T::Interrupt::steal() }.unpend();
177 irq.unpend(); 264 unsafe { T::Interrupt::steal() }.enable();
178 irq.enable();
179 265
180 let regs = T::regs(); 266 let regs = T::regs();
181 267
@@ -225,86 +311,6 @@ impl<'d, T: Instance> Driver<'d, T> {
225 } 311 }
226 } 312 }
227 313
228 fn on_interrupt(_: *mut ()) {
229 unsafe {
230 let regs = T::regs();
231 //let x = regs.istr().read().0;
232 //trace!("USB IRQ: {:08x}", x);
233
234 let istr = regs.istr().read();
235
236 if istr.susp() {
237 //trace!("USB IRQ: susp");
238 IRQ_SUSPEND.store(true, Ordering::Relaxed);
239 regs.cntr().modify(|w| {
240 w.set_fsusp(true);
241 w.set_lpmode(true);
242 });
243
244 // Write 0 to clear.
245 let mut clear = regs::Istr(!0);
246 clear.set_susp(false);
247 regs.istr().write_value(clear);
248
249 // Wake main thread.
250 BUS_WAKER.wake();
251 }
252
253 if istr.wkup() {
254 //trace!("USB IRQ: wkup");
255 IRQ_RESUME.store(true, Ordering::Relaxed);
256 regs.cntr().modify(|w| {
257 w.set_fsusp(false);
258 w.set_lpmode(false);
259 });
260
261 // Write 0 to clear.
262 let mut clear = regs::Istr(!0);
263 clear.set_wkup(false);
264 regs.istr().write_value(clear);
265
266 // Wake main thread.
267 BUS_WAKER.wake();
268 }
269
270 if istr.reset() {
271 //trace!("USB IRQ: reset");
272 IRQ_RESET.store(true, Ordering::Relaxed);
273
274 // Write 0 to clear.
275 let mut clear = regs::Istr(!0);
276 clear.set_reset(false);
277 regs.istr().write_value(clear);
278
279 // Wake main thread.
280 BUS_WAKER.wake();
281 }
282
283 if istr.ctr() {
284 let index = istr.ep_id() as usize;
285 let mut epr = regs.epr(index).read();
286 if epr.ctr_rx() {
287 if index == 0 && epr.setup() {
288 EP0_SETUP.store(true, Ordering::Relaxed);
289 }
290 //trace!("EP {} RX, setup={}", index, epr.setup());
291 EP_OUT_WAKERS[index].wake();
292 }
293 if epr.ctr_tx() {
294 //trace!("EP {} TX", index);
295 EP_IN_WAKERS[index].wake();
296 }
297 epr.set_dtog_rx(false);
298 epr.set_dtog_tx(false);
299 epr.set_stat_rx(Stat(0));
300 epr.set_stat_tx(Stat(0));
301 epr.set_ctr_rx(!epr.ctr_rx());
302 epr.set_ctr_tx(!epr.ctr_tx());
303 regs.epr(index).write_value(epr);
304 }
305 }
306 }
307
308 fn alloc_ep_mem(&mut self, len: u16) -> u16 { 314 fn alloc_ep_mem(&mut self, len: u16) -> u16 {
309 assert!(len as usize % USBRAM_ALIGN == 0); 315 assert!(len as usize % USBRAM_ALIGN == 0);
310 let addr = self.ep_mem_free; 316 let addr = self.ep_mem_free;
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index 96c574ca8..921a73c8b 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -4,7 +4,7 @@ use core::task::Poll;
4 4
5use atomic_polyfill::{AtomicBool, AtomicU16, Ordering}; 5use atomic_polyfill::{AtomicBool, AtomicU16, Ordering};
6use embassy_cortex_m::interrupt::InterruptExt; 6use embassy_cortex_m::interrupt::InterruptExt;
7use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 7use embassy_hal_common::{into_ref, Peripheral};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use embassy_usb_driver::{ 9use embassy_usb_driver::{
10 self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut, 10 self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut,
@@ -14,10 +14,161 @@ use futures::future::poll_fn;
14 14
15use super::*; 15use super::*;
16use crate::gpio::sealed::AFType; 16use crate::gpio::sealed::AFType;
17use crate::interrupt;
17use crate::pac::otg::{regs, vals}; 18use crate::pac::otg::{regs, vals};
18use crate::rcc::sealed::RccPeripheral; 19use crate::rcc::sealed::RccPeripheral;
19use crate::time::Hertz; 20use crate::time::Hertz;
20 21
22/// Interrupt handler.
23pub struct InterruptHandler<T: Instance> {
24 _phantom: PhantomData<T>,
25}
26
27impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
28 unsafe fn on_interrupt() {
29 trace!("irq");
30 let r = T::regs();
31 let state = T::state();
32
33 // SAFETY: atomic read/write
34 let ints = unsafe { r.gintsts().read() };
35 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() {
36 // Mask interrupts and notify `Bus` to process them
37 unsafe { r.gintmsk().write(|_| {}) };
38 T::state().bus_waker.wake();
39 }
40
41 // Handle RX
42 // SAFETY: atomic read with no side effects
43 while unsafe { r.gintsts().read().rxflvl() } {
44 // SAFETY: atomic "pop" register
45 let status = unsafe { r.grxstsp().read() };
46 let ep_num = status.epnum() as usize;
47 let len = status.bcnt() as usize;
48
49 assert!(ep_num < T::ENDPOINT_COUNT);
50
51 match status.pktstsd() {
52 vals::Pktstsd::SETUP_DATA_RX => {
53 trace!("SETUP_DATA_RX");
54 assert!(len == 8, "invalid SETUP packet length={}", len);
55 assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
56
57 if state.ep0_setup_ready.load(Ordering::Relaxed) == false {
58 // SAFETY: exclusive access ensured by atomic bool
59 let data = unsafe { &mut *state.ep0_setup_data.get() };
60 // SAFETY: FIFO reads are exclusive to this IRQ
61 unsafe {
62 data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
63 data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
64 }
65 state.ep0_setup_ready.store(true, Ordering::Release);
66 state.ep_out_wakers[0].wake();
67 } else {
68 error!("received SETUP before previous finished processing");
69 // discard FIFO
70 // SAFETY: FIFO reads are exclusive to IRQ
71 unsafe {
72 r.fifo(0).read();
73 r.fifo(0).read();
74 }
75 }
76 }
77 vals::Pktstsd::OUT_DATA_RX => {
78 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
79
80 if state.ep_out_size[ep_num].load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY {
81 // SAFETY: Buffer size is allocated to be equal to endpoint's maximum packet size
82 // We trust the peripheral to not exceed its configured MPSIZ
83 let buf = unsafe { core::slice::from_raw_parts_mut(*state.ep_out_buffers[ep_num].get(), len) };
84
85 for chunk in buf.chunks_mut(4) {
86 // RX FIFO is shared so always read from fifo(0)
87 // SAFETY: FIFO reads are exclusive to IRQ
88 let data = unsafe { r.fifo(0).read().0 };
89 chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]);
90 }
91
92 state.ep_out_size[ep_num].store(len as u16, Ordering::Release);
93 state.ep_out_wakers[ep_num].wake();
94 } else {
95 error!("ep_out buffer overflow index={}", ep_num);
96
97 // discard FIFO data
98 let len_words = (len + 3) / 4;
99 for _ in 0..len_words {
100 // SAFETY: FIFO reads are exclusive to IRQ
101 unsafe { r.fifo(0).read().data() };
102 }
103 }
104 }
105 vals::Pktstsd::OUT_DATA_DONE => {
106 trace!("OUT_DATA_DONE ep={}", ep_num);
107 }
108 vals::Pktstsd::SETUP_DATA_DONE => {
109 trace!("SETUP_DATA_DONE ep={}", ep_num);
110 }
111 x => trace!("unknown PKTSTS: {}", x.0),
112 }
113 }
114
115 // IN endpoint interrupt
116 if ints.iepint() {
117 // SAFETY: atomic read with no side effects
118 let mut ep_mask = unsafe { r.daint().read().iepint() };
119 let mut ep_num = 0;
120
121 // Iterate over endpoints while there are non-zero bits in the mask
122 while ep_mask != 0 {
123 if ep_mask & 1 != 0 {
124 // SAFETY: atomic read with no side effects
125 let ep_ints = unsafe { r.diepint(ep_num).read() };
126
127 // clear all
128 // SAFETY: DIEPINT is exclusive to IRQ
129 unsafe { r.diepint(ep_num).write_value(ep_ints) };
130
131 // TXFE is cleared in DIEPEMPMSK
132 if ep_ints.txfe() {
133 // SAFETY: DIEPEMPMSK is shared with `Endpoint` so critical section is needed for RMW
134 critical_section::with(|_| unsafe {
135 r.diepempmsk().modify(|w| {
136 w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num));
137 });
138 });
139 }
140
141 state.ep_in_wakers[ep_num].wake();
142 trace!("in ep={} irq val={:b}", ep_num, ep_ints.0);
143 }
144
145 ep_mask >>= 1;
146 ep_num += 1;
147 }
148 }
149
150 // not needed? reception handled in rxflvl
151 // OUT endpoint interrupt
152 // if ints.oepint() {
153 // let mut ep_mask = r.daint().read().oepint();
154 // let mut ep_num = 0;
155
156 // while ep_mask != 0 {
157 // if ep_mask & 1 != 0 {
158 // let ep_ints = r.doepint(ep_num).read();
159 // // clear all
160 // r.doepint(ep_num).write_value(ep_ints);
161 // state.ep_out_wakers[ep_num].wake();
162 // trace!("out ep={} irq val={=u32:b}", ep_num, ep_ints.0);
163 // }
164
165 // ep_mask >>= 1;
166 // ep_num += 1;
167 // }
168 // }
169 }
170}
171
21macro_rules! config_ulpi_pins { 172macro_rules! config_ulpi_pins {
22 ($($pin:ident),*) => { 173 ($($pin:ident),*) => {
23 into_ref!($($pin),*); 174 into_ref!($($pin),*);
@@ -123,7 +274,6 @@ struct EndpointData {
123 274
124pub struct Driver<'d, T: Instance> { 275pub struct Driver<'d, T: Instance> {
125 phantom: PhantomData<&'d mut T>, 276 phantom: PhantomData<&'d mut T>,
126 irq: PeripheralRef<'d, T::Interrupt>,
127 ep_in: [Option<EndpointData>; MAX_EP_COUNT], 277 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
128 ep_out: [Option<EndpointData>; MAX_EP_COUNT], 278 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
129 ep_out_buffer: &'d mut [u8], 279 ep_out_buffer: &'d mut [u8],
@@ -141,12 +291,12 @@ impl<'d, T: Instance> Driver<'d, T> {
141 /// Endpoint allocation will fail if it is too small. 291 /// Endpoint allocation will fail if it is too small.
142 pub fn new_fs( 292 pub fn new_fs(
143 _peri: impl Peripheral<P = T> + 'd, 293 _peri: impl Peripheral<P = T> + 'd,
144 irq: impl Peripheral<P = T::Interrupt> + 'd, 294 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
145 dp: impl Peripheral<P = impl DpPin<T>> + 'd, 295 dp: impl Peripheral<P = impl DpPin<T>> + 'd,
146 dm: impl Peripheral<P = impl DmPin<T>> + 'd, 296 dm: impl Peripheral<P = impl DmPin<T>> + 'd,
147 ep_out_buffer: &'d mut [u8], 297 ep_out_buffer: &'d mut [u8],
148 ) -> Self { 298 ) -> Self {
149 into_ref!(dp, dm, irq); 299 into_ref!(dp, dm);
150 300
151 unsafe { 301 unsafe {
152 dp.set_as_af(dp.af_num(), AFType::OutputPushPull); 302 dp.set_as_af(dp.af_num(), AFType::OutputPushPull);
@@ -155,7 +305,6 @@ impl<'d, T: Instance> Driver<'d, T> {
155 305
156 Self { 306 Self {
157 phantom: PhantomData, 307 phantom: PhantomData,
158 irq,
159 ep_in: [None; MAX_EP_COUNT], 308 ep_in: [None; MAX_EP_COUNT],
160 ep_out: [None; MAX_EP_COUNT], 309 ep_out: [None; MAX_EP_COUNT],
161 ep_out_buffer, 310 ep_out_buffer,
@@ -173,7 +322,7 @@ impl<'d, T: Instance> Driver<'d, T> {
173 /// Endpoint allocation will fail if it is too small. 322 /// Endpoint allocation will fail if it is too small.
174 pub fn new_hs_ulpi( 323 pub fn new_hs_ulpi(
175 _peri: impl Peripheral<P = T> + 'd, 324 _peri: impl Peripheral<P = T> + 'd,
176 irq: impl Peripheral<P = T::Interrupt> + 'd, 325 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
177 ulpi_clk: impl Peripheral<P = impl UlpiClkPin<T>> + 'd, 326 ulpi_clk: impl Peripheral<P = impl UlpiClkPin<T>> + 'd,
178 ulpi_dir: impl Peripheral<P = impl UlpiDirPin<T>> + 'd, 327 ulpi_dir: impl Peripheral<P = impl UlpiDirPin<T>> + 'd,
179 ulpi_nxt: impl Peripheral<P = impl UlpiNxtPin<T>> + 'd, 328 ulpi_nxt: impl Peripheral<P = impl UlpiNxtPin<T>> + 'd,
@@ -195,11 +344,8 @@ impl<'d, T: Instance> Driver<'d, T> {
195 ulpi_d7 344 ulpi_d7
196 ); 345 );
197 346
198 into_ref!(irq);
199
200 Self { 347 Self {
201 phantom: PhantomData, 348 phantom: PhantomData,
202 irq,
203 ep_in: [None; MAX_EP_COUNT], 349 ep_in: [None; MAX_EP_COUNT],
204 ep_out: [None; MAX_EP_COUNT], 350 ep_out: [None; MAX_EP_COUNT],
205 ep_out_buffer, 351 ep_out_buffer,
@@ -337,7 +483,6 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
337 ( 483 (
338 Bus { 484 Bus {
339 phantom: PhantomData, 485 phantom: PhantomData,
340 irq: self.irq,
341 ep_in: self.ep_in, 486 ep_in: self.ep_in,
342 ep_out: self.ep_out, 487 ep_out: self.ep_out,
343 phy_type: self.phy_type, 488 phy_type: self.phy_type,
@@ -355,7 +500,6 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
355 500
356pub struct Bus<'d, T: Instance> { 501pub struct Bus<'d, T: Instance> {
357 phantom: PhantomData<&'d mut T>, 502 phantom: PhantomData<&'d mut T>,
358 irq: PeripheralRef<'d, T::Interrupt>,
359 ep_in: [Option<EndpointData>; MAX_EP_COUNT], 503 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
360 ep_out: [Option<EndpointData>; MAX_EP_COUNT], 504 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
361 phy_type: PhyType, 505 phy_type: PhyType,
@@ -485,8 +629,7 @@ impl<'d, T: Instance> Bus<'d, T> {
485 } 629 }
486 630
487 fn disable(&mut self) { 631 fn disable(&mut self) {
488 self.irq.disable(); 632 unsafe { T::Interrupt::steal() }.disable();
489 self.irq.remove_handler();
490 633
491 <T as RccPeripheral>::disable(); 634 <T as RccPeripheral>::disable();
492 635
@@ -496,149 +639,6 @@ impl<'d, T: Instance> Bus<'d, T> {
496 // Cannot disable PWR, because other peripherals might be using it 639 // Cannot disable PWR, because other peripherals might be using it
497 } 640 }
498 } 641 }
499
500 fn on_interrupt(_: *mut ()) {
501 trace!("irq");
502 let r = T::regs();
503 let state = T::state();
504
505 // SAFETY: atomic read/write
506 let ints = unsafe { r.gintsts().read() };
507 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() {
508 // Mask interrupts and notify `Bus` to process them
509 unsafe { r.gintmsk().write(|_| {}) };
510 T::state().bus_waker.wake();
511 }
512
513 // Handle RX
514 // SAFETY: atomic read with no side effects
515 while unsafe { r.gintsts().read().rxflvl() } {
516 // SAFETY: atomic "pop" register
517 let status = unsafe { r.grxstsp().read() };
518 let ep_num = status.epnum() as usize;
519 let len = status.bcnt() as usize;
520
521 assert!(ep_num < T::ENDPOINT_COUNT);
522
523 match status.pktstsd() {
524 vals::Pktstsd::SETUP_DATA_RX => {
525 trace!("SETUP_DATA_RX");
526 assert!(len == 8, "invalid SETUP packet length={}", len);
527 assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
528
529 if state.ep0_setup_ready.load(Ordering::Relaxed) == false {
530 // SAFETY: exclusive access ensured by atomic bool
531 let data = unsafe { &mut *state.ep0_setup_data.get() };
532 // SAFETY: FIFO reads are exclusive to this IRQ
533 unsafe {
534 data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
535 data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
536 }
537 state.ep0_setup_ready.store(true, Ordering::Release);
538 state.ep_out_wakers[0].wake();
539 } else {
540 error!("received SETUP before previous finished processing");
541 // discard FIFO
542 // SAFETY: FIFO reads are exclusive to IRQ
543 unsafe {
544 r.fifo(0).read();
545 r.fifo(0).read();
546 }
547 }
548 }
549 vals::Pktstsd::OUT_DATA_RX => {
550 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
551
552 if state.ep_out_size[ep_num].load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY {
553 // SAFETY: Buffer size is allocated to be equal to endpoint's maximum packet size
554 // We trust the peripheral to not exceed its configured MPSIZ
555 let buf = unsafe { core::slice::from_raw_parts_mut(*state.ep_out_buffers[ep_num].get(), len) };
556
557 for chunk in buf.chunks_mut(4) {
558 // RX FIFO is shared so always read from fifo(0)
559 // SAFETY: FIFO reads are exclusive to IRQ
560 let data = unsafe { r.fifo(0).read().0 };
561 chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]);
562 }
563
564 state.ep_out_size[ep_num].store(len as u16, Ordering::Release);
565 state.ep_out_wakers[ep_num].wake();
566 } else {
567 error!("ep_out buffer overflow index={}", ep_num);
568
569 // discard FIFO data
570 let len_words = (len + 3) / 4;
571 for _ in 0..len_words {
572 // SAFETY: FIFO reads are exclusive to IRQ
573 unsafe { r.fifo(0).read().data() };
574 }
575 }
576 }
577 vals::Pktstsd::OUT_DATA_DONE => {
578 trace!("OUT_DATA_DONE ep={}", ep_num);
579 }
580 vals::Pktstsd::SETUP_DATA_DONE => {
581 trace!("SETUP_DATA_DONE ep={}", ep_num);
582 }
583 x => trace!("unknown PKTSTS: {}", x.0),
584 }
585 }
586
587 // IN endpoint interrupt
588 if ints.iepint() {
589 // SAFETY: atomic read with no side effects
590 let mut ep_mask = unsafe { r.daint().read().iepint() };
591 let mut ep_num = 0;
592
593 // Iterate over endpoints while there are non-zero bits in the mask
594 while ep_mask != 0 {
595 if ep_mask & 1 != 0 {
596 // SAFETY: atomic read with no side effects
597 let ep_ints = unsafe { r.diepint(ep_num).read() };
598
599 // clear all
600 // SAFETY: DIEPINT is exclusive to IRQ
601 unsafe { r.diepint(ep_num).write_value(ep_ints) };
602
603 // TXFE is cleared in DIEPEMPMSK
604 if ep_ints.txfe() {
605 // SAFETY: DIEPEMPMSK is shared with `Endpoint` so critical section is needed for RMW
606 critical_section::with(|_| unsafe {
607 r.diepempmsk().modify(|w| {
608 w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num));
609 });
610 });
611 }
612
613 state.ep_in_wakers[ep_num].wake();
614 trace!("in ep={} irq val={:b}", ep_num, ep_ints.0);
615 }
616
617 ep_mask >>= 1;
618 ep_num += 1;
619 }
620 }
621
622 // not needed? reception handled in rxflvl
623 // OUT endpoint interrupt
624 // if ints.oepint() {
625 // let mut ep_mask = r.daint().read().oepint();
626 // let mut ep_num = 0;
627
628 // while ep_mask != 0 {
629 // if ep_mask & 1 != 0 {
630 // let ep_ints = r.doepint(ep_num).read();
631 // // clear all
632 // r.doepint(ep_num).write_value(ep_ints);
633 // state.ep_out_wakers[ep_num].wake();
634 // trace!("out ep={} irq val={=u32:b}", ep_num, ep_ints.0);
635 // }
636
637 // ep_mask >>= 1;
638 // ep_num += 1;
639 // }
640 // }
641 }
642} 642}
643 643
644impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { 644impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
@@ -902,9 +902,8 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
902 <T as RccPeripheral>::enable(); 902 <T as RccPeripheral>::enable();
903 <T as RccPeripheral>::reset(); 903 <T as RccPeripheral>::reset();
904 904
905 self.irq.set_handler(Self::on_interrupt); 905 T::Interrupt::steal().unpend();
906 self.irq.unpend(); 906 T::Interrupt::steal().enable();
907 self.irq.enable();
908 907
909 let r = T::regs(); 908 let r = T::regs();
910 let core_id = r.cid().read().0; 909 let core_id = r.cid().read().0;
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index 92b9a5ca8..18ebf97d8 100644
--- a/embassy-stm32/src/wdg/mod.rs
+++ b/embassy-stm32/src/wdg/mod.rs
@@ -13,13 +13,13 @@ pub struct IndependentWatchdog<'d, T: Instance> {
13const MAX_RL: u16 = 0xFFF; 13const MAX_RL: u16 = 0xFFF;
14 14
15/// Calculates maximum watchdog timeout in us (RL = 0xFFF) for a given prescaler 15/// Calculates maximum watchdog timeout in us (RL = 0xFFF) for a given prescaler
16const fn max_timeout(prescaler: u16) -> u32 { 16const fn get_timeout_us(prescaler: u16, reload_value: u16) -> u32 {
17 1_000_000 * MAX_RL as u32 / (LSI_FREQ.0 / prescaler as u32) 17 1_000_000 * (reload_value + 1) as u32 / (LSI_FREQ.0 / prescaler as u32)
18} 18}
19 19
20/// Calculates watchdog reload value for the given prescaler and desired timeout 20/// Calculates watchdog reload value for the given prescaler and desired timeout
21const fn reload_value(prescaler: u16, timeout_us: u32) -> u16 { 21const fn reload_value(prescaler: u16, timeout_us: u32) -> u16 {
22 (timeout_us / prescaler as u32 * LSI_FREQ.0 / 1_000_000) as u16 22 (timeout_us / prescaler as u32 * LSI_FREQ.0 / 1_000_000) as u16 - 1
23} 23}
24 24
25impl<'d, T: Instance> IndependentWatchdog<'d, T> { 25impl<'d, T: Instance> IndependentWatchdog<'d, T> {
@@ -34,7 +34,7 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
34 // This iterates from 4 (2^2) to 256 (2^8). 34 // This iterates from 4 (2^2) to 256 (2^8).
35 let psc_power = unwrap!((2..=8).find(|psc_power| { 35 let psc_power = unwrap!((2..=8).find(|psc_power| {
36 let psc = 2u16.pow(*psc_power); 36 let psc = 2u16.pow(*psc_power);
37 timeout_us <= max_timeout(psc) 37 timeout_us <= get_timeout_us(psc, MAX_RL)
38 })); 38 }));
39 39
40 // Prescaler value 40 // Prescaler value
@@ -54,6 +54,14 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
54 wdg.rlr().write(|w| w.set_rl(rl)); 54 wdg.rlr().write(|w| w.set_rl(rl));
55 } 55 }
56 56
57 trace!(
58 "Watchdog configured with {}us timeout, desired was {}us (PR={}, RL={})",
59 get_timeout_us(psc, rl),
60 timeout_us,
61 pr,
62 rl
63 );
64
57 IndependentWatchdog { 65 IndependentWatchdog {
58 wdg: PhantomData::default(), 66 wdg: PhantomData::default(),
59 } 67 }
@@ -87,3 +95,27 @@ foreach_peripheral!(
87 impl Instance for crate::peripherals::$inst {} 95 impl Instance for crate::peripherals::$inst {}
88 }; 96 };
89); 97);
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn can_compute_timeout_us() {
105 assert_eq!(125, get_timeout_us(4, 0));
106 assert_eq!(512_000, get_timeout_us(4, MAX_RL));
107
108 assert_eq!(8_000, get_timeout_us(256, 0));
109 assert_eq!(32768_000, get_timeout_us(256, MAX_RL));
110
111 assert_eq!(8000_000, get_timeout_us(64, 3999));
112 }
113
114 #[test]
115 fn can_compute_reload_value() {
116 assert_eq!(0xFFF, reload_value(4, 512_000));
117 assert_eq!(0xFFF, reload_value(256, 32768_000));
118
119 assert_eq!(3999, reload_value(64, 8000_000));
120 }
121}
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs
index 07cad84ef..663099ff7 100644
--- a/examples/stm32f1/src/bin/usb_serial.rs
+++ b/examples/stm32f1/src/bin/usb_serial.rs
@@ -8,13 +8,17 @@ use embassy_futures::join::join;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
10use embassy_stm32::usb::{Driver, Instance}; 10use embassy_stm32::usb::{Driver, Instance};
11use embassy_stm32::{interrupt, Config}; 11use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
12use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
13use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
14use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
15use embassy_usb::Builder; 15use embassy_usb::Builder;
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18bind_interrupts!(struct Irqs {
19 USB_LP_CAN1_RX0 => usb::InterruptHandler<peripherals::USB>;
20});
21
18#[embassy_executor::main] 22#[embassy_executor::main]
19async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
20 let mut config = Config::default(); 24 let mut config = Config::default();
@@ -35,8 +39,7 @@ async fn main(_spawner: Spawner) {
35 } 39 }
36 40
37 // Create the driver, from the HAL. 41 // Create the driver, from the HAL.
38 let irq = interrupt::take!(USB_LP_CAN1_RX0); 42 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
39 let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
40 43
41 // Create embassy-usb Config 44 // Create embassy-usb Config
42 let config = embassy_usb::Config::new(0xc0de, 0xcafe); 45 let config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32f3/src/bin/usart_dma.rs b/examples/stm32f3/src/bin/usart_dma.rs
index 47121acf1..85f01a69e 100644
--- a/examples/stm32f3/src/bin/usart_dma.rs
+++ b/examples/stm32f3/src/bin/usart_dma.rs
@@ -7,19 +7,22 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
11use embassy_stm32::{bind_interrupts, peripherals, usart};
12use heapless::String; 12use heapless::String;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs {
16 USART1 => usart::InterruptHandler<peripherals::USART1>;
17});
18
15#[embassy_executor::main] 19#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 20async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 21 let p = embassy_stm32::init(Default::default());
18 info!("Hello World!"); 22 info!("Hello World!");
19 23
20 let config = Config::default(); 24 let config = Config::default();
21 let irq = interrupt::take!(USART1); 25 let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, Irqs, p.DMA1_CH4, NoDma, config);
22 let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, irq, p.DMA1_CH4, NoDma, config);
23 26
24 for n in 0u32.. { 27 for n in 0u32.. {
25 let mut s: String<128> = String::new(); 28 let mut s: String<128> = String::new();
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs
index 5b4e0a91a..f15f333b7 100644
--- a/examples/stm32f3/src/bin/usb_serial.rs
+++ b/examples/stm32f3/src/bin/usb_serial.rs
@@ -8,13 +8,17 @@ use embassy_futures::join::join;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::time::mhz; 9use embassy_stm32::time::mhz;
10use embassy_stm32::usb::{Driver, Instance}; 10use embassy_stm32::usb::{Driver, Instance};
11use embassy_stm32::{interrupt, Config}; 11use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
12use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
13use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
14use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
15use embassy_usb::Builder; 15use embassy_usb::Builder;
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18bind_interrupts!(struct Irqs {
19 USB_LP_CAN_RX0 => usb::InterruptHandler<peripherals::USB>;
20});
21
18#[embassy_executor::main] 22#[embassy_executor::main]
19async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
20 let mut config = Config::default(); 24 let mut config = Config::default();
@@ -33,8 +37,7 @@ async fn main(_spawner: Spawner) {
33 dp_pullup.set_high(); 37 dp_pullup.set_high();
34 38
35 // Create the driver, from the HAL. 39 // Create the driver, from the HAL.
36 let irq = interrupt::take!(USB_LP_CAN_RX0); 40 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
37 let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
38 41
39 // Create embassy-usb Config 42 // Create embassy-usb Config
40 let config = embassy_usb::Config::new(0xc0de, 0xcafe); 43 let config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs
index f8ae0890c..a92957325 100644
--- a/examples/stm32f4/src/bin/i2c.rs
+++ b/examples/stm32f4/src/bin/i2c.rs
@@ -6,25 +6,28 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; 8use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
9use embassy_stm32::interrupt;
10use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, i2c, peripherals};
11use embassy_time::Duration; 11use embassy_time::Duration;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14const ADDRESS: u8 = 0x5F; 14const ADDRESS: u8 = 0x5F;
15const WHOAMI: u8 = 0x0F; 15const WHOAMI: u8 = 0x0F;
16 16
17bind_interrupts!(struct Irqs {
18 I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
19});
20
17#[embassy_executor::main] 21#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
19 info!("Hello world!"); 23 info!("Hello world!");
20 let p = embassy_stm32::init(Default::default()); 24 let p = embassy_stm32::init(Default::default());
21 25
22 let irq = interrupt::take!(I2C2_EV);
23 let mut i2c = I2c::new( 26 let mut i2c = I2c::new(
24 p.I2C2, 27 p.I2C2,
25 p.PB10, 28 p.PB10,
26 p.PB11, 29 p.PB11,
27 irq, 30 Irqs,
28 NoDma, 31 NoDma,
29 NoDma, 32 NoDma,
30 Hertz(100_000), 33 Hertz(100_000),
diff --git a/examples/stm32f4/src/bin/i2s_dma.rs b/examples/stm32f4/src/bin/i2s_dma.rs
new file mode 100644
index 000000000..e8d7b5f77
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2s_dma.rs
@@ -0,0 +1,36 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use core::fmt::Write;
6
7use defmt::*;
8use embassy_executor::Spawner;
9use embassy_stm32::i2s::{Config, I2S};
10use embassy_stm32::time::Hertz;
11use heapless::String;
12use {defmt_rtt as _, panic_probe as _};
13
14#[embassy_executor::main]
15async fn main(_spawner: Spawner) {
16 let p = embassy_stm32::init(Default::default());
17 info!("Hello World!");
18
19 let mut i2s = I2S::new(
20 p.SPI2,
21 p.PC3, // sd
22 p.PB12, // ws
23 p.PB10, // ck
24 p.PC6, // mck
25 p.DMA1_CH4,
26 p.DMA1_CH3,
27 Hertz(1_000_000),
28 Config::default(),
29 );
30
31 for n in 0u32.. {
32 let mut write: String<128> = String::new();
33 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
34 i2s.write(&mut write.as_bytes()).await.ok();
35 }
36}
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs
index eeecbd321..6ec7d0fec 100644
--- a/examples/stm32f4/src/bin/sdmmc.rs
+++ b/examples/stm32f4/src/bin/sdmmc.rs
@@ -6,13 +6,17 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; 7use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
8use embassy_stm32::time::mhz; 8use embassy_stm32::time::mhz;
9use embassy_stm32::{interrupt, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12/// This is a safeguard to not overwrite any data on the SD card. 12/// This is a safeguard to not overwrite any data on the SD card.
13/// If you don't care about SD card contents, set this to `true` to test writes. 13/// If you don't care about SD card contents, set this to `true` to test writes.
14const ALLOW_WRITES: bool = false; 14const ALLOW_WRITES: bool = false;
15 15
16bind_interrupts!(struct Irqs {
17 SDIO => sdmmc::InterruptHandler<peripherals::SDIO>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 let mut config = Config::default(); 22 let mut config = Config::default();
@@ -21,11 +25,9 @@ async fn main(_spawner: Spawner) {
21 let p = embassy_stm32::init(config); 25 let p = embassy_stm32::init(config);
22 info!("Hello World!"); 26 info!("Hello World!");
23 27
24 let irq = interrupt::take!(SDIO);
25
26 let mut sdmmc = Sdmmc::new_4bit( 28 let mut sdmmc = Sdmmc::new_4bit(
27 p.SDIO, 29 p.SDIO,
28 irq, 30 Irqs,
29 p.DMA2_CH3, 31 p.DMA2_CH3,
30 p.PC12, 32 p.PC12,
31 p.PD2, 33 p.PD2,
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs
index 8f41bb6c4..7680fe845 100644
--- a/examples/stm32f4/src/bin/usart.rs
+++ b/examples/stm32f4/src/bin/usart.rs
@@ -5,10 +5,14 @@
5use cortex_m_rt::entry; 5use cortex_m_rt::entry;
6use defmt::*; 6use defmt::*;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt;
9use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
9use embassy_stm32::{bind_interrupts, peripherals, usart};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 USART3 => usart::InterruptHandler<peripherals::USART3>;
14});
15
12#[entry] 16#[entry]
13fn main() -> ! { 17fn main() -> ! {
14 info!("Hello World!"); 18 info!("Hello World!");
@@ -16,8 +20,7 @@ fn main() -> ! {
16 let p = embassy_stm32::init(Default::default()); 20 let p = embassy_stm32::init(Default::default());
17 21
18 let config = Config::default(); 22 let config = Config::default();
19 let irq = interrupt::take!(USART3); 23 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, NoDma, NoDma, config);
20 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, NoDma, NoDma, config);
21 24
22 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 25 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
23 info!("wrote Hello, starting echo"); 26 info!("wrote Hello, starting echo");
diff --git a/examples/stm32f4/src/bin/usart_buffered.rs b/examples/stm32f4/src/bin/usart_buffered.rs
index a93f8baeb..c573dc3a3 100644
--- a/examples/stm32f4/src/bin/usart_buffered.rs
+++ b/examples/stm32f4/src/bin/usart_buffered.rs
@@ -4,11 +4,15 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::interrupt;
8use embassy_stm32::usart::{BufferedUart, Config}; 7use embassy_stm32::usart::{BufferedUart, Config};
8use embassy_stm32::{bind_interrupts, peripherals, usart};
9use embedded_io::asynch::BufRead; 9use embedded_io::asynch::BufRead;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 USART3 => usart::BufferedInterruptHandler<peripherals::USART3>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
@@ -16,10 +20,9 @@ async fn main(_spawner: Spawner) {
16 20
17 let config = Config::default(); 21 let config = Config::default();
18 22
19 let irq = interrupt::take!(USART3);
20 let mut tx_buf = [0u8; 32]; 23 let mut tx_buf = [0u8; 32];
21 let mut rx_buf = [0u8; 32]; 24 let mut rx_buf = [0u8; 32];
22 let mut buf_usart = BufferedUart::new(p.USART3, irq, p.PD9, p.PD8, &mut tx_buf, &mut rx_buf, config); 25 let mut buf_usart = BufferedUart::new(p.USART3, Irqs, p.PD9, p.PD8, &mut tx_buf, &mut rx_buf, config);
23 26
24 loop { 27 loop {
25 let buf = buf_usart.fill_buf().await.unwrap(); 28 let buf = buf_usart.fill_buf().await.unwrap();
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs
index 78baeaa0d..3408ec370 100644
--- a/examples/stm32f4/src/bin/usart_dma.rs
+++ b/examples/stm32f4/src/bin/usart_dma.rs
@@ -7,19 +7,22 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
11use embassy_stm32::{bind_interrupts, peripherals, usart};
12use heapless::String; 12use heapless::String;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs {
16 USART3 => usart::InterruptHandler<peripherals::USART3>;
17});
18
15#[embassy_executor::main] 19#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 20async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 21 let p = embassy_stm32::init(Default::default());
18 info!("Hello World!"); 22 info!("Hello World!");
19 23
20 let config = Config::default(); 24 let config = Config::default();
21 let irq = interrupt::take!(USART3); 25 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, p.DMA1_CH3, NoDma, config);
22 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, p.DMA1_CH3, NoDma, config);
23 26
24 for n in 0u32.. { 27 for n in 0u32.. {
25 let mut s: String<128> = String::new(); 28 let mut s: String<128> = String::new();
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs
index 9131e5896..c4e395f0f 100644
--- a/examples/stm32f4/src/bin/usb_ethernet.rs
+++ b/examples/stm32f4/src/bin/usb_ethernet.rs
@@ -9,7 +9,7 @@ use embassy_net::{Stack, StackResources};
9use embassy_stm32::rng::Rng; 9use embassy_stm32::rng::Rng;
10use embassy_stm32::time::mhz; 10use embassy_stm32::time::mhz;
11use embassy_stm32::usb_otg::Driver; 11use embassy_stm32::usb_otg::Driver;
12use embassy_stm32::{interrupt, Config}; 12use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
13use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 13use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
14use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 14use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
15use embassy_usb::{Builder, UsbDevice}; 15use embassy_usb::{Builder, UsbDevice};
@@ -45,6 +45,10 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
45 stack.run().await 45 stack.run().await
46} 46}
47 47
48bind_interrupts!(struct Irqs {
49 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
50});
51
48#[embassy_executor::main] 52#[embassy_executor::main]
49async fn main(spawner: Spawner) { 53async fn main(spawner: Spawner) {
50 info!("Hello World!"); 54 info!("Hello World!");
@@ -56,9 +60,8 @@ async fn main(spawner: Spawner) {
56 let p = embassy_stm32::init(config); 60 let p = embassy_stm32::init(config);
57 61
58 // Create the driver, from the HAL. 62 // Create the driver, from the HAL.
59 let irq = interrupt::take!(OTG_FS);
60 let ep_out_buffer = &mut singleton!([0; 256])[..]; 63 let ep_out_buffer = &mut singleton!([0; 256])[..];
61 let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, ep_out_buffer); 64 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer);
62 65
63 // Create embassy-usb Config 66 // Create embassy-usb Config
64 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 67 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs
index d2b1dca43..f8f5940a7 100644
--- a/examples/stm32f4/src/bin/usb_serial.rs
+++ b/examples/stm32f4/src/bin/usb_serial.rs
@@ -6,13 +6,17 @@ use defmt::{panic, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::mhz; 7use embassy_stm32::time::mhz;
8use embassy_stm32::usb_otg::{Driver, Instance}; 8use embassy_stm32::usb_otg::{Driver, Instance};
9use embassy_stm32::{interrupt, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder; 12use embassy_usb::Builder;
13use futures::future::join; 13use futures::future::join;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs {
17 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 info!("Hello World!"); 22 info!("Hello World!");
@@ -24,9 +28,8 @@ async fn main(_spawner: Spawner) {
24 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
25 29
26 // Create the driver, from the HAL. 30 // Create the driver, from the HAL.
27 let irq = interrupt::take!(OTG_FS);
28 let mut ep_out_buffer = [0u8; 256]; 31 let mut ep_out_buffer = [0u8; 256];
29 let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer); 32 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
30 33
31 // Create embassy-usb Config 34 // Create embassy-usb Config
32 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 35 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs
index b947361ac..6d286c368 100644
--- a/examples/stm32f7/src/bin/eth.rs
+++ b/examples/stm32f7/src/bin/eth.rs
@@ -11,7 +11,7 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{interrupt, Config}; 14use embassy_stm32::{bind_interrupts, eth, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
17use rand_core::RngCore; 17use rand_core::RngCore;
@@ -27,6 +27,10 @@ macro_rules! singleton {
27 }}; 27 }};
28} 28}
29 29
30bind_interrupts!(struct Irqs {
31 ETH => eth::InterruptHandler;
32});
33
30type Device = Ethernet<'static, ETH, GenericSMI>; 34type Device = Ethernet<'static, ETH, GenericSMI>;
31 35
32#[embassy_executor::task] 36#[embassy_executor::task]
@@ -48,13 +52,12 @@ async fn main(spawner: Spawner) -> ! {
48 rng.fill_bytes(&mut seed); 52 rng.fill_bytes(&mut seed);
49 let seed = u64::from_le_bytes(seed); 53 let seed = u64::from_le_bytes(seed);
50 54
51 let eth_int = interrupt::take!(ETH);
52 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 55 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
53 56
54 let device = Ethernet::new( 57 let device = Ethernet::new(
55 singleton!(PacketQueue::<16, 16>::new()), 58 singleton!(PacketQueue::<16, 16>::new()),
56 p.ETH, 59 p.ETH,
57 eth_int, 60 Irqs,
58 p.PA1, 61 p.PA1,
59 p.PA2, 62 p.PA2,
60 p.PC1, 63 p.PC1,
diff --git a/examples/stm32f7/src/bin/sdmmc.rs b/examples/stm32f7/src/bin/sdmmc.rs
index c050a4002..9d43892a0 100644
--- a/examples/stm32f7/src/bin/sdmmc.rs
+++ b/examples/stm32f7/src/bin/sdmmc.rs
@@ -6,9 +6,13 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::sdmmc::Sdmmc; 7use embassy_stm32::sdmmc::Sdmmc;
8use embassy_stm32::time::mhz; 8use embassy_stm32::time::mhz;
9use embassy_stm32::{interrupt, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 SDMMC1 => sdmmc::InterruptHandler<peripherals::SDMMC1>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let mut config = Config::default(); 18 let mut config = Config::default();
@@ -18,11 +22,9 @@ async fn main(_spawner: Spawner) {
18 22
19 info!("Hello World!"); 23 info!("Hello World!");
20 24
21 let irq = interrupt::take!(SDMMC1);
22
23 let mut sdmmc = Sdmmc::new_4bit( 25 let mut sdmmc = Sdmmc::new_4bit(
24 p.SDMMC1, 26 p.SDMMC1,
25 irq, 27 Irqs,
26 p.DMA2_CH3, 28 p.DMA2_CH3,
27 p.PC12, 29 p.PC12,
28 p.PD2, 30 p.PD2,
diff --git a/examples/stm32f7/src/bin/usart_dma.rs b/examples/stm32f7/src/bin/usart_dma.rs
index 4827c52ae..4700287a7 100644
--- a/examples/stm32f7/src/bin/usart_dma.rs
+++ b/examples/stm32f7/src/bin/usart_dma.rs
@@ -7,17 +7,20 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
11use embassy_stm32::{bind_interrupts, peripherals, usart};
12use heapless::String; 12use heapless::String;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs {
16 UART7 => usart::InterruptHandler<peripherals::UART7>;
17});
18
15#[embassy_executor::main] 19#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 20async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 21 let p = embassy_stm32::init(Default::default());
18 let config = Config::default(); 22 let config = Config::default();
19 let irq = interrupt::take!(UART7); 23 let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, Irqs, p.DMA1_CH1, NoDma, config);
20 let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, irq, p.DMA1_CH1, NoDma, config);
21 24
22 for n in 0u32.. { 25 for n in 0u32.. {
23 let mut s: String<128> = String::new(); 26 let mut s: String<128> = String::new();
diff --git a/examples/stm32f7/src/bin/usb_serial.rs b/examples/stm32f7/src/bin/usb_serial.rs
index dca90d9cb..763309ce2 100644
--- a/examples/stm32f7/src/bin/usb_serial.rs
+++ b/examples/stm32f7/src/bin/usb_serial.rs
@@ -6,13 +6,17 @@ use defmt::{panic, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::mhz; 7use embassy_stm32::time::mhz;
8use embassy_stm32::usb_otg::{Driver, Instance}; 8use embassy_stm32::usb_otg::{Driver, Instance};
9use embassy_stm32::{interrupt, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder; 12use embassy_usb::Builder;
13use futures::future::join; 13use futures::future::join;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs {
17 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 info!("Hello World!"); 22 info!("Hello World!");
@@ -25,9 +29,8 @@ async fn main(_spawner: Spawner) {
25 let p = embassy_stm32::init(config); 29 let p = embassy_stm32::init(config);
26 30
27 // Create the driver, from the HAL. 31 // Create the driver, from the HAL.
28 let irq = interrupt::take!(OTG_FS);
29 let mut ep_out_buffer = [0u8; 256]; 32 let mut ep_out_buffer = [0u8; 256];
30 let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer); 33 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
31 34
32 // Create embassy-usb Config 35 // Create embassy-usb Config
33 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 36 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs
index b2e252fc7..fa1f225fe 100644
--- a/examples/stm32h5/src/bin/eth.rs
+++ b/examples/stm32h5/src/bin/eth.rs
@@ -12,7 +12,7 @@ use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; 12use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
14use embassy_stm32::time::Hertz; 14use embassy_stm32::time::Hertz;
15use embassy_stm32::{interrupt, Config}; 15use embassy_stm32::{bind_interrupts, eth, Config};
16use embassy_time::{Duration, Timer}; 16use embassy_time::{Duration, Timer};
17use embedded_io::asynch::Write; 17use embedded_io::asynch::Write;
18use rand_core::RngCore; 18use rand_core::RngCore;
@@ -28,6 +28,10 @@ macro_rules! singleton {
28 }}; 28 }};
29} 29}
30 30
31bind_interrupts!(struct Irqs {
32 ETH => eth::InterruptHandler;
33});
34
31type Device = Ethernet<'static, ETH, GenericSMI>; 35type Device = Ethernet<'static, ETH, GenericSMI>;
32 36
33#[embassy_executor::task] 37#[embassy_executor::task]
@@ -67,13 +71,12 @@ async fn main(spawner: Spawner) -> ! {
67 rng.fill_bytes(&mut seed); 71 rng.fill_bytes(&mut seed);
68 let seed = u64::from_le_bytes(seed); 72 let seed = u64::from_le_bytes(seed);
69 73
70 let eth_int = interrupt::take!(ETH);
71 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 74 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
72 75
73 let device = Ethernet::new( 76 let device = Ethernet::new(
74 singleton!(PacketQueue::<4, 4>::new()), 77 singleton!(PacketQueue::<4, 4>::new()),
75 p.ETH, 78 p.ETH,
76 eth_int, 79 Irqs,
77 p.PA1, 80 p.PA1,
78 p.PA2, 81 p.PA2,
79 p.PC1, 82 p.PC1,
diff --git a/examples/stm32h5/src/bin/i2c.rs b/examples/stm32h5/src/bin/i2c.rs
index 6cbf58bbc..8b6fe71ae 100644
--- a/examples/stm32h5/src/bin/i2c.rs
+++ b/examples/stm32h5/src/bin/i2c.rs
@@ -5,25 +5,28 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; 7use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
8use embassy_stm32::interrupt;
9use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, i2c, peripherals};
10use embassy_time::Duration; 10use embassy_time::Duration;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13const ADDRESS: u8 = 0x5F; 13const ADDRESS: u8 = 0x5F;
14const WHOAMI: u8 = 0x0F; 14const WHOAMI: u8 = 0x0F;
15 15
16bind_interrupts!(struct Irqs {
17 I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 info!("Hello world!"); 22 info!("Hello world!");
19 let p = embassy_stm32::init(Default::default()); 23 let p = embassy_stm32::init(Default::default());
20 24
21 let irq = interrupt::take!(I2C2_EV);
22 let mut i2c = I2c::new( 25 let mut i2c = I2c::new(
23 p.I2C2, 26 p.I2C2,
24 p.PB10, 27 p.PB10,
25 p.PB11, 28 p.PB11,
26 irq, 29 Irqs,
27 p.GPDMA1_CH4, 30 p.GPDMA1_CH4,
28 p.GPDMA1_CH5, 31 p.GPDMA1_CH5,
29 Hertz(100_000), 32 Hertz(100_000),
diff --git a/examples/stm32h5/src/bin/usart.rs b/examples/stm32h5/src/bin/usart.rs
index 405f18ec7..0abb94abb 100644
--- a/examples/stm32h5/src/bin/usart.rs
+++ b/examples/stm32h5/src/bin/usart.rs
@@ -6,18 +6,21 @@ use cortex_m_rt::entry;
6use defmt::*; 6use defmt::*;
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_stm32::dma::NoDma; 8use embassy_stm32::dma::NoDma;
9use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 9use embassy_stm32::usart::{Config, Uart};
10use embassy_stm32::{bind_interrupts, peripherals, usart};
11use static_cell::StaticCell; 11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs {
15 UART7 => usart::InterruptHandler<peripherals::UART7>;
16});
17
14#[embassy_executor::task] 18#[embassy_executor::task]
15async fn main_task() { 19async fn main_task() {
16 let p = embassy_stm32::init(Default::default()); 20 let p = embassy_stm32::init(Default::default());
17 21
18 let config = Config::default(); 22 let config = Config::default();
19 let irq = interrupt::take!(UART7); 23 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, NoDma, NoDma, config);
20 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, NoDma, NoDma, config);
21 24
22 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 25 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
23 info!("wrote Hello, starting echo"); 26 info!("wrote Hello, starting echo");
diff --git a/examples/stm32h5/src/bin/usart_dma.rs b/examples/stm32h5/src/bin/usart_dma.rs
index 43d791aae..48264f884 100644
--- a/examples/stm32h5/src/bin/usart_dma.rs
+++ b/examples/stm32h5/src/bin/usart_dma.rs
@@ -8,19 +8,22 @@ use cortex_m_rt::entry;
8use defmt::*; 8use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_stm32::dma::NoDma; 10use embassy_stm32::dma::NoDma;
11use embassy_stm32::interrupt;
12use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
12use embassy_stm32::{bind_interrupts, peripherals, usart};
13use heapless::String; 13use heapless::String;
14use static_cell::StaticCell; 14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17bind_interrupts!(struct Irqs {
18 UART7 => usart::InterruptHandler<peripherals::UART7>;
19});
20
17#[embassy_executor::task] 21#[embassy_executor::task]
18async fn main_task() { 22async fn main_task() {
19 let p = embassy_stm32::init(Default::default()); 23 let p = embassy_stm32::init(Default::default());
20 24
21 let config = Config::default(); 25 let config = Config::default();
22 let irq = interrupt::take!(UART7); 26 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, NoDma, config);
23 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.GPDMA1_CH0, NoDma, config);
24 27
25 for n in 0u32.. { 28 for n in 0u32.. {
26 let mut s: String<128> = String::new(); 29 let mut s: String<128> = String::new();
diff --git a/examples/stm32h5/src/bin/usart_split.rs b/examples/stm32h5/src/bin/usart_split.rs
index 16a499582..debd6f454 100644
--- a/examples/stm32h5/src/bin/usart_split.rs
+++ b/examples/stm32h5/src/bin/usart_split.rs
@@ -5,13 +5,17 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt;
9use embassy_stm32::peripherals::{GPDMA1_CH1, UART7}; 8use embassy_stm32::peripherals::{GPDMA1_CH1, UART7};
10use embassy_stm32::usart::{Config, Uart, UartRx}; 9use embassy_stm32::usart::{Config, Uart, UartRx};
10use embassy_stm32::{bind_interrupts, peripherals, usart};
11use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 11use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
12use embassy_sync::channel::Channel; 12use embassy_sync::channel::Channel;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs {
16 UART7 => usart::InterruptHandler<peripherals::UART7>;
17});
18
15#[embassy_executor::task] 19#[embassy_executor::task]
16async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) { 20async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
17 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 21 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
@@ -32,8 +36,7 @@ async fn main(spawner: Spawner) -> ! {
32 info!("Hello World!"); 36 info!("Hello World!");
33 37
34 let config = Config::default(); 38 let config = Config::default();
35 let irq = interrupt::take!(UART7); 39 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1, config);
36 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.GPDMA1_CH0, p.GPDMA1_CH1, config);
37 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n")); 40 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
38 41
39 let (mut tx, rx) = usart.split(); 42 let (mut tx, rx) = usart.split();
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs
index 4f987cbd1..3912327e2 100644
--- a/examples/stm32h5/src/bin/usb_serial.rs
+++ b/examples/stm32h5/src/bin/usb_serial.rs
@@ -7,13 +7,17 @@ use embassy_executor::Spawner;
7use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; 7use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
8use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::usb::{Driver, Instance}; 9use embassy_stm32::usb::{Driver, Instance};
10use embassy_stm32::{interrupt, pac, Config}; 10use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
12use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
13use embassy_usb::Builder; 13use embassy_usb::Builder;
14use futures::future::join; 14use futures::future::join;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17bind_interrupts!(struct Irqs {
18 USB_DRD_FS => usb::InterruptHandler<peripherals::USB>;
19});
20
17#[embassy_executor::main] 21#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
19 let mut config = Config::default(); 23 let mut config = Config::default();
@@ -48,8 +52,7 @@ async fn main(_spawner: Spawner) {
48 } 52 }
49 53
50 // Create the driver, from the HAL. 54 // Create the driver, from the HAL.
51 let irq = interrupt::take!(USB_DRD_FS); 55 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
52 let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
53 56
54 // Create embassy-usb Config 57 // Create embassy-usb Config
55 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 58 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs
index 9c443b83a..6f75a0630 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -8,7 +8,7 @@ use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::i2c::I2c; 8use embassy_stm32::i2c::I2c;
9use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; 9use embassy_stm32::rcc::{Mco, Mco1Source, McoClock};
10use embassy_stm32::time::{khz, mhz}; 10use embassy_stm32::time::{khz, mhz};
11use embassy_stm32::{interrupt, Config}; 11use embassy_stm32::{bind_interrupts, i2c, peripherals, Config};
12use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
13use ov7725::*; 13use ov7725::*;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
@@ -18,6 +18,11 @@ const HEIGHT: usize = 100;
18 18
19static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2]; 19static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2];
20 20
21bind_interrupts!(struct Irqs {
22 I2C1_EV => i2c::InterruptHandler<peripherals::I2C1>;
23 DCMI => dcmi::InterruptHandler<peripherals::DCMI>;
24});
25
21#[embassy_executor::main] 26#[embassy_executor::main]
22async fn main(_spawner: Spawner) { 27async fn main(_spawner: Spawner) {
23 let mut config = Config::default(); 28 let mut config = Config::default();
@@ -34,12 +39,11 @@ async fn main(_spawner: Spawner) {
34 let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::Hsi, McoClock::Divided(3)); 39 let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::Hsi, McoClock::Divided(3));
35 40
36 let mut led = Output::new(p.PE3, Level::High, Speed::Low); 41 let mut led = Output::new(p.PE3, Level::High, Speed::Low);
37 let i2c_irq = interrupt::take!(I2C1_EV);
38 let cam_i2c = I2c::new( 42 let cam_i2c = I2c::new(
39 p.I2C1, 43 p.I2C1,
40 p.PB8, 44 p.PB8,
41 p.PB9, 45 p.PB9,
42 i2c_irq, 46 Irqs,
43 p.DMA1_CH1, 47 p.DMA1_CH1,
44 p.DMA1_CH2, 48 p.DMA1_CH2,
45 khz(100), 49 khz(100),
@@ -55,11 +59,9 @@ async fn main(_spawner: Spawner) {
55 59
56 defmt::info!("manufacturer: 0x{:x}, pid: 0x{:x}", manufacturer_id, camera_id); 60 defmt::info!("manufacturer: 0x{:x}, pid: 0x{:x}", manufacturer_id, camera_id);
57 61
58 let dcmi_irq = interrupt::take!(DCMI);
59 let config = dcmi::Config::default(); 62 let config = dcmi::Config::default();
60 let mut dcmi = Dcmi::new_8bit( 63 let mut dcmi = Dcmi::new_8bit(
61 p.DCMI, p.DMA1_CH0, dcmi_irq, p.PC6, p.PC7, p.PE0, p.PE1, p.PE4, p.PD3, p.PE5, p.PE6, p.PB7, p.PA4, p.PA6, 64 p.DCMI, p.DMA1_CH0, Irqs, p.PC6, p.PC7, p.PE0, p.PE1, p.PE4, p.PD3, p.PE5, p.PE6, p.PB7, p.PA4, p.PA6, config,
62 config,
63 ); 65 );
64 66
65 defmt::info!("attempting capture"); 67 defmt::info!("attempting capture");
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index 61bb7e37b..dbfc90cf4 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -11,7 +11,7 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{interrupt, Config}; 14use embassy_stm32::{bind_interrupts, eth, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
17use rand_core::RngCore; 17use rand_core::RngCore;
@@ -27,6 +27,10 @@ macro_rules! singleton {
27 }}; 27 }};
28} 28}
29 29
30bind_interrupts!(struct Irqs {
31 ETH => eth::InterruptHandler;
32});
33
30type Device = Ethernet<'static, ETH, GenericSMI>; 34type Device = Ethernet<'static, ETH, GenericSMI>;
31 35
32#[embassy_executor::task] 36#[embassy_executor::task]
@@ -49,13 +53,12 @@ async fn main(spawner: Spawner) -> ! {
49 rng.fill_bytes(&mut seed); 53 rng.fill_bytes(&mut seed);
50 let seed = u64::from_le_bytes(seed); 54 let seed = u64::from_le_bytes(seed);
51 55
52 let eth_int = interrupt::take!(ETH);
53 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 56 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
54 57
55 let device = Ethernet::new( 58 let device = Ethernet::new(
56 singleton!(PacketQueue::<16, 16>::new()), 59 singleton!(PacketQueue::<16, 16>::new()),
57 p.ETH, 60 p.ETH,
58 eth_int, 61 Irqs,
59 p.PA1, 62 p.PA1,
60 p.PA2, 63 p.PA2,
61 p.PC1, 64 p.PC1,
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index b609fa5df..14e6b7914 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -11,7 +11,7 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{interrupt, Config}; 14use embassy_stm32::{bind_interrupts, eth, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
17use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; 17use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect};
@@ -28,6 +28,10 @@ macro_rules! singleton {
28 }}; 28 }};
29} 29}
30 30
31bind_interrupts!(struct Irqs {
32 ETH => eth::InterruptHandler;
33});
34
31type Device = Ethernet<'static, ETH, GenericSMI>; 35type Device = Ethernet<'static, ETH, GenericSMI>;
32 36
33#[embassy_executor::task] 37#[embassy_executor::task]
@@ -50,13 +54,12 @@ async fn main(spawner: Spawner) -> ! {
50 rng.fill_bytes(&mut seed); 54 rng.fill_bytes(&mut seed);
51 let seed = u64::from_le_bytes(seed); 55 let seed = u64::from_le_bytes(seed);
52 56
53 let eth_int = interrupt::take!(ETH);
54 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 57 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
55 58
56 let device = Ethernet::new( 59 let device = Ethernet::new(
57 singleton!(PacketQueue::<16, 16>::new()), 60 singleton!(PacketQueue::<16, 16>::new()),
58 p.ETH, 61 p.ETH,
59 eth_int, 62 Irqs,
60 p.PA1, 63 p.PA1,
61 p.PA2, 64 p.PA2,
62 p.PC1, 65 p.PC1,
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs
index 78e03f014..c2979c59b 100644
--- a/examples/stm32h7/src/bin/i2c.rs
+++ b/examples/stm32h7/src/bin/i2c.rs
@@ -5,25 +5,28 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; 7use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
8use embassy_stm32::interrupt;
9use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, i2c, peripherals};
10use embassy_time::Duration; 10use embassy_time::Duration;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13const ADDRESS: u8 = 0x5F; 13const ADDRESS: u8 = 0x5F;
14const WHOAMI: u8 = 0x0F; 14const WHOAMI: u8 = 0x0F;
15 15
16bind_interrupts!(struct Irqs {
17 I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 info!("Hello world!"); 22 info!("Hello world!");
19 let p = embassy_stm32::init(Default::default()); 23 let p = embassy_stm32::init(Default::default());
20 24
21 let irq = interrupt::take!(I2C2_EV);
22 let mut i2c = I2c::new( 25 let mut i2c = I2c::new(
23 p.I2C2, 26 p.I2C2,
24 p.PB10, 27 p.PB10,
25 p.PB11, 28 p.PB11,
26 irq, 29 Irqs,
27 p.DMA1_CH4, 30 p.DMA1_CH4,
28 p.DMA1_CH5, 31 p.DMA1_CH5,
29 Hertz(100_000), 32 Hertz(100_000),
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs
index 26d1db01e..ce91b6b1c 100644
--- a/examples/stm32h7/src/bin/sdmmc.rs
+++ b/examples/stm32h7/src/bin/sdmmc.rs
@@ -6,9 +6,13 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::sdmmc::Sdmmc; 7use embassy_stm32::sdmmc::Sdmmc;
8use embassy_stm32::time::mhz; 8use embassy_stm32::time::mhz;
9use embassy_stm32::{interrupt, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 SDMMC1 => sdmmc::InterruptHandler<peripherals::SDMMC1>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! { 17async fn main(_spawner: Spawner) -> ! {
14 let mut config = Config::default(); 18 let mut config = Config::default();
@@ -16,11 +20,9 @@ async fn main(_spawner: Spawner) -> ! {
16 let p = embassy_stm32::init(config); 20 let p = embassy_stm32::init(config);
17 info!("Hello World!"); 21 info!("Hello World!");
18 22
19 let irq = interrupt::take!(SDMMC1);
20
21 let mut sdmmc = Sdmmc::new_4bit( 23 let mut sdmmc = Sdmmc::new_4bit(
22 p.SDMMC1, 24 p.SDMMC1,
23 irq, 25 Irqs,
24 p.PC12, 26 p.PC12,
25 p.PD2, 27 p.PD2,
26 p.PC8, 28 p.PC8,
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs
index 405f18ec7..0abb94abb 100644
--- a/examples/stm32h7/src/bin/usart.rs
+++ b/examples/stm32h7/src/bin/usart.rs
@@ -6,18 +6,21 @@ use cortex_m_rt::entry;
6use defmt::*; 6use defmt::*;
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_stm32::dma::NoDma; 8use embassy_stm32::dma::NoDma;
9use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 9use embassy_stm32::usart::{Config, Uart};
10use embassy_stm32::{bind_interrupts, peripherals, usart};
11use static_cell::StaticCell; 11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs {
15 UART7 => usart::InterruptHandler<peripherals::UART7>;
16});
17
14#[embassy_executor::task] 18#[embassy_executor::task]
15async fn main_task() { 19async fn main_task() {
16 let p = embassy_stm32::init(Default::default()); 20 let p = embassy_stm32::init(Default::default());
17 21
18 let config = Config::default(); 22 let config = Config::default();
19 let irq = interrupt::take!(UART7); 23 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, NoDma, NoDma, config);
20 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, NoDma, NoDma, config);
21 24
22 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 25 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
23 info!("wrote Hello, starting echo"); 26 info!("wrote Hello, starting echo");
diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs
index 6e3491e55..f1fe7fce6 100644
--- a/examples/stm32h7/src/bin/usart_dma.rs
+++ b/examples/stm32h7/src/bin/usart_dma.rs
@@ -8,19 +8,22 @@ use cortex_m_rt::entry;
8use defmt::*; 8use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_stm32::dma::NoDma; 10use embassy_stm32::dma::NoDma;
11use embassy_stm32::interrupt;
12use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
12use embassy_stm32::{bind_interrupts, peripherals, usart};
13use heapless::String; 13use heapless::String;
14use static_cell::StaticCell; 14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17bind_interrupts!(struct Irqs {
18 UART7 => usart::InterruptHandler<peripherals::UART7>;
19});
20
17#[embassy_executor::task] 21#[embassy_executor::task]
18async fn main_task() { 22async fn main_task() {
19 let p = embassy_stm32::init(Default::default()); 23 let p = embassy_stm32::init(Default::default());
20 24
21 let config = Config::default(); 25 let config = Config::default();
22 let irq = interrupt::take!(UART7); 26 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.DMA1_CH0, NoDma, config);
23 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, NoDma, config);
24 27
25 for n in 0u32.. { 28 for n in 0u32.. {
26 let mut s: String<128> = String::new(); 29 let mut s: String<128> = String::new();
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs
index f97176ecb..330d1ce09 100644
--- a/examples/stm32h7/src/bin/usart_split.rs
+++ b/examples/stm32h7/src/bin/usart_split.rs
@@ -5,13 +5,17 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt;
9use embassy_stm32::peripherals::{DMA1_CH1, UART7}; 8use embassy_stm32::peripherals::{DMA1_CH1, UART7};
10use embassy_stm32::usart::{Config, Uart, UartRx}; 9use embassy_stm32::usart::{Config, Uart, UartRx};
10use embassy_stm32::{bind_interrupts, peripherals, usart};
11use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 11use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
12use embassy_sync::channel::Channel; 12use embassy_sync::channel::Channel;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs {
16 UART7 => usart::InterruptHandler<peripherals::UART7>;
17});
18
15#[embassy_executor::task] 19#[embassy_executor::task]
16async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) { 20async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
17 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 21 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
@@ -32,8 +36,7 @@ async fn main(spawner: Spawner) -> ! {
32 info!("Hello World!"); 36 info!("Hello World!");
33 37
34 let config = Config::default(); 38 let config = Config::default();
35 let irq = interrupt::take!(UART7); 39 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.DMA1_CH0, p.DMA1_CH1, config);
36 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, p.DMA1_CH1, config);
37 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n")); 40 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
38 41
39 let (mut tx, rx) = usart.split(); 42 let (mut tx, rx) = usart.split();
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs
index 475af116d..c622f19f7 100644
--- a/examples/stm32h7/src/bin/usb_serial.rs
+++ b/examples/stm32h7/src/bin/usb_serial.rs
@@ -6,13 +6,17 @@ use defmt::{panic, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::mhz; 7use embassy_stm32::time::mhz;
8use embassy_stm32::usb_otg::{Driver, Instance}; 8use embassy_stm32::usb_otg::{Driver, Instance};
9use embassy_stm32::{interrupt, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder; 12use embassy_usb::Builder;
13use futures::future::join; 13use futures::future::join;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs {
17 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 info!("Hello World!"); 22 info!("Hello World!");
@@ -24,9 +28,8 @@ async fn main(_spawner: Spawner) {
24 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
25 29
26 // Create the driver, from the HAL. 30 // Create the driver, from the HAL.
27 let irq = interrupt::take!(OTG_FS);
28 let mut ep_out_buffer = [0u8; 256]; 31 let mut ep_out_buffer = [0u8; 256];
29 let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer); 32 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
30 33
31 // Create embassy-usb Config 34 // Create embassy-usb Config
32 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 35 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32l0/src/bin/usart_dma.rs b/examples/stm32l0/src/bin/usart_dma.rs
index c307f857a..eae8f3452 100644
--- a/examples/stm32l0/src/bin/usart_dma.rs
+++ b/examples/stm32l0/src/bin/usart_dma.rs
@@ -4,15 +4,18 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::interrupt;
8use embassy_stm32::usart::{Config, Uart}; 7use embassy_stm32::usart::{Config, Uart};
8use embassy_stm32::{bind_interrupts, peripherals, usart};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs {
12 USART1 => usart::InterruptHandler<peripherals::USART1>;
13});
14
11#[embassy_executor::main] 15#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
13 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
14 let irq = interrupt::take!(USART1); 18 let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, Irqs, p.DMA1_CH2, p.DMA1_CH3, Config::default());
15 let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, irq, p.DMA1_CH2, p.DMA1_CH3, Config::default());
16 19
17 usart.write(b"Hello Embassy World!\r\n").await.unwrap(); 20 usart.write(b"Hello Embassy World!\r\n").await.unwrap();
18 info!("wrote Hello, starting echo"); 21 info!("wrote Hello, starting echo");
diff --git a/examples/stm32l0/src/bin/usart_irq.rs b/examples/stm32l0/src/bin/usart_irq.rs
index 465347004..f2c72a107 100644
--- a/examples/stm32l0/src/bin/usart_irq.rs
+++ b/examples/stm32l0/src/bin/usart_irq.rs
@@ -4,11 +4,15 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::interrupt;
8use embassy_stm32::usart::{BufferedUart, Config}; 7use embassy_stm32::usart::{BufferedUart, Config};
8use embassy_stm32::{bind_interrupts, peripherals, usart};
9use embedded_io::asynch::{Read, Write}; 9use embedded_io::asynch::{Read, Write};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 USART2 => usart::BufferedInterruptHandler<peripherals::USART2>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
@@ -20,8 +24,7 @@ async fn main(_spawner: Spawner) {
20 let mut config = Config::default(); 24 let mut config = Config::default();
21 config.baudrate = 9600; 25 config.baudrate = 9600;
22 26
23 let irq = interrupt::take!(USART2); 27 let mut usart = unsafe { BufferedUart::new(p.USART2, Irqs, p.PA3, p.PA2, &mut TX_BUFFER, &mut RX_BUFFER, config) };
24 let mut usart = unsafe { BufferedUart::new(p.USART2, irq, p.PA3, p.PA2, &mut TX_BUFFER, &mut RX_BUFFER, config) };
25 28
26 usart.write_all(b"Hello Embassy World!\r\n").await.unwrap(); 29 usart.write_all(b"Hello Embassy World!\r\n").await.unwrap();
27 info!("wrote Hello, starting echo"); 30 info!("wrote Hello, starting echo");
diff --git a/examples/stm32l4/src/bin/i2c.rs b/examples/stm32l4/src/bin/i2c.rs
index d40d6803d..d0060d20c 100644
--- a/examples/stm32l4/src/bin/i2c.rs
+++ b/examples/stm32l4/src/bin/i2c.rs
@@ -6,22 +6,25 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::i2c::I2c; 8use embassy_stm32::i2c::I2c;
9use embassy_stm32::interrupt;
10use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, i2c, peripherals};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13const ADDRESS: u8 = 0x5F; 13const ADDRESS: u8 = 0x5F;
14const WHOAMI: u8 = 0x0F; 14const WHOAMI: u8 = 0x0F;
15 15
16bind_interrupts!(struct Irqs {
17 I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 let p = embassy_stm32::init(Default::default()); 22 let p = embassy_stm32::init(Default::default());
19 let irq = interrupt::take!(I2C2_EV);
20 let mut i2c = I2c::new( 23 let mut i2c = I2c::new(
21 p.I2C2, 24 p.I2C2,
22 p.PB10, 25 p.PB10,
23 p.PB11, 26 p.PB11,
24 irq, 27 Irqs,
25 NoDma, 28 NoDma,
26 NoDma, 29 NoDma,
27 Hertz(100_000), 30 Hertz(100_000),
diff --git a/examples/stm32l4/src/bin/i2c_blocking_async.rs b/examples/stm32l4/src/bin/i2c_blocking_async.rs
index d868cac01..eca59087b 100644
--- a/examples/stm32l4/src/bin/i2c_blocking_async.rs
+++ b/examples/stm32l4/src/bin/i2c_blocking_async.rs
@@ -7,23 +7,26 @@ use embassy_embedded_hal::adapter::BlockingAsync;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::dma::NoDma; 8use embassy_stm32::dma::NoDma;
9use embassy_stm32::i2c::I2c; 9use embassy_stm32::i2c::I2c;
10use embassy_stm32::interrupt;
11use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
11use embassy_stm32::{bind_interrupts, i2c, peripherals};
12use embedded_hal_async::i2c::I2c as I2cTrait; 12use embedded_hal_async::i2c::I2c as I2cTrait;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15const ADDRESS: u8 = 0x5F; 15const ADDRESS: u8 = 0x5F;
16const WHOAMI: u8 = 0x0F; 16const WHOAMI: u8 = 0x0F;
17 17
18bind_interrupts!(struct Irqs {
19 I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
20});
21
18#[embassy_executor::main] 22#[embassy_executor::main]
19async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
20 let p = embassy_stm32::init(Default::default()); 24 let p = embassy_stm32::init(Default::default());
21 let irq = interrupt::take!(I2C2_EV);
22 let i2c = I2c::new( 25 let i2c = I2c::new(
23 p.I2C2, 26 p.I2C2,
24 p.PB10, 27 p.PB10,
25 p.PB11, 28 p.PB11,
26 irq, 29 Irqs,
27 NoDma, 30 NoDma,
28 NoDma, 31 NoDma,
29 Hertz(100_000), 32 Hertz(100_000),
diff --git a/examples/stm32l4/src/bin/i2c_dma.rs b/examples/stm32l4/src/bin/i2c_dma.rs
index 7e62ee637..cf6f3da67 100644
--- a/examples/stm32l4/src/bin/i2c_dma.rs
+++ b/examples/stm32l4/src/bin/i2c_dma.rs
@@ -5,22 +5,25 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::i2c::I2c; 7use embassy_stm32::i2c::I2c;
8use embassy_stm32::interrupt;
9use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, i2c, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12const ADDRESS: u8 = 0x5F; 12const ADDRESS: u8 = 0x5F;
13const WHOAMI: u8 = 0x0F; 13const WHOAMI: u8 = 0x0F;
14 14
15bind_interrupts!(struct Irqs {
16 I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>;
17});
18
15#[embassy_executor::main] 19#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 20async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 21 let p = embassy_stm32::init(Default::default());
18 let irq = interrupt::take!(I2C2_EV);
19 let mut i2c = I2c::new( 22 let mut i2c = I2c::new(
20 p.I2C2, 23 p.I2C2,
21 p.PB10, 24 p.PB10,
22 p.PB11, 25 p.PB11,
23 irq, 26 Irqs,
24 p.DMA1_CH4, 27 p.DMA1_CH4,
25 p.DMA1_CH5, 28 p.DMA1_CH5,
26 Hertz(100_000), 29 Hertz(100_000),
diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs
index 7d874d9d7..beb5ec558 100644
--- a/examples/stm32l4/src/bin/usart.rs
+++ b/examples/stm32l4/src/bin/usart.rs
@@ -4,10 +4,14 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_stm32::dma::NoDma; 6use embassy_stm32::dma::NoDma;
7use embassy_stm32::interrupt;
8use embassy_stm32::usart::{Config, Uart}; 7use embassy_stm32::usart::{Config, Uart};
8use embassy_stm32::{bind_interrupts, peripherals, usart};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs {
12 UART4 => usart::InterruptHandler<peripherals::UART4>;
13});
14
11#[cortex_m_rt::entry] 15#[cortex_m_rt::entry]
12fn main() -> ! { 16fn main() -> ! {
13 info!("Hello World!"); 17 info!("Hello World!");
@@ -15,8 +19,7 @@ fn main() -> ! {
15 let p = embassy_stm32::init(Default::default()); 19 let p = embassy_stm32::init(Default::default());
16 20
17 let config = Config::default(); 21 let config = Config::default();
18 let irq = interrupt::take!(UART4); 22 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, NoDma, NoDma, config);
19 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, NoDma, NoDma, config);
20 23
21 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 24 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
22 info!("wrote Hello, starting echo"); 25 info!("wrote Hello, starting echo");
diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs
index 452bede30..b7d4cb01e 100644
--- a/examples/stm32l4/src/bin/usart_dma.rs
+++ b/examples/stm32l4/src/bin/usart_dma.rs
@@ -7,19 +7,22 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
11use embassy_stm32::{bind_interrupts, peripherals, usart};
12use heapless::String; 12use heapless::String;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs {
16 UART4 => usart::InterruptHandler<peripherals::UART4>;
17});
18
15#[embassy_executor::main] 19#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 20async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 21 let p = embassy_stm32::init(Default::default());
18 info!("Hello World!"); 22 info!("Hello World!");
19 23
20 let config = Config::default(); 24 let config = Config::default();
21 let irq = interrupt::take!(UART4); 25 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, p.DMA1_CH3, NoDma, config);
22 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, p.DMA1_CH3, NoDma, config);
23 26
24 for n in 0u32.. { 27 for n in 0u32.. {
25 let mut s: String<128> = String::new(); 28 let mut s: String<128> = String::new();
diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs
index bdb290e63..80811a43e 100644
--- a/examples/stm32l4/src/bin/usb_serial.rs
+++ b/examples/stm32l4/src/bin/usb_serial.rs
@@ -7,13 +7,17 @@ use defmt_rtt as _; // global logger
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::rcc::*; 8use embassy_stm32::rcc::*;
9use embassy_stm32::usb_otg::{Driver, Instance}; 9use embassy_stm32::usb_otg::{Driver, Instance};
10use embassy_stm32::{interrupt, Config}; 10use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
12use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
13use embassy_usb::Builder; 13use embassy_usb::Builder;
14use futures::future::join; 14use futures::future::join;
15use panic_probe as _; 15use panic_probe as _;
16 16
17bind_interrupts!(struct Irqs {
18 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
19});
20
17#[embassy_executor::main] 21#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
19 info!("Hello World!"); 23 info!("Hello World!");
@@ -25,9 +29,8 @@ async fn main(_spawner: Spawner) {
25 let p = embassy_stm32::init(config); 29 let p = embassy_stm32::init(config);
26 30
27 // Create the driver, from the HAL. 31 // Create the driver, from the HAL.
28 let irq = interrupt::take!(OTG_FS);
29 let mut ep_out_buffer = [0u8; 256]; 32 let mut ep_out_buffer = [0u8; 256];
30 let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer); 33 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
31 34
32 // Create embassy-usb Config 35 // Create embassy-usb Config
33 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 36 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index 6c5645a41..b84e53d3a 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -9,7 +9,7 @@ use embassy_net::{Stack, StackResources};
9use embassy_stm32::rcc::*; 9use embassy_stm32::rcc::*;
10use embassy_stm32::rng::Rng; 10use embassy_stm32::rng::Rng;
11use embassy_stm32::usb::Driver; 11use embassy_stm32::usb::Driver;
12use embassy_stm32::{interrupt, Config}; 12use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
13use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 13use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
14use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 14use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
15use embassy_usb::{Builder, UsbDevice}; 15use embassy_usb::{Builder, UsbDevice};
@@ -31,6 +31,10 @@ macro_rules! singleton {
31 31
32const MTU: usize = 1514; 32const MTU: usize = 1514;
33 33
34bind_interrupts!(struct Irqs {
35 USB_FS => usb::InterruptHandler<peripherals::USB>;
36});
37
34#[embassy_executor::task] 38#[embassy_executor::task]
35async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! { 39async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! {
36 device.run().await 40 device.run().await
@@ -54,8 +58,7 @@ async fn main(spawner: Spawner) {
54 let p = embassy_stm32::init(config); 58 let p = embassy_stm32::init(config);
55 59
56 // Create the driver, from the HAL. 60 // Create the driver, from the HAL.
57 let irq = interrupt::take!(USB_FS); 61 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
58 let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
59 62
60 // Create embassy-usb Config 63 // Create embassy-usb Config
61 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 64 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs
index e3bbe9d09..7e894e407 100644
--- a/examples/stm32l5/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_stm32::rcc::*; 8use embassy_stm32::rcc::*;
9use embassy_stm32::usb::Driver; 9use embassy_stm32::usb::Driver;
10use embassy_stm32::{interrupt, Config}; 10use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
11use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
12use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 12use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
13use embassy_usb::control::OutResponse; 13use embassy_usb::control::OutResponse;
@@ -15,6 +15,10 @@ use embassy_usb::Builder;
15use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 15use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18bind_interrupts!(struct Irqs {
19 USB_FS => usb::InterruptHandler<peripherals::USB>;
20});
21
18#[embassy_executor::main] 22#[embassy_executor::main]
19async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
20 let mut config = Config::default(); 24 let mut config = Config::default();
@@ -23,8 +27,7 @@ async fn main(_spawner: Spawner) {
23 let p = embassy_stm32::init(config); 27 let p = embassy_stm32::init(config);
24 28
25 // Create the driver, from the HAL. 29 // Create the driver, from the HAL.
26 let irq = interrupt::take!(USB_FS); 30 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
27 let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
28 31
29 // Create embassy-usb Config 32 // Create embassy-usb Config
30 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 33 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs
index 66ccacb73..0c719560f 100644
--- a/examples/stm32l5/src/bin/usb_serial.rs
+++ b/examples/stm32l5/src/bin/usb_serial.rs
@@ -7,12 +7,16 @@ use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_stm32::rcc::*; 8use embassy_stm32::rcc::*;
9use embassy_stm32::usb::{Driver, Instance}; 9use embassy_stm32::usb::{Driver, Instance};
10use embassy_stm32::{interrupt, Config}; 10use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
12use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
13use embassy_usb::Builder; 13use embassy_usb::Builder;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs {
17 USB_FS => usb::InterruptHandler<peripherals::USB>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
18 let mut config = Config::default(); 22 let mut config = Config::default();
@@ -23,8 +27,7 @@ async fn main(_spawner: Spawner) {
23 info!("Hello World!"); 27 info!("Hello World!");
24 28
25 // Create the driver, from the HAL. 29 // Create the driver, from the HAL.
26 let irq = interrupt::take!(USB_FS); 30 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
27 let driver = Driver::new(p.USB, irq, p.PA12, p.PA11);
28 31
29 // Create embassy-usb Config 32 // Create embassy-usb Config
30 let config = embassy_usb::Config::new(0xc0de, 0xcafe); 33 let config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs
index 4882cd2e0..f36daf91b 100644
--- a/examples/stm32u5/src/bin/usb_serial.rs
+++ b/examples/stm32u5/src/bin/usb_serial.rs
@@ -7,13 +7,17 @@ use defmt_rtt as _; // global logger
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::rcc::*; 8use embassy_stm32::rcc::*;
9use embassy_stm32::usb_otg::{Driver, Instance}; 9use embassy_stm32::usb_otg::{Driver, Instance};
10use embassy_stm32::{interrupt, Config}; 10use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
12use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
13use embassy_usb::Builder; 13use embassy_usb::Builder;
14use futures::future::join; 14use futures::future::join;
15use panic_probe as _; 15use panic_probe as _;
16 16
17bind_interrupts!(struct Irqs {
18 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
19});
20
17#[embassy_executor::main] 21#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
19 info!("Hello World!"); 23 info!("Hello World!");
@@ -26,9 +30,8 @@ async fn main(_spawner: Spawner) {
26 let p = embassy_stm32::init(config); 30 let p = embassy_stm32::init(config);
27 31
28 // Create the driver, from the HAL. 32 // Create the driver, from the HAL.
29 let irq = interrupt::take!(OTG_FS);
30 let mut ep_out_buffer = [0u8; 256]; 33 let mut ep_out_buffer = [0u8; 256];
31 let driver = Driver::new_fs(p.USB_OTG_FS, irq, p.PA12, p.PA11, &mut ep_out_buffer); 34 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer);
32 35
33 // Create embassy-usb Config 36 // Create embassy-usb Config
34 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 37 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs
index acbc60c87..326e4be85 100644
--- a/examples/stm32wb/src/bin/tl_mbox.rs
+++ b/examples/stm32wb/src/bin/tl_mbox.rs
@@ -4,12 +4,17 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::interrupt;
8use embassy_stm32::ipcc::{Config, Ipcc}; 7use embassy_stm32::ipcc::{Config, Ipcc};
9use embassy_stm32::tl_mbox::TlMbox; 8use embassy_stm32::tl_mbox::TlMbox;
9use embassy_stm32::{bind_interrupts, tl_mbox};
10use embassy_time::{Duration, Timer}; 10use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs{
14 IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler;
15 IPCC_C1_TX => tl_mbox::TransmitInterruptHandler;
16});
17
13#[embassy_executor::main] 18#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
15 /* 20 /*
@@ -42,10 +47,7 @@ async fn main(_spawner: Spawner) {
42 let config = Config::default(); 47 let config = Config::default();
43 let mut ipcc = Ipcc::new(p.IPCC, config); 48 let mut ipcc = Ipcc::new(p.IPCC, config);
44 49
45 let rx_irq = interrupt::take!(IPCC_C1_RX); 50 let mbox = TlMbox::init(&mut ipcc, Irqs);
46 let tx_irq = interrupt::take!(IPCC_C1_TX);
47
48 let mbox = TlMbox::init(&mut ipcc, rx_irq, tx_irq);
49 51
50 loop { 52 loop {
51 let wireless_fw_info = mbox.wireless_fw_info(); 53 let wireless_fw_info = mbox.wireless_fw_info();
diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
index 1008e1e41..7a69f26b7 100644
--- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
@@ -4,11 +4,16 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::interrupt;
8use embassy_stm32::ipcc::{Config, Ipcc}; 7use embassy_stm32::ipcc::{Config, Ipcc};
9use embassy_stm32::tl_mbox::TlMbox; 8use embassy_stm32::tl_mbox::TlMbox;
9use embassy_stm32::{bind_interrupts, tl_mbox};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs{
13 IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler;
14 IPCC_C1_TX => tl_mbox::TransmitInterruptHandler;
15});
16
12#[embassy_executor::main] 17#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 18async fn main(_spawner: Spawner) {
14 /* 19 /*
@@ -41,10 +46,7 @@ async fn main(_spawner: Spawner) {
41 let config = Config::default(); 46 let config = Config::default();
42 let mut ipcc = Ipcc::new(p.IPCC, config); 47 let mut ipcc = Ipcc::new(p.IPCC, config);
43 48
44 let rx_irq = interrupt::take!(IPCC_C1_RX); 49 let mbox = TlMbox::init(&mut ipcc, Irqs);
45 let tx_irq = interrupt::take!(IPCC_C1_TX);
46
47 let mbox = TlMbox::init(&mut ipcc, rx_irq, tx_irq);
48 50
49 // initialize ble stack, does not return a response 51 // initialize ble stack, does not return a response
50 mbox.shci_ble_init(&mut ipcc, Default::default()); 52 mbox.shci_ble_init(&mut ipcc, Default::default());
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
index 1a271b2f2..e179c5ca1 100644
--- a/examples/stm32wl/src/bin/lora_lorawan.rs
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -7,12 +7,12 @@
7 7
8use defmt::info; 8use defmt::info;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_lora::iv::Stm32wlInterfaceVariant; 10use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
11use embassy_lora::LoraTimer; 11use embassy_lora::LoraTimer;
12use embassy_stm32::gpio::{Level, Output, Pin, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pin, Speed};
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
14use embassy_stm32::spi::Spi; 14use embassy_stm32::spi::Spi;
15use embassy_stm32::{interrupt, into_ref, pac, Peripheral}; 15use embassy_stm32::{bind_interrupts, pac};
16use embassy_time::Delay; 16use embassy_time::Delay;
17use lora_phy::mod_params::*; 17use lora_phy::mod_params::*;
18use lora_phy::sx1261_2::SX1261_2; 18use lora_phy::sx1261_2::SX1261_2;
@@ -24,6 +24,10 @@ use {defmt_rtt as _, panic_probe as _};
24 24
25const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region 25const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region
26 26
27bind_interrupts!(struct Irqs{
28 SUBGHZ_RADIO => InterruptHandler;
29});
30
27#[embassy_executor::main] 31#[embassy_executor::main]
28async fn main(_spawner: Spawner) { 32async fn main(_spawner: Spawner) {
29 let mut config = embassy_stm32::Config::default(); 33 let mut config = embassy_stm32::Config::default();
@@ -35,13 +39,11 @@ async fn main(_spawner: Spawner) {
35 39
36 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 40 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
37 41
38 let irq = interrupt::take!(SUBGHZ_RADIO);
39 into_ref!(irq);
40 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx 42 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx
41 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High); 43 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High);
42 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High); 44 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High);
43 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High); 45 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High);
44 let iv = Stm32wlInterfaceVariant::new(irq, None, Some(ctrl2)).unwrap(); 46 let iv = Stm32wlInterfaceVariant::new(Irqs, None, Some(ctrl2)).unwrap();
45 47
46 let mut delay = Delay; 48 let mut delay = Delay;
47 49
diff --git a/examples/stm32wl/src/bin/lora_p2p_receive.rs b/examples/stm32wl/src/bin/lora_p2p_receive.rs
index 5e80e8f6a..d3f051b1c 100644
--- a/examples/stm32wl/src/bin/lora_p2p_receive.rs
+++ b/examples/stm32wl/src/bin/lora_p2p_receive.rs
@@ -7,10 +7,10 @@
7 7
8use defmt::info; 8use defmt::info;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_lora::iv::Stm32wlInterfaceVariant; 10use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
11use embassy_stm32::bind_interrupts;
11use embassy_stm32::gpio::{Level, Output, Pin, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pin, Speed};
12use embassy_stm32::spi::Spi; 13use embassy_stm32::spi::Spi;
13use embassy_stm32::{interrupt, into_ref, Peripheral};
14use embassy_time::{Delay, Duration, Timer}; 14use embassy_time::{Delay, Duration, Timer};
15use lora_phy::mod_params::*; 15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 16use lora_phy::sx1261_2::SX1261_2;
@@ -19,6 +19,10 @@ use {defmt_rtt as _, panic_probe as _};
19 19
20const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region 20const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
21 21
22bind_interrupts!(struct Irqs{
23 SUBGHZ_RADIO => InterruptHandler;
24});
25
22#[embassy_executor::main] 26#[embassy_executor::main]
23async fn main(_spawner: Spawner) { 27async fn main(_spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default(); 28 let mut config = embassy_stm32::Config::default();
@@ -27,13 +31,11 @@ async fn main(_spawner: Spawner) {
27 31
28 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 32 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
29 33
30 let irq = interrupt::take!(SUBGHZ_RADIO);
31 into_ref!(irq);
32 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx 34 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx
33 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High); 35 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High);
34 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High); 36 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High);
35 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High); 37 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High);
36 let iv = Stm32wlInterfaceVariant::new(irq, None, Some(ctrl2)).unwrap(); 38 let iv = Stm32wlInterfaceVariant::new(Irqs, None, Some(ctrl2)).unwrap();
37 39
38 let mut delay = Delay; 40 let mut delay = Delay;
39 41
diff --git a/examples/stm32wl/src/bin/lora_p2p_send.rs b/examples/stm32wl/src/bin/lora_p2p_send.rs
index e22c714bd..fc5205c85 100644
--- a/examples/stm32wl/src/bin/lora_p2p_send.rs
+++ b/examples/stm32wl/src/bin/lora_p2p_send.rs
@@ -7,10 +7,10 @@
7 7
8use defmt::info; 8use defmt::info;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_lora::iv::Stm32wlInterfaceVariant; 10use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
11use embassy_stm32::bind_interrupts;
11use embassy_stm32::gpio::{Level, Output, Pin, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pin, Speed};
12use embassy_stm32::spi::Spi; 13use embassy_stm32::spi::Spi;
13use embassy_stm32::{interrupt, into_ref, Peripheral};
14use embassy_time::Delay; 14use embassy_time::Delay;
15use lora_phy::mod_params::*; 15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 16use lora_phy::sx1261_2::SX1261_2;
@@ -19,6 +19,10 @@ use {defmt_rtt as _, panic_probe as _};
19 19
20const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region 20const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
21 21
22bind_interrupts!(struct Irqs{
23 SUBGHZ_RADIO => InterruptHandler;
24});
25
22#[embassy_executor::main] 26#[embassy_executor::main]
23async fn main(_spawner: Spawner) { 27async fn main(_spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default(); 28 let mut config = embassy_stm32::Config::default();
@@ -27,13 +31,11 @@ async fn main(_spawner: Spawner) {
27 31
28 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 32 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
29 33
30 let irq = interrupt::take!(SUBGHZ_RADIO);
31 into_ref!(irq);
32 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx 34 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx
33 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High); 35 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High);
34 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High); 36 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High);
35 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High); 37 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High);
36 let iv = Stm32wlInterfaceVariant::new(irq, None, Some(ctrl2)).unwrap(); 38 let iv = Stm32wlInterfaceVariant::new(Irqs, None, Some(ctrl2)).unwrap();
37 39
38 let mut delay = Delay; 40 let mut delay = Delay;
39 41
diff --git a/examples/stm32wl/src/bin/uart_async.rs b/examples/stm32wl/src/bin/uart_async.rs
index ac8766af6..07b0f9d2c 100644
--- a/examples/stm32wl/src/bin/uart_async.rs
+++ b/examples/stm32wl/src/bin/uart_async.rs
@@ -4,10 +4,15 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::interrupt; 7use embassy_stm32::usart::{Config, InterruptHandler, Uart};
8use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::{bind_interrupts, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs{
12 USART1 => InterruptHandler<peripherals::USART1>;
13 LPUART1 => InterruptHandler<peripherals::LPUART1>;
14});
15
11/* 16/*
12Pass Incoming data from LPUART1 to USART1 17Pass Incoming data from LPUART1 to USART1
13Example is written for the LoRa-E5 mini v1.0, 18Example is written for the LoRa-E5 mini v1.0,
@@ -28,12 +33,10 @@ async fn main(_spawner: Spawner) {
28 config2.baudrate = 9600; 33 config2.baudrate = 9600;
29 34
30 //RX/TX connected to USB/UART Bridge on LoRa-E5 mini v1.0 35 //RX/TX connected to USB/UART Bridge on LoRa-E5 mini v1.0
31 let irq = interrupt::take!(USART1); 36 let mut usart1 = Uart::new(p.USART1, p.PB7, p.PB6, Irqs, p.DMA1_CH3, p.DMA1_CH4, config1);
32 let mut usart1 = Uart::new(p.USART1, p.PB7, p.PB6, irq, p.DMA1_CH3, p.DMA1_CH4, config1);
33 37
34 //RX1/TX1 (LPUART) on LoRa-E5 mini v1.0 38 //RX1/TX1 (LPUART) on LoRa-E5 mini v1.0
35 let irq = interrupt::take!(LPUART1); 39 let mut usart2 = Uart::new(p.LPUART1, p.PC0, p.PC1, Irqs, p.DMA1_CH5, p.DMA1_CH6, config2);
36 let mut usart2 = Uart::new(p.LPUART1, p.PC0, p.PC1, irq, p.DMA1_CH5, p.DMA1_CH6, config2);
37 40
38 unwrap!(usart1.write(b"Hello Embassy World!\r\n").await); 41 unwrap!(usart1.write(b"Hello Embassy World!\r\n").await);
39 unwrap!(usart2.write(b"Hello Embassy World!\r\n").await); 42 unwrap!(usart2.write(b"Hello Embassy World!\r\n").await);
diff --git a/tests/stm32/src/bin/sdmmc.rs b/tests/stm32/src/bin/sdmmc.rs
index c4e50cb4a..7d96cf41e 100644
--- a/tests/stm32/src/bin/sdmmc.rs
+++ b/tests/stm32/src/bin/sdmmc.rs
@@ -7,9 +7,13 @@ use defmt::{assert_eq, *};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; 8use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
9use embassy_stm32::time::mhz; 9use embassy_stm32::time::mhz;
10use embassy_stm32::{interrupt, Config}; 10use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs {
14 SDIO => sdmmc::InterruptHandler<peripherals::SDIO>;
15});
16
13#[embassy_executor::main] 17#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 18async fn main(_spawner: Spawner) {
15 info!("Hello World!"); 19 info!("Hello World!");
@@ -20,17 +24,8 @@ async fn main(_spawner: Spawner) {
20 let p = embassy_stm32::init(config); 24 let p = embassy_stm32::init(config);
21 25
22 #[cfg(feature = "stm32f429zi")] 26 #[cfg(feature = "stm32f429zi")]
23 let (mut sdmmc, mut irq, mut dma, mut clk, mut cmd, mut d0, mut d1, mut d2, mut d3) = ( 27 let (mut sdmmc, mut dma, mut clk, mut cmd, mut d0, mut d1, mut d2, mut d3) =
24 p.SDIO, 28 (p.SDIO, p.DMA2_CH3, p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11);
25 interrupt::take!(SDIO),
26 p.DMA2_CH3,
27 p.PC12,
28 p.PD2,
29 p.PC8,
30 p.PC9,
31 p.PC10,
32 p.PC11,
33 );
34 29
35 // Arbitrary block index 30 // Arbitrary block index
36 let block_idx = 16; 31 let block_idx = 16;
@@ -48,7 +43,7 @@ async fn main(_spawner: Spawner) {
48 info!("initializing in 4-bit mode..."); 43 info!("initializing in 4-bit mode...");
49 let mut s = Sdmmc::new_4bit( 44 let mut s = Sdmmc::new_4bit(
50 &mut sdmmc, 45 &mut sdmmc,
51 &mut irq, 46 Irqs,
52 &mut dma, 47 &mut dma,
53 &mut clk, 48 &mut clk,
54 &mut cmd, 49 &mut cmd,
@@ -97,7 +92,7 @@ async fn main(_spawner: Spawner) {
97 info!("initializing in 1-bit mode..."); 92 info!("initializing in 1-bit mode...");
98 let mut s = Sdmmc::new_1bit( 93 let mut s = Sdmmc::new_1bit(
99 &mut sdmmc, 94 &mut sdmmc,
100 &mut irq, 95 Irqs,
101 &mut dma, 96 &mut dma,
102 &mut clk, 97 &mut clk,
103 &mut cmd, 98 &mut cmd,
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs
index 0749f8406..415c7afa9 100644
--- a/tests/stm32/src/bin/usart.rs
+++ b/tests/stm32/src/bin/usart.rs
@@ -7,11 +7,37 @@ mod example_common;
7use defmt::assert_eq; 7use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Error, Uart}; 10use embassy_stm32::usart::{Config, Error, Uart};
11use embassy_stm32::{bind_interrupts, peripherals, usart};
12use embassy_time::{Duration, Instant}; 12use embassy_time::{Duration, Instant};
13use example_common::*; 13use example_common::*;
14 14
15#[cfg(any(
16 feature = "stm32f103c8",
17 feature = "stm32g491re",
18 feature = "stm32g071rb",
19 feature = "stm32h755zi",
20 feature = "stm32c031c6",
21))]
22bind_interrupts!(struct Irqs {
23 USART1 => usart::InterruptHandler<peripherals::USART1>;
24});
25
26#[cfg(feature = "stm32u585ai")]
27bind_interrupts!(struct Irqs {
28 USART3 => usart::InterruptHandler<peripherals::USART3>;
29});
30
31#[cfg(feature = "stm32f429zi")]
32bind_interrupts!(struct Irqs {
33 USART6 => usart::InterruptHandler<peripherals::USART6>;
34});
35
36#[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))]
37bind_interrupts!(struct Irqs {
38 LPUART1 => usart::InterruptHandler<peripherals::LPUART1>;
39});
40
15#[embassy_executor::main] 41#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 42async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(config()); 43 let p = embassy_stm32::init(config());
@@ -20,27 +46,27 @@ async fn main(_spawner: Spawner) {
20 // Arduino pins D0 and D1 46 // Arduino pins D0 and D1
21 // They're connected together with a 1K resistor. 47 // They're connected together with a 1K resistor.
22 #[cfg(feature = "stm32f103c8")] 48 #[cfg(feature = "stm32f103c8")]
23 let (mut tx, mut rx, mut usart, mut irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1)); 49 let (mut tx, mut rx, mut usart) = (p.PA9, p.PA10, p.USART1);
24 #[cfg(feature = "stm32g491re")] 50 #[cfg(feature = "stm32g491re")]
25 let (mut tx, mut rx, mut usart, mut irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1)); 51 let (mut tx, mut rx, mut usart) = (p.PC4, p.PC5, p.USART1);
26 #[cfg(feature = "stm32g071rb")] 52 #[cfg(feature = "stm32g071rb")]
27 let (mut tx, mut rx, mut usart, mut irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1)); 53 let (mut tx, mut rx, mut usart) = (p.PC4, p.PC5, p.USART1);
28 #[cfg(feature = "stm32f429zi")] 54 #[cfg(feature = "stm32f429zi")]
29 let (mut tx, mut rx, mut usart, mut irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6)); 55 let (mut tx, mut rx, mut usart) = (p.PG14, p.PG9, p.USART6);
30 #[cfg(feature = "stm32wb55rg")] 56 #[cfg(feature = "stm32wb55rg")]
31 let (mut tx, mut rx, mut usart, mut irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1)); 57 let (mut tx, mut rx, mut usart) = (p.PA2, p.PA3, p.LPUART1);
32 #[cfg(feature = "stm32h755zi")] 58 #[cfg(feature = "stm32h755zi")]
33 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1)); 59 let (mut tx, mut rx, mut usart) = (p.PB6, p.PB7, p.USART1);
34 #[cfg(feature = "stm32u585ai")] 60 #[cfg(feature = "stm32u585ai")]
35 let (mut tx, mut rx, mut usart, mut irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3)); 61 let (mut tx, mut rx, mut usart) = (p.PD8, p.PD9, p.USART3);
36 #[cfg(feature = "stm32h563zi")] 62 #[cfg(feature = "stm32h563zi")]
37 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.LPUART1, interrupt::take!(LPUART1)); 63 let (mut tx, mut rx, mut usart) = (p.PB6, p.PB7, p.LPUART1);
38 #[cfg(feature = "stm32c031c6")] 64 #[cfg(feature = "stm32c031c6")]
39 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1)); 65 let (mut tx, mut rx, mut usart) = (p.PB6, p.PB7, p.USART1);
40 66
41 { 67 {
42 let config = Config::default(); 68 let config = Config::default();
43 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config); 69 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, Irqs, NoDma, NoDma, config);
44 70
45 // We can't send too many bytes, they have to fit in the FIFO. 71 // We can't send too many bytes, they have to fit in the FIFO.
46 // This is because we aren't sending+receiving at the same time. 72 // This is because we aren't sending+receiving at the same time.
@@ -56,7 +82,7 @@ async fn main(_spawner: Spawner) {
56 // Test error handling with with an overflow error 82 // Test error handling with with an overflow error
57 { 83 {
58 let config = Config::default(); 84 let config = Config::default();
59 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config); 85 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, Irqs, NoDma, NoDma, config);
60 86
61 // Send enough bytes to fill the RX FIFOs off all USART versions. 87 // Send enough bytes to fill the RX FIFOs off all USART versions.
62 let data = [0xC0, 0xDE, 0x12, 0x23, 0x34]; 88 let data = [0xC0, 0xDE, 0x12, 0x23, 0x34];
@@ -90,7 +116,7 @@ async fn main(_spawner: Spawner) {
90 116
91 let mut config = Config::default(); 117 let mut config = Config::default();
92 config.baudrate = baudrate; 118 config.baudrate = baudrate;
93 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config); 119 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, Irqs, NoDma, NoDma, config);
94 120
95 let n = (baudrate as usize / 100).max(64); 121 let n = (baudrate as usize / 100).max(64);
96 122
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index 62444f0a8..7f002b97e 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -7,10 +7,36 @@ mod example_common;
7use defmt::assert_eq; 7use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_futures::join::join; 9use embassy_futures::join::join;
10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
11use embassy_stm32::{bind_interrupts, peripherals, usart};
12use example_common::*; 12use example_common::*;
13 13
14#[cfg(any(
15 feature = "stm32f103c8",
16 feature = "stm32g491re",
17 feature = "stm32g071rb",
18 feature = "stm32h755zi",
19 feature = "stm32c031c6",
20))]
21bind_interrupts!(struct Irqs {
22 USART1 => usart::InterruptHandler<peripherals::USART1>;
23});
24
25#[cfg(feature = "stm32u585ai")]
26bind_interrupts!(struct Irqs {
27 USART3 => usart::InterruptHandler<peripherals::USART3>;
28});
29
30#[cfg(feature = "stm32f429zi")]
31bind_interrupts!(struct Irqs {
32 USART6 => usart::InterruptHandler<peripherals::USART6>;
33});
34
35#[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))]
36bind_interrupts!(struct Irqs {
37 LPUART1 => usart::InterruptHandler<peripherals::LPUART1>;
38});
39
14#[embassy_executor::main] 40#[embassy_executor::main]
15async fn main(_spawner: Spawner) { 41async fn main(_spawner: Spawner) {
16 let p = embassy_stm32::init(config()); 42 let p = embassy_stm32::init(config());
@@ -19,62 +45,23 @@ async fn main(_spawner: Spawner) {
19 // Arduino pins D0 and D1 45 // Arduino pins D0 and D1
20 // They're connected together with a 1K resistor. 46 // They're connected together with a 1K resistor.
21 #[cfg(feature = "stm32f103c8")] 47 #[cfg(feature = "stm32f103c8")]
22 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 48 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, Irqs, p.DMA1_CH4, p.DMA1_CH5);
23 p.PA9,
24 p.PA10,
25 p.USART1,
26 interrupt::take!(USART1),
27 p.DMA1_CH4,
28 p.DMA1_CH5,
29 );
30 #[cfg(feature = "stm32g491re")] 49 #[cfg(feature = "stm32g491re")]
31 let (tx, rx, usart, irq, tx_dma, rx_dma) = 50 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, Irqs, p.DMA1_CH1, p.DMA1_CH2);
32 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
33 #[cfg(feature = "stm32g071rb")] 51 #[cfg(feature = "stm32g071rb")]
34 let (tx, rx, usart, irq, tx_dma, rx_dma) = 52 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, Irqs, p.DMA1_CH1, p.DMA1_CH2);
35 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
36 #[cfg(feature = "stm32f429zi")] 53 #[cfg(feature = "stm32f429zi")]
37 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 54 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, Irqs, p.DMA2_CH6, p.DMA2_CH1);
38 p.PG14,
39 p.PG9,
40 p.USART6,
41 interrupt::take!(USART6),
42 p.DMA2_CH6,
43 p.DMA2_CH1,
44 );
45 #[cfg(feature = "stm32wb55rg")] 55 #[cfg(feature = "stm32wb55rg")]
46 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 56 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PA2, p.PA3, p.LPUART1, Irqs, p.DMA1_CH1, p.DMA1_CH2);
47 p.PA2,
48 p.PA3,
49 p.LPUART1,
50 interrupt::take!(LPUART1),
51 p.DMA1_CH1,
52 p.DMA1_CH2,
53 );
54 #[cfg(feature = "stm32h755zi")] 57 #[cfg(feature = "stm32h755zi")]
55 let (tx, rx, usart, irq, tx_dma, rx_dma) = 58 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, Irqs, p.DMA1_CH0, p.DMA1_CH1);
56 (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH0, p.DMA1_CH1);
57 #[cfg(feature = "stm32u585ai")] 59 #[cfg(feature = "stm32u585ai")]
58 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 60 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PD8, p.PD9, p.USART3, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1);
59 p.PD8,
60 p.PD9,
61 p.USART3,
62 interrupt::take!(USART3),
63 p.GPDMA1_CH0,
64 p.GPDMA1_CH1,
65 );
66 #[cfg(feature = "stm32h563zi")] 61 #[cfg(feature = "stm32h563zi")]
67 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 62 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PB6, p.PB7, p.LPUART1, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1);
68 p.PB6,
69 p.PB7,
70 p.LPUART1,
71 interrupt::take!(LPUART1),
72 p.GPDMA1_CH0,
73 p.GPDMA1_CH1,
74 );
75 #[cfg(feature = "stm32c031c6")] 63 #[cfg(feature = "stm32c031c6")]
76 let (tx, rx, usart, irq, tx_dma, rx_dma) = 64 let (tx, rx, usart, irq, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, Irqs, p.DMA1_CH1, p.DMA1_CH2);
77 (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
78 65
79 let config = Config::default(); 66 let config = Config::default();
80 let usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config); 67 let usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config);
diff --git a/tests/stm32/src/bin/usart_rx_ringbuffered.rs b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
index 9d75dbe55..3a34773f7 100644
--- a/tests/stm32/src/bin/usart_rx_ringbuffered.rs
+++ b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
@@ -8,13 +8,40 @@
8mod example_common; 8mod example_common;
9use defmt::{assert_eq, panic}; 9use defmt::{assert_eq, panic};
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_stm32::interrupt;
12use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx}; 11use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx};
12use embassy_stm32::{bind_interrupts, peripherals, usart};
13use embassy_time::{Duration, Timer}; 13use embassy_time::{Duration, Timer};
14use example_common::*; 14use example_common::*;
15use rand_chacha::ChaCha8Rng; 15use rand_chacha::ChaCha8Rng;
16use rand_core::{RngCore, SeedableRng}; 16use rand_core::{RngCore, SeedableRng};
17 17
18#[cfg(any(
19 feature = "stm32f103c8",
20 feature = "stm32g491re",
21 feature = "stm32g071rb",
22 feature = "stm32h755zi",
23 feature = "stm32c031c6",
24))]
25bind_interrupts!(struct Irqs {
26 USART1 => usart::InterruptHandler<peripherals::USART1>;
27});
28
29#[cfg(feature = "stm32u585ai")]
30bind_interrupts!(struct Irqs {
31 USART3 => usart::InterruptHandler<peripherals::USART3>;
32});
33
34#[cfg(feature = "stm32f429zi")]
35bind_interrupts!(struct Irqs {
36 USART1 => usart::InterruptHandler<peripherals::USART1>;
37 USART6 => usart::InterruptHandler<peripherals::USART6>;
38});
39
40#[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))]
41bind_interrupts!(struct Irqs {
42 LPUART1 => usart::InterruptHandler<peripherals::LPUART1>;
43});
44
18#[cfg(feature = "stm32f103c8")] 45#[cfg(feature = "stm32f103c8")]
19mod board { 46mod board {
20 pub type Uart = embassy_stm32::peripherals::USART1; 47 pub type Uart = embassy_stm32::peripherals::USART1;
@@ -74,53 +101,21 @@ async fn main(spawner: Spawner) {
74 // Arduino pins D0 and D1 101 // Arduino pins D0 and D1
75 // They're connected together with a 1K resistor. 102 // They're connected together with a 1K resistor.
76 #[cfg(feature = "stm32f103c8")] 103 #[cfg(feature = "stm32f103c8")]
77 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 104 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH4, p.DMA1_CH5);
78 p.PA9,
79 p.PA10,
80 p.USART1,
81 interrupt::take!(USART1),
82 p.DMA1_CH4,
83 p.DMA1_CH5,
84 );
85 #[cfg(feature = "stm32g491re")] 105 #[cfg(feature = "stm32g491re")]
86 let (tx, rx, usart, irq, tx_dma, rx_dma) = 106 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
87 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
88 #[cfg(feature = "stm32g071rb")] 107 #[cfg(feature = "stm32g071rb")]
89 let (tx, rx, usart, irq, tx_dma, rx_dma) = 108 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
90 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
91 #[cfg(feature = "stm32f429zi")] 109 #[cfg(feature = "stm32f429zi")]
92 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 110 let (tx, rx, usart, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, p.DMA2_CH6, p.DMA2_CH1);
93 p.PG14,
94 p.PG9,
95 p.USART6,
96 interrupt::take!(USART6),
97 p.DMA2_CH6,
98 p.DMA2_CH1,
99 );
100 #[cfg(feature = "stm32wb55rg")] 111 #[cfg(feature = "stm32wb55rg")]
101 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 112 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA2, p.PA3, p.LPUART1, p.DMA1_CH1, p.DMA1_CH2);
102 p.PA2,
103 p.PA3,
104 p.LPUART1,
105 interrupt::take!(LPUART1),
106 p.DMA1_CH1,
107 p.DMA1_CH2,
108 );
109 #[cfg(feature = "stm32h755zi")] 113 #[cfg(feature = "stm32h755zi")]
110 let (tx, rx, usart, irq, tx_dma, rx_dma) = 114 let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH0, p.DMA1_CH1);
111 (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH0, p.DMA1_CH1);
112 #[cfg(feature = "stm32u585ai")] 115 #[cfg(feature = "stm32u585ai")]
113 let (tx, rx, usart, irq, tx_dma, rx_dma) = ( 116 let (tx, rx, usart, tx_dma, rx_dma) = (p.PD8, p.PD9, p.USART3, p.GPDMA1_CH0, p.GPDMA1_CH1);
114 p.PD8,
115 p.PD9,
116 p.USART3,
117 interrupt::take!(USART3),
118 p.GPDMA1_CH0,
119 p.GPDMA1_CH1,
120 );
121 #[cfg(feature = "stm32c031c6")] 117 #[cfg(feature = "stm32c031c6")]
122 let (tx, rx, usart, irq, tx_dma, rx_dma) = 118 let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
123 (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
124 119
125 // To run this test, use the saturating_serial test utility to saturate the serial port 120 // To run this test, use the saturating_serial test utility to saturate the serial port
126 121
@@ -132,7 +127,7 @@ async fn main(spawner: Spawner) {
132 config.stop_bits = StopBits::STOP1; 127 config.stop_bits = StopBits::STOP1;
133 config.parity = Parity::ParityNone; 128 config.parity = Parity::ParityNone;
134 129
135 let usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config); 130 let usart = Uart::new(usart, rx, tx, Irqs, tx_dma, rx_dma, config);
136 let (tx, rx) = usart.split(); 131 let (tx, rx) = usart.split();
137 static mut DMA_BUF: [u8; DMA_BUF_SIZE] = [0; DMA_BUF_SIZE]; 132 static mut DMA_BUF: [u8; DMA_BUF_SIZE] = [0; DMA_BUF_SIZE];
138 let dma_buf = unsafe { DMA_BUF.as_mut() }; 133 let dma_buf = unsafe { DMA_BUF.as_mut() };