diff options
86 files changed, 1865 insertions, 916 deletions
| @@ -143,6 +143,7 @@ cargo batch \ | |||
| 143 | $BUILD_EXTRA | 143 | $BUILD_EXTRA |
| 144 | 144 | ||
| 145 | 145 | ||
| 146 | |||
| 146 | function run_elf { | 147 | function 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] |
| 15 | std = [] | 15 | std = [] |
| 16 | # Enable nightly-only features | 16 | # Enable nightly-only features |
| 17 | nightly = ["embedded-hal-async", "embedded-storage-async"] | 17 | nightly = ["embassy-futures", "embedded-hal-async", "embedded-storage-async"] |
| 18 | 18 | ||
| 19 | [dependencies] | 19 | [dependencies] |
| 20 | embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true } | ||
| 20 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | 21 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } |
| 21 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } | 22 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ |
| 23 | "unproven", | ||
| 24 | ] } | ||
| 22 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 25 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } |
| 23 | embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true } | 26 | embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true } |
| 24 | embedded-storage = "0.3.0" | 27 | embedded-storage = "0.3.0" |
| @@ -26,3 +29,6 @@ embedded-storage-async = { version = "0.4.0", optional = true } | |||
| 26 | nb = "1.0.0" | 29 | nb = "1.0.0" |
| 27 | 30 | ||
| 28 | defmt = { version = "0.3", optional = true } | 31 | defmt = { version = "0.3", optional = true } |
| 32 | |||
| 33 | [dev-dependencies] | ||
| 34 | futures-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 | |||
| 3 | use embedded_hal_02::{blocking, serial}; | 1 | use 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 | |||
| 3 | mod blocking_async; | ||
| 4 | mod yielding_async; | ||
| 5 | |||
| 6 | pub use blocking_async::BlockingAsync; | ||
| 7 | pub 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 @@ | |||
| 1 | use 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. | ||
| 7 | pub struct YieldingAsync<T> { | ||
| 8 | wrapped: T, | ||
| 9 | } | ||
| 10 | |||
| 11 | impl<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 | // | ||
| 21 | impl<T> embedded_hal_1::i2c::ErrorType for YieldingAsync<T> | ||
| 22 | where | ||
| 23 | T: embedded_hal_1::i2c::ErrorType, | ||
| 24 | { | ||
| 25 | type Error = T::Error; | ||
| 26 | } | ||
| 27 | |||
| 28 | impl<T> embedded_hal_async::i2c::I2c for YieldingAsync<T> | ||
| 29 | where | ||
| 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 | |||
| 65 | impl<T> embedded_hal_async::spi::ErrorType for YieldingAsync<T> | ||
| 66 | where | ||
| 67 | T: embedded_hal_async::spi::ErrorType, | ||
| 68 | { | ||
| 69 | type Error = T::Error; | ||
| 70 | } | ||
| 71 | |||
| 72 | impl<T> embedded_hal_async::spi::SpiBus<u8> for YieldingAsync<T> | ||
| 73 | where | ||
| 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 | |||
| 89 | impl<T> embedded_hal_async::spi::SpiBusFlush for YieldingAsync<T> | ||
| 90 | where | ||
| 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 | |||
| 100 | impl<T> embedded_hal_async::spi::SpiBusWrite<u8> for YieldingAsync<T> | ||
| 101 | where | ||
| 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 | |||
| 111 | impl<T> embedded_hal_async::spi::SpiBusRead<u8> for YieldingAsync<T> | ||
| 112 | where | ||
| 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 | /// | ||
| 125 | impl<T: embedded_storage::nor_flash::ErrorType> embedded_storage::nor_flash::ErrorType for YieldingAsync<T> { | ||
| 126 | type Error = T::Error; | ||
| 127 | } | ||
| 128 | |||
| 129 | impl<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 | |||
| 144 | impl<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)] | ||
| 166 | mod 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-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")] |
| 2 | use embassy_stm32::interrupt; | ||
| 3 | #[cfg(feature = "stm32wl")] | ||
| 2 | use embassy_stm32::interrupt::*; | 4 | use embassy_stm32::interrupt::*; |
| 3 | #[cfg(feature = "stm32wl")] | 5 | #[cfg(feature = "stm32wl")] |
| 4 | use embassy_stm32::{pac, PeripheralRef}; | 6 | use embassy_stm32::pac; |
| 5 | #[cfg(feature = "stm32wl")] | 7 | #[cfg(feature = "stm32wl")] |
| 6 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 7 | #[cfg(feature = "stm32wl")] | 9 | #[cfg(feature = "stm32wl")] |
| @@ -13,47 +15,51 @@ use lora_phy::mod_params::RadioError::*; | |||
| 13 | use lora_phy::mod_params::{BoardType, RadioError}; | 15 | use lora_phy::mod_params::{BoardType, RadioError}; |
| 14 | use lora_phy::mod_traits::InterfaceVariant; | 16 | use lora_phy::mod_traits::InterfaceVariant; |
| 15 | 17 | ||
| 18 | /// Interrupt handler. | ||
| 19 | #[cfg(feature = "stm32wl")] | ||
| 20 | pub struct InterruptHandler {} | ||
| 21 | |||
| 22 | #[cfg(feature = "stm32wl")] | ||
| 23 | impl 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")] |
| 17 | static IRQ_SIGNAL: Signal<CriticalSectionRawMutex, ()> = Signal::new(); | 31 | static 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 |
| 21 | pub struct Stm32wlInterfaceVariant<'a, CTRL> { | 35 | pub 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")] |
| 29 | impl<'a, CTRL> Stm32wlInterfaceVariant<'a, CTRL> | 42 | impl<'a, CTRL> Stm32wlInterfaceVariant<CTRL> |
| 30 | where | 43 | where |
| 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")] |
| 56 | impl<CTRL> InterfaceVariant for Stm32wlInterfaceVariant<'_, CTRL> | 62 | impl<CTRL> InterfaceVariant for Stm32wlInterfaceVariant<CTRL> |
| 57 | where | 63 | where |
| 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 a00c6c416..540981727 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -206,6 +206,7 @@ fn main() { | |||
| 206 | erase_size: #erase_size, | 206 | erase_size: #erase_size, |
| 207 | write_size: #write_size, | 207 | write_size: #write_size, |
| 208 | erase_value: #erase_value, | 208 | erase_value: #erase_value, |
| 209 | _ensure_internal: (), | ||
| 209 | }; | 210 | }; |
| 210 | }); | 211 | }); |
| 211 | 212 | ||
| @@ -420,6 +421,10 @@ fn main() { | |||
| 420 | (("spi", "SCK"), quote!(crate::spi::SckPin)), | 421 | (("spi", "SCK"), quote!(crate::spi::SckPin)), |
| 421 | (("spi", "MOSI"), quote!(crate::spi::MosiPin)), | 422 | (("spi", "MOSI"), quote!(crate::spi::MosiPin)), |
| 422 | (("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)), | ||
| 423 | (("i2c", "SDA"), quote!(crate::i2c::SdaPin)), | 428 | (("i2c", "SDA"), quote!(crate::i2c::SdaPin)), |
| 424 | (("i2c", "SCL"), quote!(crate::i2c::SclPin)), | 429 | (("i2c", "SCL"), quote!(crate::i2c::SclPin)), |
| 425 | (("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 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | ||
| 2 | use core::task::Poll; | 3 | use core::task::Poll; |
| 3 | 4 | ||
| 4 | use embassy_hal_common::{into_ref, PeripheralRef}; | 5 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| @@ -8,7 +9,31 @@ use crate::dma::Transfer; | |||
| 8 | use crate::gpio::sealed::AFType; | 9 | use crate::gpio::sealed::AFType; |
| 9 | use crate::gpio::Speed; | 10 | use crate::gpio::Speed; |
| 10 | use crate::interrupt::{Interrupt, InterruptExt}; | 11 | use crate::interrupt::{Interrupt, InterruptExt}; |
| 11 | use crate::Peripheral; | 12 | use crate::{interrupt, Peripheral}; |
| 13 | |||
| 14 | /// Interrupt handler. | ||
| 15 | pub struct InterruptHandler<T: Instance> { | ||
| 16 | _phantom: PhantomData<T>, | ||
| 17 | } | ||
| 18 | |||
| 19 | impl<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; | |||
| 11 | use embassy_net_driver::{Capabilities, LinkState}; | 11 | use embassy_net_driver::{Capabilities, LinkState}; |
| 12 | use embassy_sync::waitqueue::AtomicWaker; | 12 | use embassy_sync::waitqueue::AtomicWaker; |
| 13 | 13 | ||
| 14 | pub use self::_version::*; | 14 | pub use self::_version::{InterruptHandler, *}; |
| 15 | 15 | ||
| 16 | #[allow(unused)] | 16 | #[allow(unused)] |
| 17 | const MTU: usize = 1514; | 17 | const 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 | ||
| 6 | use core::sync::atomic::{fence, Ordering}; | 6 | use core::sync::atomic::{fence, Ordering}; |
| 7 | 7 | ||
| 8 | use embassy_cortex_m::interrupt::InterruptExt; | 8 | use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; |
| 9 | use embassy_hal_common::{into_ref, PeripheralRef}; | 9 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 10 | use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf}; | 10 | use 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))] |
| 20 | use crate::pac::SYSCFG; | 20 | use crate::pac::SYSCFG; |
| 21 | use crate::pac::{ETH, RCC}; | 21 | use crate::pac::{ETH, RCC}; |
| 22 | use crate::Peripheral; | 22 | use crate::{interrupt, Peripheral}; |
| 23 | |||
| 24 | /// Interrupt handler. | ||
| 25 | pub struct InterruptHandler {} | ||
| 26 | |||
| 27 | impl 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 | ||
| 24 | pub struct Ethernet<'d, T: Instance, P: PHY> { | 47 | pub 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 | ||
| 273 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { | 278 | unsafe 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 | ||
| 3 | use core::sync::atomic::{fence, Ordering}; | 3 | use core::sync::atomic::{fence, Ordering}; |
| 4 | 4 | ||
| 5 | use embassy_cortex_m::interrupt::InterruptExt; | 5 | use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; |
| 6 | use embassy_hal_common::{into_ref, PeripheralRef}; | 6 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 7 | 7 | ||
| 8 | pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; | 8 | pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; |
| @@ -10,7 +10,30 @@ use super::*; | |||
| 10 | use crate::gpio::sealed::{AFType, Pin as _}; | 10 | use crate::gpio::sealed::{AFType, Pin as _}; |
| 11 | use crate::gpio::{AnyPin, Speed}; | 11 | use crate::gpio::{AnyPin, Speed}; |
| 12 | use crate::pac::ETH; | 12 | use crate::pac::ETH; |
| 13 | use crate::Peripheral; | 13 | use crate::{interrupt, Peripheral}; |
| 14 | |||
| 15 | /// Interrupt handler. | ||
| 16 | pub struct InterruptHandler {} | ||
| 17 | |||
| 18 | impl 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 | ||
| 15 | const MTU: usize = 1514; // 14 Ethernet header + 1500 IP packet | 38 | const 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 | ||
| 244 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { | 249 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { |
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 6d7f55974..432c8a43b 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs | |||
| @@ -17,6 +17,7 @@ impl<'d> Flash<'d> { | |||
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | pub fn into_regions(self) -> FlashLayout<'d> { | 19 | pub fn into_regions(self) -> FlashLayout<'d> { |
| 20 | family::set_default_layout(); | ||
| 20 | FlashLayout::new(self.release()) | 21 | FlashLayout::new(self.release()) |
| 21 | } | 22 | } |
| 22 | 23 | ||
| @@ -25,11 +26,11 @@ impl<'d> Flash<'d> { | |||
| 25 | } | 26 | } |
| 26 | 27 | ||
| 27 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | 28 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { |
| 28 | unsafe { blocking_write(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } | 29 | unsafe { blocking_write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | 32 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { |
| 32 | unsafe { blocking_erase(FLASH_BASE as u32, from, to) } | 33 | unsafe { blocking_erase_sectored(FLASH_BASE as u32, from, to) } |
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | pub(crate) fn release(self) -> PeripheralRef<'d, crate::peripherals::FLASH> { | 36 | pub(crate) fn release(self) -> PeripheralRef<'d, crate::peripherals::FLASH> { |
| @@ -37,7 +38,7 @@ impl<'d> Flash<'d> { | |||
| 37 | } | 38 | } |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | 41 | pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { |
| 41 | if offset + bytes.len() as u32 > size { | 42 | if offset + bytes.len() as u32 > size { |
| 42 | return Err(Error::Size); | 43 | return Err(Error::Size); |
| 43 | } | 44 | } |
| @@ -48,7 +49,7 @@ fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result< | |||
| 48 | Ok(()) | 49 | Ok(()) |
| 49 | } | 50 | } |
| 50 | 51 | ||
| 51 | unsafe fn blocking_write(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { | 52 | pub(super) unsafe fn blocking_write_chunked(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { |
| 52 | if offset + bytes.len() as u32 > size { | 53 | if offset + bytes.len() as u32 > size { |
| 53 | return Err(Error::Size); | 54 | return Err(Error::Size); |
| 54 | } | 55 | } |
| @@ -81,7 +82,7 @@ unsafe fn blocking_write(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Res | |||
| 81 | Ok(()) | 82 | Ok(()) |
| 82 | } | 83 | } |
| 83 | 84 | ||
| 84 | unsafe fn blocking_erase(base: u32, from: u32, to: u32) -> Result<(), Error> { | 85 | pub(super) unsafe fn blocking_erase_sectored(base: u32, from: u32, to: u32) -> Result<(), Error> { |
| 85 | let start_address = base + from; | 86 | let start_address = base + from; |
| 86 | let end_address = base + to; | 87 | let end_address = base + to; |
| 87 | let regions = family::get_flash_regions(); | 88 | let regions = family::get_flash_regions(); |
| @@ -154,11 +155,11 @@ impl FlashRegion { | |||
| 154 | } | 155 | } |
| 155 | 156 | ||
| 156 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | 157 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { |
| 157 | unsafe { blocking_write(self.base, self.size, offset, bytes) } | 158 | unsafe { blocking_write_chunked(self.base, self.size, offset, bytes) } |
| 158 | } | 159 | } |
| 159 | 160 | ||
| 160 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | 161 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { |
| 161 | unsafe { blocking_erase(self.base, from, to) } | 162 | unsafe { blocking_erase_sectored(self.base, from, to) } |
| 162 | } | 163 | } |
| 163 | } | 164 | } |
| 164 | 165 | ||
| @@ -199,11 +200,11 @@ foreach_flash_region! { | |||
| 199 | } | 200 | } |
| 200 | 201 | ||
| 201 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | 202 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { |
| 202 | unsafe { blocking_write(self.0.base, self.0.size, offset, bytes) } | 203 | unsafe { blocking_write_chunked(self.0.base, self.0.size, offset, bytes) } |
| 203 | } | 204 | } |
| 204 | 205 | ||
| 205 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | 206 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { |
| 206 | unsafe { blocking_erase(self.0.base, from, to) } | 207 | unsafe { blocking_erase_sectored(self.0.base, from, to) } |
| 207 | } | 208 | } |
| 208 | } | 209 | } |
| 209 | 210 | ||
diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index 033afecd5..c6441ef16 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs | |||
| @@ -7,6 +7,8 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 7 | use crate::flash::Error; | 7 | use crate::flash::Error; |
| 8 | use crate::pac; | 8 | use crate::pac; |
| 9 | 9 | ||
| 10 | pub const fn set_default_layout() {} | ||
| 11 | |||
| 10 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 12 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 11 | &FLASH_REGIONS | 13 | &FLASH_REGIONS |
| 12 | } | 14 | } |
diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 10a09c42c..4c8172203 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs | |||
| @@ -7,6 +7,8 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 7 | use crate::flash::Error; | 7 | use crate::flash::Error; |
| 8 | use crate::pac; | 8 | use crate::pac; |
| 9 | 9 | ||
| 10 | pub const fn set_default_layout() {} | ||
| 11 | |||
| 10 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 12 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 11 | &FLASH_REGIONS | 13 | &FLASH_REGIONS |
| 12 | } | 14 | } |
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 60ac62c17..7f1c5f671 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs | |||
| @@ -11,8 +11,11 @@ mod alt_regions { | |||
| 11 | use embassy_hal_common::PeripheralRef; | 11 | use embassy_hal_common::PeripheralRef; |
| 12 | use stm32_metapac::FLASH_SIZE; | 12 | use stm32_metapac::FLASH_SIZE; |
| 13 | 13 | ||
| 14 | use crate::_generated::flash_regions::{BANK1_REGION1, BANK1_REGION2, BANK1_REGION3}; | 14 | use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; |
| 15 | use crate::flash::{Bank1Region1, Bank1Region2, Flash, FlashBank, FlashRegion}; | 15 | use crate::flash::{ |
| 16 | blocking_erase_sectored, blocking_read, blocking_write_chunked, Bank1Region1, Bank1Region2, Error, Flash, | ||
| 17 | FlashBank, FlashRegion, | ||
| 18 | }; | ||
| 16 | use crate::peripherals::FLASH; | 19 | use crate::peripherals::FLASH; |
| 17 | 20 | ||
| 18 | pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { | 21 | pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { |
| @@ -45,20 +48,19 @@ mod alt_regions { | |||
| 45 | &ALT_BANK2_REGION3, | 48 | &ALT_BANK2_REGION3, |
| 46 | ]; | 49 | ]; |
| 47 | 50 | ||
| 48 | pub type AltBank1Region1<'d> = Bank1Region1<'d>; | ||
| 49 | pub type AltBank1Region2<'d> = Bank1Region2<'d>; | ||
| 50 | pub struct AltBank1Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); | 51 | pub struct AltBank1Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); |
| 51 | pub struct AltBank2Region1<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); | 52 | pub struct AltBank2Region1<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); |
| 52 | pub struct AltBank2Region2<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); | 53 | pub struct AltBank2Region2<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); |
| 53 | pub struct AltBank2Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); | 54 | pub struct AltBank2Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); |
| 54 | 55 | ||
| 55 | pub struct AltFlashLayout<'d> { | 56 | pub struct AltFlashLayout<'d> { |
| 56 | pub bank1_region1: AltBank1Region1<'d>, | 57 | pub bank1_region1: Bank1Region1<'d>, |
| 57 | pub bank1_region2: AltBank1Region2<'d>, | 58 | pub bank1_region2: Bank1Region2<'d>, |
| 58 | pub bank1_region3: AltBank1Region3<'d>, | 59 | pub bank1_region3: AltBank1Region3<'d>, |
| 59 | pub bank2_region1: AltBank2Region1<'d>, | 60 | pub bank2_region1: AltBank2Region1<'d>, |
| 60 | pub bank2_region2: AltBank2Region2<'d>, | 61 | pub bank2_region2: AltBank2Region2<'d>, |
| 61 | pub bank2_region3: AltBank2Region3<'d>, | 62 | pub bank2_region3: AltBank2Region3<'d>, |
| 63 | pub otp_region: OTPRegion<'d>, | ||
| 62 | } | 64 | } |
| 63 | 65 | ||
| 64 | impl<'d> Flash<'d> { | 66 | impl<'d> Flash<'d> { |
| @@ -66,7 +68,7 @@ mod alt_regions { | |||
| 66 | unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; | 68 | unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; |
| 67 | 69 | ||
| 68 | // SAFETY: We never expose the cloned peripheral references, and their instance is not public. | 70 | // SAFETY: We never expose the cloned peripheral references, and their instance is not public. |
| 69 | // Also, all flash region operations are protected with a cs. | 71 | // Also, all blocking flash region operations are protected with a cs. |
| 70 | let p = self.release(); | 72 | let p = self.release(); |
| 71 | AltFlashLayout { | 73 | AltFlashLayout { |
| 72 | bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }), | 74 | bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }), |
| @@ -75,22 +77,74 @@ mod alt_regions { | |||
| 75 | bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }), | 77 | bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }), |
| 76 | bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }), | 78 | bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }), |
| 77 | bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }), | 79 | bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }), |
| 80 | otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }), | ||
| 78 | } | 81 | } |
| 79 | } | 82 | } |
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | impl Drop for AltFlashLayout<'_> { | 85 | macro_rules! foreach_altflash_region { |
| 83 | fn drop(&mut self) { | 86 | ($type_name:ident, $region:ident) => { |
| 84 | unsafe { | 87 | impl $type_name<'_> { |
| 85 | super::lock(); | 88 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { |
| 86 | crate::pac::FLASH.optcr().modify(|r| r.set_db1m(false)) | 89 | blocking_read(self.0.base, self.0.size, offset, bytes) |
| 87 | }; | 90 | } |
| 88 | } | 91 | |
| 92 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | ||
| 93 | unsafe { blocking_write_chunked(self.0.base, self.0.size, offset, bytes) } | ||
| 94 | } | ||
| 95 | |||
| 96 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | ||
| 97 | unsafe { blocking_erase_sectored(self.0.base, from, to) } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | impl embedded_storage::nor_flash::ErrorType for $type_name<'_> { | ||
| 102 | type Error = Error; | ||
| 103 | } | ||
| 104 | |||
| 105 | impl embedded_storage::nor_flash::ReadNorFlash for $type_name<'_> { | ||
| 106 | const READ_SIZE: usize = 1; | ||
| 107 | |||
| 108 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | ||
| 109 | self.blocking_read(offset, bytes) | ||
| 110 | } | ||
| 111 | |||
| 112 | fn capacity(&self) -> usize { | ||
| 113 | self.0.size as usize | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | impl embedded_storage::nor_flash::NorFlash for $type_name<'_> { | ||
| 118 | const WRITE_SIZE: usize = $region.write_size as usize; | ||
| 119 | const ERASE_SIZE: usize = $region.erase_size as usize; | ||
| 120 | |||
| 121 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { | ||
| 122 | self.blocking_write(offset, bytes) | ||
| 123 | } | ||
| 124 | |||
| 125 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { | ||
| 126 | self.blocking_erase(from, to) | ||
| 127 | } | ||
| 128 | } | ||
| 129 | }; | ||
| 89 | } | 130 | } |
| 131 | |||
| 132 | foreach_altflash_region!(AltBank1Region3, ALT_BANK1_REGION3); | ||
| 133 | foreach_altflash_region!(AltBank2Region1, ALT_BANK2_REGION1); | ||
| 134 | foreach_altflash_region!(AltBank2Region2, ALT_BANK2_REGION2); | ||
| 135 | foreach_altflash_region!(AltBank2Region3, ALT_BANK2_REGION3); | ||
| 90 | } | 136 | } |
| 91 | 137 | ||
| 92 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] | 138 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] |
| 93 | pub use alt_regions::{AltFlashLayout, ALT_FLASH_REGIONS}; | 139 | pub use alt_regions::*; |
| 140 | |||
| 141 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] | ||
| 142 | pub fn set_default_layout() { | ||
| 143 | unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(false)) }; | ||
| 144 | } | ||
| 145 | |||
| 146 | #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] | ||
| 147 | pub const fn set_default_layout() {} | ||
| 94 | 148 | ||
| 95 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] | 149 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] |
| 96 | pub fn get_flash_regions() -> &'static [&'static FlashRegion] { | 150 | pub fn get_flash_regions() -> &'static [&'static FlashRegion] { |
diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index 6427d5a09..ac2834a84 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs | |||
| @@ -6,6 +6,8 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 6 | use crate::flash::Error; | 6 | use crate::flash::Error; |
| 7 | use crate::pac; | 7 | use crate::pac; |
| 8 | 8 | ||
| 9 | pub const fn set_default_layout() {} | ||
| 10 | |||
| 9 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 11 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 10 | &FLASH_REGIONS | 12 | &FLASH_REGIONS |
| 11 | } | 13 | } |
diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 4f38d50c0..1b1631068 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs | |||
| @@ -7,6 +7,8 @@ use super::{FlashRegion, FlashSector, BANK1_REGION, FLASH_REGIONS, WRITE_SIZE}; | |||
| 7 | use crate::flash::Error; | 7 | use crate::flash::Error; |
| 8 | use crate::pac; | 8 | use crate::pac; |
| 9 | 9 | ||
| 10 | pub const fn set_default_layout() {} | ||
| 11 | |||
| 10 | const fn is_dual_bank() -> bool { | 12 | const fn is_dual_bank() -> bool { |
| 11 | FLASH_REGIONS.len() == 2 | 13 | FLASH_REGIONS.len() == 2 |
| 12 | } | 14 | } |
diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index 7d9cc6ea3..c94f61900 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs | |||
| @@ -6,6 +6,8 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 6 | use crate::flash::Error; | 6 | use crate::flash::Error; |
| 7 | use crate::pac; | 7 | use crate::pac; |
| 8 | 8 | ||
| 9 | pub const fn set_default_layout() {} | ||
| 10 | |||
| 9 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 11 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 10 | &FLASH_REGIONS | 12 | &FLASH_REGIONS |
| 11 | } | 13 | } |
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index f6efa7753..b93270ae1 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs | |||
| @@ -19,6 +19,7 @@ pub struct FlashRegion { | |||
| 19 | pub erase_size: u32, | 19 | pub erase_size: u32, |
| 20 | pub write_size: u32, | 20 | pub write_size: u32, |
| 21 | pub erase_value: u8, | 21 | pub erase_value: u8, |
| 22 | pub(crate) _ensure_internal: (), | ||
| 22 | } | 23 | } |
| 23 | 24 | ||
| 24 | #[derive(Debug, PartialEq)] | 25 | #[derive(Debug, PartialEq)] |
diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index c151cb828..556034654 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | use super::{Error, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | 3 | use super::{Error, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; |
| 4 | 4 | ||
| 5 | pub const fn set_default_layout() {} | ||
| 6 | |||
| 5 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 7 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 6 | &FLASH_REGIONS | 8 | &FLASH_REGIONS |
| 7 | } | 9 | } |
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; | |||
| 9 | use crate::i2c::{Error, Instance, SclPin, SdaPin}; | 9 | use crate::i2c::{Error, Instance, SclPin, SdaPin}; |
| 10 | use crate::pac::i2c; | 10 | use crate::pac::i2c; |
| 11 | use crate::time::Hertz; | 11 | use crate::time::Hertz; |
| 12 | use crate::Peripheral; | 12 | use crate::{interrupt, Peripheral}; |
| 13 | |||
| 14 | /// Interrupt handler. | ||
| 15 | pub struct InterruptHandler<T: Instance> { | ||
| 16 | _phantom: PhantomData<T>, | ||
| 17 | } | ||
| 18 | |||
| 19 | impl<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 @@ | |||
| 1 | use core::cmp; | 1 | use core::cmp; |
| 2 | use core::future::poll_fn; | 2 | use core::future::poll_fn; |
| 3 | use core::marker::PhantomData; | ||
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| 6 | use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; | ||
| 5 | use embassy_embedded_hal::SetConfig; | 7 | use embassy_embedded_hal::SetConfig; |
| 6 | use embassy_hal_common::drop::OnDrop; | 8 | use embassy_hal_common::drop::OnDrop; |
| 7 | use embassy_hal_common::{into_ref, PeripheralRef}; | 9 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| @@ -11,10 +13,30 @@ use crate::dma::{NoDma, Transfer}; | |||
| 11 | use crate::gpio::sealed::AFType; | 13 | use crate::gpio::sealed::AFType; |
| 12 | use crate::gpio::Pull; | 14 | use crate::gpio::Pull; |
| 13 | use crate::i2c::{Error, Instance, SclPin, SdaPin}; | 15 | use crate::i2c::{Error, Instance, SclPin, SdaPin}; |
| 14 | use crate::interrupt::InterruptExt; | ||
| 15 | use crate::pac::i2c; | 16 | use crate::pac::i2c; |
| 16 | use crate::time::Hertz; | 17 | use crate::time::Hertz; |
| 17 | use crate::Peripheral; | 18 | use crate::{interrupt, Peripheral}; |
| 19 | |||
| 20 | /// Interrupt handler. | ||
| 21 | pub struct InterruptHandler<T: Instance> { | ||
| 22 | _phantom: PhantomData<T>, | ||
| 23 | } | ||
| 24 | |||
| 25 | impl<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 @@ | |||
| 1 | use embassy_hal_common::into_ref; | ||
| 2 | |||
| 3 | use crate::gpio::sealed::{AFType, Pin as _}; | ||
| 4 | use crate::gpio::AnyPin; | ||
| 5 | use crate::pac::spi::vals; | ||
| 6 | use crate::rcc::get_freqs; | ||
| 7 | use crate::spi::{Config as SpiConfig, *}; | ||
| 8 | use crate::time::Hertz; | ||
| 9 | use crate::{Peripheral, PeripheralRef}; | ||
| 10 | |||
| 11 | #[derive(Copy, Clone)] | ||
| 12 | pub enum Mode { | ||
| 13 | Master, | ||
| 14 | Slave, | ||
| 15 | } | ||
| 16 | |||
| 17 | #[derive(Copy, Clone)] | ||
| 18 | pub enum Function { | ||
| 19 | Transmit, | ||
| 20 | Receive, | ||
| 21 | } | ||
| 22 | |||
| 23 | #[derive(Copy, Clone)] | ||
| 24 | pub enum Standard { | ||
| 25 | Philips, | ||
| 26 | MsbFirst, | ||
| 27 | LsbFirst, | ||
| 28 | PcmLongSync, | ||
| 29 | PcmShortSync, | ||
| 30 | } | ||
| 31 | |||
| 32 | impl 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)] | ||
| 54 | pub 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 | |||
| 65 | impl 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)] | ||
| 88 | pub enum ClockPolarity { | ||
| 89 | IdleLow, | ||
| 90 | IdleHigh, | ||
| 91 | } | ||
| 92 | |||
| 93 | impl 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)] | ||
| 111 | pub 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 | |||
| 120 | impl 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 | |||
| 133 | pub 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 | |||
| 141 | impl<'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 | |||
| 265 | impl<'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 | ||
| 291 | fn 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 @@ | |||
| 1 | pub use critical_section::{CriticalSection, Mutex}; | ||
| 2 | pub use embassy_cortex_m::interrupt::*; | ||
| 3 | |||
| 4 | pub 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; | |||
| 6 | include!(concat!(env!("OUT_DIR"), "/_macros.rs")); | 6 | include!(concat!(env!("OUT_DIR"), "/_macros.rs")); |
| 7 | 7 | ||
| 8 | // Utilities | 8 | // Utilities |
| 9 | pub mod interrupt; | ||
| 10 | pub mod time; | 9 | pub mod time; |
| 11 | mod traits; | 10 | mod traits; |
| 12 | 11 | ||
| @@ -40,6 +39,8 @@ pub mod i2c; | |||
| 40 | #[cfg(crc)] | 39 | #[cfg(crc)] |
| 41 | pub mod crc; | 40 | pub mod crc; |
| 42 | pub mod flash; | 41 | pub mod flash; |
| 42 | #[cfg(all(spi_v1, rcc_f4))] | ||
| 43 | pub mod i2s; | ||
| 43 | #[cfg(stm32wb)] | 44 | #[cfg(stm32wb)] |
| 44 | pub mod ipcc; | 45 | pub mod ipcc; |
| 45 | pub mod pwm; | 46 | pub 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 | ||
| 77 | pub 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 |
| 77 | pub use _generated::{peripherals, Peripherals}; | 113 | pub use _generated::{peripherals, Peripherals}; |
| 78 | pub use embassy_cortex_m::executor; | 114 | pub 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 | ||
| 3 | use core::default::Default; | 3 | use core::default::Default; |
| 4 | use core::future::poll_fn; | 4 | use core::future::poll_fn; |
| 5 | use core::marker::PhantomData; | ||
| 5 | use core::ops::{Deref, DerefMut}; | 6 | use core::ops::{Deref, DerefMut}; |
| 6 | use core::task::Poll; | 7 | use core::task::Poll; |
| 7 | 8 | ||
| @@ -17,7 +18,36 @@ use crate::interrupt::{Interrupt, InterruptExt}; | |||
| 17 | use crate::pac::sdmmc::Sdmmc as RegBlock; | 18 | use crate::pac::sdmmc::Sdmmc as RegBlock; |
| 18 | use crate::rcc::RccPeripheral; | 19 | use crate::rcc::RccPeripheral; |
| 19 | use crate::time::Hertz; | 20 | use crate::time::Hertz; |
| 20 | use crate::{peripherals, Peripheral}; | 21 | use crate::{interrupt, peripherals, Peripheral}; |
| 22 | |||
| 23 | /// Interrupt handler. | ||
| 24 | pub struct InterruptHandler<T: Instance> { | ||
| 25 | _phantom: PhantomData<T>, | ||
| 26 | } | ||
| 27 | |||
| 28 | impl<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 | |||
| 45 | impl<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. |
| 23 | const SD_INIT_FREQ: Hertz = Hertz(400_000); | 53 | const SD_INIT_FREQ: Hertz = Hertz(400_000); |
| @@ -223,7 +253,6 @@ impl Default for Config { | |||
| 223 | /// Sdmmc device | 253 | /// Sdmmc device |
| 224 | pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { | 254 | pub 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> { | |||
| 247 | impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | 276 | impl<'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> { | |||
| 329 | impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | 356 | impl<'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> { | |||
| 408 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | 433 | impl<'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 | ||
| 1290 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { | 1289 | impl<'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 {} | |||
| 1044 | pin_trait!(SckPin, Instance); | 1055 | pin_trait!(SckPin, Instance); |
| 1045 | pin_trait!(MosiPin, Instance); | 1056 | pin_trait!(MosiPin, Instance); |
| 1046 | pin_trait!(MisoPin, Instance); | 1057 | pin_trait!(MisoPin, Instance); |
| 1058 | pin_trait!(CsPin, Instance); | ||
| 1059 | pin_trait!(MckPin, Instance); | ||
| 1060 | pin_trait!(CkPin, Instance); | ||
| 1061 | pin_trait!(WsPin, Instance); | ||
| 1047 | dma_trait!(RxDma, Instance); | 1062 | dma_trait!(RxDma, Instance); |
| 1048 | dma_trait!(TxDma, Instance); | 1063 | dma_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}; | |||
| 4 | use core::{mem, ptr}; | 4 | use core::{mem, ptr}; |
| 5 | 5 | ||
| 6 | use atomic_polyfill::{AtomicU32, AtomicU8}; | 6 | use atomic_polyfill::{AtomicU32, AtomicU8}; |
| 7 | use critical_section::CriticalSection; | ||
| 7 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 8 | use embassy_sync::blocking_mutex::Mutex; | 9 | use embassy_sync::blocking_mutex::Mutex; |
| 9 | use embassy_time::driver::{AlarmHandle, Driver}; | 10 | use embassy_time::driver::{AlarmHandle, Driver}; |
| 10 | use embassy_time::TICK_HZ; | 11 | use embassy_time::TICK_HZ; |
| 11 | use stm32_metapac::timer::regs; | 12 | use stm32_metapac::timer::regs; |
| 12 | 13 | ||
| 13 | use crate::interrupt::{CriticalSection, InterruptExt}; | 14 | use crate::interrupt::InterruptExt; |
| 14 | use crate::pac::timer::vals; | 15 | use crate::pac::timer::vals; |
| 15 | use crate::rcc::sealed::RccPeripheral; | 16 | use crate::rcc::sealed::RccPeripheral; |
| 16 | use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance}; | 17 | use 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 @@ | |||
| 1 | use core::mem::MaybeUninit; | 1 | use core::mem::MaybeUninit; |
| 2 | 2 | ||
| 3 | use bit_field::BitField; | 3 | use bit_field::BitField; |
| 4 | use embassy_cortex_m::interrupt::InterruptExt; | ||
| 5 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 4 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 6 | use embassy_sync::channel::Channel; | 5 | use embassy_sync::channel::Channel; |
| 7 | 6 | ||
| @@ -12,7 +11,7 @@ use self::mm::MemoryManager; | |||
| 12 | use self::shci::{shci_ble_init, ShciBleInitCmdParam}; | 11 | use self::shci::{shci_ble_init, ShciBleInitCmdParam}; |
| 13 | use self::sys::Sys; | 12 | use self::sys::Sys; |
| 14 | use self::unsafe_linked_list::LinkedListNode; | 13 | use self::unsafe_linked_list::LinkedListNode; |
| 15 | use crate::_generated::interrupt::{IPCC_C1_RX, IPCC_C1_TX}; | 14 | use crate::interrupt; |
| 16 | use crate::ipcc::Ipcc; | 15 | use crate::ipcc::Ipcc; |
| 17 | 16 | ||
| 18 | mod ble; | 17 | mod ble; |
| @@ -55,6 +54,19 @@ pub struct FusInfoTable { | |||
| 55 | fus_info: u32, | 54 | fus_info: u32, |
| 56 | } | 55 | } |
| 57 | 56 | ||
| 57 | /// Interrupt handler. | ||
| 58 | pub struct ReceiveInterruptHandler {} | ||
| 59 | |||
| 60 | impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler { | ||
| 61 | unsafe fn on_interrupt() {} | ||
| 62 | } | ||
| 63 | |||
| 64 | pub struct TransmitInterruptHandler {} | ||
| 65 | |||
| 66 | impl 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 | ||
| 286 | impl TlMbox { | 298 | impl 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 | ||
| 9 | use super::*; | 9 | use super::*; |
| 10 | 10 | ||
| 11 | /// Interrupt handler. | ||
| 12 | pub struct InterruptHandler<T: BasicInstance> { | ||
| 13 | _phantom: PhantomData<T>, | ||
| 14 | } | ||
| 15 | |||
| 16 | impl<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 | |||
| 11 | pub struct State { | 83 | pub 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> { | |||
| 43 | impl<'d, T: BasicInstance> BufferedUart<'d, T> { | 115 | impl<'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 | ||
| 339 | unsafe 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 | |||
| 404 | impl embedded_io::Error for Error { | 409 | impl 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; | |||
| 5 | use core::sync::atomic::{compiler_fence, Ordering}; | 5 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 6 | use core::task::Poll; | 6 | use core::task::Poll; |
| 7 | 7 | ||
| 8 | use embassy_cortex_m::interrupt::InterruptExt; | 8 | use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; |
| 9 | use embassy_hal_common::drop::OnDrop; | 9 | use embassy_hal_common::drop::OnDrop; |
| 10 | use embassy_hal_common::{into_ref, PeripheralRef}; | 10 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 11 | use futures::future::{select, Either}; | 11 | use futures::future::{select, Either}; |
| @@ -18,7 +18,71 @@ use crate::pac::usart::Lpuart as Regs; | |||
| 18 | use crate::pac::usart::Usart as Regs; | 18 | use crate::pac::usart::Usart as Regs; |
| 19 | use crate::pac::usart::{regs, vals}; | 19 | use crate::pac::usart::{regs, vals}; |
| 20 | use crate::time::Hertz; | 20 | use crate::time::Hertz; |
| 21 | use crate::{peripherals, Peripheral}; | 21 | use crate::{interrupt, peripherals, Peripheral}; |
| 22 | |||
| 23 | /// Interrupt handler. | ||
| 24 | pub struct InterruptHandler<T: BasicInstance> { | ||
| 25 | _phantom: PhantomData<T>, | ||
| 26 | } | ||
| 27 | |||
| 28 | impl<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)] |
| 24 | pub enum DataBits { | 88 | pub 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")] |
| 1070 | pub use buffered::*; | 1073 | pub use buffered::*; |
| 1074 | |||
| 1075 | #[cfg(feature = "nightly")] | ||
| 1076 | pub use crate::usart::buffered::InterruptHandler as BufferedInterruptHandler; | ||
| 1071 | #[cfg(feature = "nightly")] | 1077 | #[cfg(feature = "nightly")] |
| 1072 | mod buffered; | 1078 | mod 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 | ||
| 15 | use super::{DmPin, DpPin, Instance}; | 15 | use super::{DmPin, DpPin, Instance}; |
| 16 | use crate::gpio::sealed::AFType; | 16 | use crate::gpio::sealed::AFType; |
| 17 | use crate::interrupt::InterruptExt; | 17 | use crate::interrupt::{Interrupt, InterruptExt}; |
| 18 | use crate::pac::usb::regs; | 18 | use crate::pac::usb::regs; |
| 19 | use crate::pac::usb::vals::{EpType, Stat}; | 19 | use crate::pac::usb::vals::{EpType, Stat}; |
| 20 | use crate::pac::USBRAM; | 20 | use crate::pac::USBRAM; |
| 21 | use crate::rcc::sealed::RccPeripheral; | 21 | use crate::rcc::sealed::RccPeripheral; |
| 22 | use crate::Peripheral; | 22 | use crate::{interrupt, Peripheral}; |
| 23 | |||
| 24 | /// Interrupt handler. | ||
| 25 | pub struct InterruptHandler<T: Instance> { | ||
| 26 | _phantom: PhantomData<T>, | ||
| 27 | } | ||
| 28 | |||
| 29 | impl<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 | ||
| 24 | const EP_COUNT: usize = 8; | 111 | const EP_COUNT: usize = 8; |
| 25 | 112 | ||
| @@ -168,14 +255,13 @@ pub struct Driver<'d, T: Instance> { | |||
| 168 | impl<'d, T: Instance> Driver<'d, T> { | 255 | impl<'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 | ||
| 5 | use atomic_polyfill::{AtomicBool, AtomicU16, Ordering}; | 5 | use atomic_polyfill::{AtomicBool, AtomicU16, Ordering}; |
| 6 | use embassy_cortex_m::interrupt::InterruptExt; | 6 | use embassy_cortex_m::interrupt::InterruptExt; |
| 7 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | 7 | use embassy_hal_common::{into_ref, Peripheral}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 8 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | use embassy_usb_driver::{ | 9 | use 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 | ||
| 15 | use super::*; | 15 | use super::*; |
| 16 | use crate::gpio::sealed::AFType; | 16 | use crate::gpio::sealed::AFType; |
| 17 | use crate::interrupt; | ||
| 17 | use crate::pac::otg::{regs, vals}; | 18 | use crate::pac::otg::{regs, vals}; |
| 18 | use crate::rcc::sealed::RccPeripheral; | 19 | use crate::rcc::sealed::RccPeripheral; |
| 19 | use crate::time::Hertz; | 20 | use crate::time::Hertz; |
| 20 | 21 | ||
| 22 | /// Interrupt handler. | ||
| 23 | pub struct InterruptHandler<T: Instance> { | ||
| 24 | _phantom: PhantomData<T>, | ||
| 25 | } | ||
| 26 | |||
| 27 | impl<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 | |||
| 21 | macro_rules! config_ulpi_pins { | 172 | macro_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 | ||
| 124 | pub struct Driver<'d, T: Instance> { | 275 | pub 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 | ||
| 356 | pub struct Bus<'d, T: Instance> { | 501 | pub 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 | ||
| 644 | impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { | 644 | impl<'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> { | |||
| 13 | const MAX_RL: u16 = 0xFFF; | 13 | const 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 |
| 16 | const fn max_timeout(prescaler: u16) -> u32 { | 16 | const 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 |
| 21 | const fn reload_value(prescaler: u16, timeout_us: u32) -> u16 { | 21 | const 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 | ||
| 25 | impl<'d, T: Instance> IndependentWatchdog<'d, T> { | 25 | impl<'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)] | ||
| 100 | mod 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; | |||
| 8 | use embassy_stm32::gpio::{Level, Output, Speed}; | 8 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 9 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 10 | use embassy_stm32::usb::{Driver, Instance}; | 10 | use embassy_stm32::usb::{Driver, Instance}; |
| 11 | use embassy_stm32::{interrupt, Config}; | 11 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; |
| 12 | use embassy_time::{Duration, Timer}; | 12 | use embassy_time::{Duration, Timer}; |
| 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 14 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 15 | use embassy_usb::Builder; | 15 | use embassy_usb::Builder; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | USB_LP_CAN1_RX0 => usb::InterruptHandler<peripherals::USB>; | ||
| 20 | }); | ||
| 21 | |||
| 18 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 19 | async fn main(_spawner: Spawner) { | 23 | async 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; | |||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::dma::NoDma; | 9 | use embassy_stm32::dma::NoDma; |
| 10 | use embassy_stm32::interrupt; | ||
| 11 | use embassy_stm32::usart::{Config, Uart}; | 10 | use embassy_stm32::usart::{Config, Uart}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 12 | use heapless::String; | 12 | use heapless::String; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | USART1 => usart::InterruptHandler<peripherals::USART1>; | ||
| 17 | }); | ||
| 18 | |||
| 15 | #[embassy_executor::main] | 19 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 20 | async 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; | |||
| 8 | use embassy_stm32::gpio::{Level, Output, Speed}; | 8 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 9 | use embassy_stm32::time::mhz; | 9 | use embassy_stm32::time::mhz; |
| 10 | use embassy_stm32::usb::{Driver, Instance}; | 10 | use embassy_stm32::usb::{Driver, Instance}; |
| 11 | use embassy_stm32::{interrupt, Config}; | 11 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; |
| 12 | use embassy_time::{Duration, Timer}; | 12 | use embassy_time::{Duration, Timer}; |
| 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 14 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 15 | use embassy_usb::Builder; | 15 | use embassy_usb::Builder; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | USB_LP_CAN_RX0 => usb::InterruptHandler<peripherals::USB>; | ||
| 20 | }); | ||
| 21 | |||
| 18 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 19 | async fn main(_spawner: Spawner) { | 23 | async 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::*; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::dma::NoDma; | 7 | use embassy_stm32::dma::NoDma; |
| 8 | use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; | 8 | use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; |
| 9 | use embassy_stm32::interrupt; | ||
| 10 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 10 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 11 | use embassy_time::Duration; | 11 | use embassy_time::Duration; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | const ADDRESS: u8 = 0x5F; | 14 | const ADDRESS: u8 = 0x5F; |
| 15 | const WHOAMI: u8 = 0x0F; | 15 | const WHOAMI: u8 = 0x0F; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | ||
| 19 | }); | ||
| 20 | |||
| 17 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 22 | async 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 | |||
| 5 | use core::fmt::Write; | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_stm32::i2s::{Config, I2S}; | ||
| 10 | use embassy_stm32::time::Hertz; | ||
| 11 | use heapless::String; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[embassy_executor::main] | ||
| 15 | async 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::*; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; | 7 | use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; |
| 8 | use embassy_stm32::time::mhz; | 8 | use embassy_stm32::time::mhz; |
| 9 | use embassy_stm32::{interrupt, Config}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {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. |
| 14 | const ALLOW_WRITES: bool = false; | 14 | const ALLOW_WRITES: bool = false; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | SDIO => sdmmc::InterruptHandler<peripherals::SDIO>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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 @@ | |||
| 5 | use cortex_m_rt::entry; | 5 | use cortex_m_rt::entry; |
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_stm32::dma::NoDma; | 7 | use embassy_stm32::dma::NoDma; |
| 8 | use embassy_stm32::interrupt; | ||
| 9 | use embassy_stm32::usart::{Config, Uart}; | 8 | use embassy_stm32::usart::{Config, Uart}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | USART3 => usart::InterruptHandler<peripherals::USART3>; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[entry] | 16 | #[entry] |
| 13 | fn main() -> ! { | 17 | fn 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::interrupt; | ||
| 8 | use embassy_stm32::usart::{BufferedUart, Config}; | 7 | use embassy_stm32::usart::{BufferedUart, Config}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 9 | use embedded_io::asynch::BufRead; | 9 | use embedded_io::asynch::BufRead; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | USART3 => usart::BufferedInterruptHandler<peripherals::USART3>; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_spawner: Spawner) { | 17 | async 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; | |||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::dma::NoDma; | 9 | use embassy_stm32::dma::NoDma; |
| 10 | use embassy_stm32::interrupt; | ||
| 11 | use embassy_stm32::usart::{Config, Uart}; | 10 | use embassy_stm32::usart::{Config, Uart}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 12 | use heapless::String; | 12 | use heapless::String; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | USART3 => usart::InterruptHandler<peripherals::USART3>; | ||
| 17 | }); | ||
| 18 | |||
| 15 | #[embassy_executor::main] | 19 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 20 | async 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}; | |||
| 9 | use embassy_stm32::rng::Rng; | 9 | use embassy_stm32::rng::Rng; |
| 10 | use embassy_stm32::time::mhz; | 10 | use embassy_stm32::time::mhz; |
| 11 | use embassy_stm32::usb_otg::Driver; | 11 | use embassy_stm32::usb_otg::Driver; |
| 12 | use embassy_stm32::{interrupt, Config}; | 12 | use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; |
| 13 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; | 13 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; |
| 14 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 14 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
| 15 | use embassy_usb::{Builder, UsbDevice}; | 15 | use 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 | ||
| 48 | bind_interrupts!(struct Irqs { | ||
| 49 | OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; | ||
| 50 | }); | ||
| 51 | |||
| 48 | #[embassy_executor::main] | 52 | #[embassy_executor::main] |
| 49 | async fn main(spawner: Spawner) { | 53 | async 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, *}; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::time::mhz; | 7 | use embassy_stm32::time::mhz; |
| 8 | use embassy_stm32::usb_otg::{Driver, Instance}; | 8 | use embassy_stm32::usb_otg::{Driver, Instance}; |
| 9 | use embassy_stm32::{interrupt, Config}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; |
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | 12 | use embassy_usb::Builder; |
| 13 | use futures::future::join; | 13 | use futures::future::join; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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}; | |||
| 11 | use embassy_stm32::peripherals::ETH; | 11 | use embassy_stm32::peripherals::ETH; |
| 12 | use embassy_stm32::rng::Rng; | 12 | use embassy_stm32::rng::Rng; |
| 13 | use embassy_stm32::time::mhz; | 13 | use embassy_stm32::time::mhz; |
| 14 | use embassy_stm32::{interrupt, Config}; | 14 | use embassy_stm32::{bind_interrupts, eth, Config}; |
| 15 | use embassy_time::{Duration, Timer}; | 15 | use embassy_time::{Duration, Timer}; |
| 16 | use embedded_io::asynch::Write; | 16 | use embedded_io::asynch::Write; |
| 17 | use rand_core::RngCore; | 17 | use rand_core::RngCore; |
| @@ -27,6 +27,10 @@ macro_rules! singleton { | |||
| 27 | }}; | 27 | }}; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | ETH => eth::InterruptHandler; | ||
| 32 | }); | ||
| 33 | |||
| 30 | type Device = Ethernet<'static, ETH, GenericSMI>; | 34 | type 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::*; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::sdmmc::Sdmmc; | 7 | use embassy_stm32::sdmmc::Sdmmc; |
| 8 | use embassy_stm32::time::mhz; | 8 | use embassy_stm32::time::mhz; |
| 9 | use embassy_stm32::{interrupt, Config}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | SDMMC1 => sdmmc::InterruptHandler<peripherals::SDMMC1>; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_spawner: Spawner) { | 17 | async 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; | |||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::dma::NoDma; | 9 | use embassy_stm32::dma::NoDma; |
| 10 | use embassy_stm32::interrupt; | ||
| 11 | use embassy_stm32::usart::{Config, Uart}; | 10 | use embassy_stm32::usart::{Config, Uart}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 12 | use heapless::String; | 12 | use heapless::String; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 17 | }); | ||
| 18 | |||
| 15 | #[embassy_executor::main] | 19 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 20 | async 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, *}; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::time::mhz; | 7 | use embassy_stm32::time::mhz; |
| 8 | use embassy_stm32::usb_otg::{Driver, Instance}; | 8 | use embassy_stm32::usb_otg::{Driver, Instance}; |
| 9 | use embassy_stm32::{interrupt, Config}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; |
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | 12 | use embassy_usb::Builder; |
| 13 | use futures::future::join; | 13 | use futures::future::join; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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; | |||
| 12 | use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; | 12 | use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; |
| 13 | use embassy_stm32::rng::Rng; | 13 | use embassy_stm32::rng::Rng; |
| 14 | use embassy_stm32::time::Hertz; | 14 | use embassy_stm32::time::Hertz; |
| 15 | use embassy_stm32::{interrupt, Config}; | 15 | use embassy_stm32::{bind_interrupts, eth, Config}; |
| 16 | use embassy_time::{Duration, Timer}; | 16 | use embassy_time::{Duration, Timer}; |
| 17 | use embedded_io::asynch::Write; | 17 | use embedded_io::asynch::Write; |
| 18 | use rand_core::RngCore; | 18 | use rand_core::RngCore; |
| @@ -28,6 +28,10 @@ macro_rules! singleton { | |||
| 28 | }}; | 28 | }}; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | bind_interrupts!(struct Irqs { | ||
| 32 | ETH => eth::InterruptHandler; | ||
| 33 | }); | ||
| 34 | |||
| 31 | type Device = Ethernet<'static, ETH, GenericSMI>; | 35 | type 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 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; | 7 | use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; |
| 8 | use embassy_stm32::interrupt; | ||
| 9 | use embassy_stm32::time::Hertz; | 8 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 10 | use embassy_time::Duration; | 10 | use embassy_time::Duration; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | const ADDRESS: u8 = 0x5F; | 13 | const ADDRESS: u8 = 0x5F; |
| 14 | const WHOAMI: u8 = 0x0F; | 14 | const WHOAMI: u8 = 0x0F; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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; | |||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Executor; | 7 | use embassy_executor::Executor; |
| 8 | use embassy_stm32::dma::NoDma; | 8 | use embassy_stm32::dma::NoDma; |
| 9 | use embassy_stm32::interrupt; | ||
| 10 | use embassy_stm32::usart::{Config, Uart}; | 9 | use embassy_stm32::usart::{Config, Uart}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 11 | use static_cell::StaticCell; | 11 | use static_cell::StaticCell; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 16 | }); | ||
| 17 | |||
| 14 | #[embassy_executor::task] | 18 | #[embassy_executor::task] |
| 15 | async fn main_task() { | 19 | async 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; | |||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Executor; | 9 | use embassy_executor::Executor; |
| 10 | use embassy_stm32::dma::NoDma; | 10 | use embassy_stm32::dma::NoDma; |
| 11 | use embassy_stm32::interrupt; | ||
| 12 | use embassy_stm32::usart::{Config, Uart}; | 11 | use embassy_stm32::usart::{Config, Uart}; |
| 12 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 13 | use heapless::String; | 13 | use heapless::String; |
| 14 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 19 | }); | ||
| 20 | |||
| 17 | #[embassy_executor::task] | 21 | #[embassy_executor::task] |
| 18 | async fn main_task() { | 22 | async 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 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::dma::NoDma; | 7 | use embassy_stm32::dma::NoDma; |
| 8 | use embassy_stm32::interrupt; | ||
| 9 | use embassy_stm32::peripherals::{GPDMA1_CH1, UART7}; | 8 | use embassy_stm32::peripherals::{GPDMA1_CH1, UART7}; |
| 10 | use embassy_stm32::usart::{Config, Uart, UartRx}; | 9 | use embassy_stm32::usart::{Config, Uart, UartRx}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 11 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 11 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| 12 | use embassy_sync::channel::Channel; | 12 | use embassy_sync::channel::Channel; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 17 | }); | ||
| 18 | |||
| 15 | #[embassy_executor::task] | 19 | #[embassy_executor::task] |
| 16 | async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) { | 20 | async 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; | |||
| 7 | use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; | 7 | use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; |
| 8 | use embassy_stm32::time::Hertz; | 8 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::usb::{Driver, Instance}; | 9 | use embassy_stm32::usb::{Driver, Instance}; |
| 10 | use embassy_stm32::{interrupt, pac, Config}; | 10 | use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config}; |
| 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 12 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::Builder; | 13 | use embassy_usb::Builder; |
| 14 | use futures::future::join; | 14 | use futures::future::join; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | USB_DRD_FS => usb::InterruptHandler<peripherals::USB>; | ||
| 19 | }); | ||
| 20 | |||
| 17 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 22 | async 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}; | |||
| 8 | use embassy_stm32::i2c::I2c; | 8 | use embassy_stm32::i2c::I2c; |
| 9 | use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; | 9 | use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; |
| 10 | use embassy_stm32::time::{khz, mhz}; | 10 | use embassy_stm32::time::{khz, mhz}; |
| 11 | use embassy_stm32::{interrupt, Config}; | 11 | use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; |
| 12 | use embassy_time::{Duration, Timer}; | 12 | use embassy_time::{Duration, Timer}; |
| 13 | use ov7725::*; | 13 | use ov7725::*; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -18,6 +18,11 @@ const HEIGHT: usize = 100; | |||
| 18 | 18 | ||
| 19 | static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2]; | 19 | static mut FRAME: [u32; WIDTH * HEIGHT / 2] = [0u32; WIDTH * HEIGHT / 2]; |
| 20 | 20 | ||
| 21 | bind_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] |
| 22 | async fn main(_spawner: Spawner) { | 27 | async 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}; | |||
| 11 | use embassy_stm32::peripherals::ETH; | 11 | use embassy_stm32::peripherals::ETH; |
| 12 | use embassy_stm32::rng::Rng; | 12 | use embassy_stm32::rng::Rng; |
| 13 | use embassy_stm32::time::mhz; | 13 | use embassy_stm32::time::mhz; |
| 14 | use embassy_stm32::{interrupt, Config}; | 14 | use embassy_stm32::{bind_interrupts, eth, Config}; |
| 15 | use embassy_time::{Duration, Timer}; | 15 | use embassy_time::{Duration, Timer}; |
| 16 | use embedded_io::asynch::Write; | 16 | use embedded_io::asynch::Write; |
| 17 | use rand_core::RngCore; | 17 | use rand_core::RngCore; |
| @@ -27,6 +27,10 @@ macro_rules! singleton { | |||
| 27 | }}; | 27 | }}; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | ETH => eth::InterruptHandler; | ||
| 32 | }); | ||
| 33 | |||
| 30 | type Device = Ethernet<'static, ETH, GenericSMI>; | 34 | type 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}; | |||
| 11 | use embassy_stm32::peripherals::ETH; | 11 | use embassy_stm32::peripherals::ETH; |
| 12 | use embassy_stm32::rng::Rng; | 12 | use embassy_stm32::rng::Rng; |
| 13 | use embassy_stm32::time::mhz; | 13 | use embassy_stm32::time::mhz; |
| 14 | use embassy_stm32::{interrupt, Config}; | 14 | use embassy_stm32::{bind_interrupts, eth, Config}; |
| 15 | use embassy_time::{Duration, Timer}; | 15 | use embassy_time::{Duration, Timer}; |
| 16 | use embedded_io::asynch::Write; | 16 | use embedded_io::asynch::Write; |
| 17 | use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; | 17 | use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; |
| @@ -28,6 +28,10 @@ macro_rules! singleton { | |||
| 28 | }}; | 28 | }}; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | bind_interrupts!(struct Irqs { | ||
| 32 | ETH => eth::InterruptHandler; | ||
| 33 | }); | ||
| 34 | |||
| 31 | type Device = Ethernet<'static, ETH, GenericSMI>; | 35 | type 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 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; | 7 | use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; |
| 8 | use embassy_stm32::interrupt; | ||
| 9 | use embassy_stm32::time::Hertz; | 8 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 10 | use embassy_time::Duration; | 10 | use embassy_time::Duration; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | const ADDRESS: u8 = 0x5F; | 13 | const ADDRESS: u8 = 0x5F; |
| 14 | const WHOAMI: u8 = 0x0F; | 14 | const WHOAMI: u8 = 0x0F; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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::*; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::sdmmc::Sdmmc; | 7 | use embassy_stm32::sdmmc::Sdmmc; |
| 8 | use embassy_stm32::time::mhz; | 8 | use embassy_stm32::time::mhz; |
| 9 | use embassy_stm32::{interrupt, Config}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | SDMMC1 => sdmmc::InterruptHandler<peripherals::SDMMC1>; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_spawner: Spawner) -> ! { | 17 | async 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; | |||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Executor; | 7 | use embassy_executor::Executor; |
| 8 | use embassy_stm32::dma::NoDma; | 8 | use embassy_stm32::dma::NoDma; |
| 9 | use embassy_stm32::interrupt; | ||
| 10 | use embassy_stm32::usart::{Config, Uart}; | 9 | use embassy_stm32::usart::{Config, Uart}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 11 | use static_cell::StaticCell; | 11 | use static_cell::StaticCell; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 16 | }); | ||
| 17 | |||
| 14 | #[embassy_executor::task] | 18 | #[embassy_executor::task] |
| 15 | async fn main_task() { | 19 | async 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; | |||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Executor; | 9 | use embassy_executor::Executor; |
| 10 | use embassy_stm32::dma::NoDma; | 10 | use embassy_stm32::dma::NoDma; |
| 11 | use embassy_stm32::interrupt; | ||
| 12 | use embassy_stm32::usart::{Config, Uart}; | 11 | use embassy_stm32::usart::{Config, Uart}; |
| 12 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 13 | use heapless::String; | 13 | use heapless::String; |
| 14 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 19 | }); | ||
| 20 | |||
| 17 | #[embassy_executor::task] | 21 | #[embassy_executor::task] |
| 18 | async fn main_task() { | 22 | async 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 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::dma::NoDma; | 7 | use embassy_stm32::dma::NoDma; |
| 8 | use embassy_stm32::interrupt; | ||
| 9 | use embassy_stm32::peripherals::{DMA1_CH1, UART7}; | 8 | use embassy_stm32::peripherals::{DMA1_CH1, UART7}; |
| 10 | use embassy_stm32::usart::{Config, Uart, UartRx}; | 9 | use embassy_stm32::usart::{Config, Uart, UartRx}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 11 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 11 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| 12 | use embassy_sync::channel::Channel; | 12 | use embassy_sync::channel::Channel; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 17 | }); | ||
| 18 | |||
| 15 | #[embassy_executor::task] | 19 | #[embassy_executor::task] |
| 16 | async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) { | 20 | async 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, *}; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::time::mhz; | 7 | use embassy_stm32::time::mhz; |
| 8 | use embassy_stm32::usb_otg::{Driver, Instance}; | 8 | use embassy_stm32::usb_otg::{Driver, Instance}; |
| 9 | use embassy_stm32::{interrupt, Config}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; |
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | 12 | use embassy_usb::Builder; |
| 13 | use futures::future::join; | 13 | use futures::future::join; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::interrupt; | ||
| 8 | use embassy_stm32::usart::{Config, Uart}; | 7 | use embassy_stm32::usart::{Config, Uart}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | USART1 => usart::InterruptHandler<peripherals::USART1>; | ||
| 13 | }); | ||
| 14 | |||
| 11 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 16 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::interrupt; | ||
| 8 | use embassy_stm32::usart::{BufferedUart, Config}; | 7 | use embassy_stm32::usart::{BufferedUart, Config}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 9 | use embedded_io::asynch::{Read, Write}; | 9 | use embedded_io::asynch::{Read, Write}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | USART2 => usart::BufferedInterruptHandler<peripherals::USART2>; | ||
| 14 | }); | ||
| 15 | |||
| 12 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 13 | async fn main(_spawner: Spawner) { | 17 | async 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::*; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::dma::NoDma; | 7 | use embassy_stm32::dma::NoDma; |
| 8 | use embassy_stm32::i2c::I2c; | 8 | use embassy_stm32::i2c::I2c; |
| 9 | use embassy_stm32::interrupt; | ||
| 10 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 10 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | const ADDRESS: u8 = 0x5F; | 13 | const ADDRESS: u8 = 0x5F; |
| 14 | const WHOAMI: u8 = 0x0F; | 14 | const WHOAMI: u8 = 0x0F; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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; | |||
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::dma::NoDma; | 8 | use embassy_stm32::dma::NoDma; |
| 9 | use embassy_stm32::i2c::I2c; | 9 | use embassy_stm32::i2c::I2c; |
| 10 | use embassy_stm32::interrupt; | ||
| 11 | use embassy_stm32::time::Hertz; | 10 | use embassy_stm32::time::Hertz; |
| 11 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 12 | use embedded_hal_async::i2c::I2c as I2cTrait; | 12 | use embedded_hal_async::i2c::I2c as I2cTrait; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | const ADDRESS: u8 = 0x5F; | 15 | const ADDRESS: u8 = 0x5F; |
| 16 | const WHOAMI: u8 = 0x0F; | 16 | const WHOAMI: u8 = 0x0F; |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | ||
| 20 | }); | ||
| 21 | |||
| 18 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 19 | async fn main(_spawner: Spawner) { | 23 | async 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 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::i2c::I2c; | 7 | use embassy_stm32::i2c::I2c; |
| 8 | use embassy_stm32::interrupt; | ||
| 9 | use embassy_stm32::time::Hertz; | 8 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | const ADDRESS: u8 = 0x5F; | 12 | const ADDRESS: u8 = 0x5F; |
| 13 | const WHOAMI: u8 = 0x0F; | 13 | const WHOAMI: u8 = 0x0F; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | I2C2_EV => i2c::InterruptHandler<peripherals::I2C2>; | ||
| 17 | }); | ||
| 18 | |||
| 15 | #[embassy_executor::main] | 19 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 20 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_stm32::dma::NoDma; | 6 | use embassy_stm32::dma::NoDma; |
| 7 | use embassy_stm32::interrupt; | ||
| 8 | use embassy_stm32::usart::{Config, Uart}; | 7 | use embassy_stm32::usart::{Config, Uart}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | UART4 => usart::InterruptHandler<peripherals::UART4>; | ||
| 13 | }); | ||
| 14 | |||
| 11 | #[cortex_m_rt::entry] | 15 | #[cortex_m_rt::entry] |
| 12 | fn main() -> ! { | 16 | fn 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; | |||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::dma::NoDma; | 9 | use embassy_stm32::dma::NoDma; |
| 10 | use embassy_stm32::interrupt; | ||
| 11 | use embassy_stm32::usart::{Config, Uart}; | 10 | use embassy_stm32::usart::{Config, Uart}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 12 | use heapless::String; | 12 | use heapless::String; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | UART4 => usart::InterruptHandler<peripherals::UART4>; | ||
| 17 | }); | ||
| 18 | |||
| 15 | #[embassy_executor::main] | 19 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 20 | async 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 | |||
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::rcc::*; | 8 | use embassy_stm32::rcc::*; |
| 9 | use embassy_stm32::usb_otg::{Driver, Instance}; | 9 | use embassy_stm32::usb_otg::{Driver, Instance}; |
| 10 | use embassy_stm32::{interrupt, Config}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; |
| 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 12 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::Builder; | 13 | use embassy_usb::Builder; |
| 14 | use futures::future::join; | 14 | use futures::future::join; |
| 15 | use panic_probe as _; | 15 | use panic_probe as _; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; | ||
| 19 | }); | ||
| 20 | |||
| 17 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 22 | async 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}; | |||
| 9 | use embassy_stm32::rcc::*; | 9 | use embassy_stm32::rcc::*; |
| 10 | use embassy_stm32::rng::Rng; | 10 | use embassy_stm32::rng::Rng; |
| 11 | use embassy_stm32::usb::Driver; | 11 | use embassy_stm32::usb::Driver; |
| 12 | use embassy_stm32::{interrupt, Config}; | 12 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; |
| 13 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; | 13 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; |
| 14 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 14 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
| 15 | use embassy_usb::{Builder, UsbDevice}; | 15 | use embassy_usb::{Builder, UsbDevice}; |
| @@ -31,6 +31,10 @@ macro_rules! singleton { | |||
| 31 | 31 | ||
| 32 | const MTU: usize = 1514; | 32 | const MTU: usize = 1514; |
| 33 | 33 | ||
| 34 | bind_interrupts!(struct Irqs { | ||
| 35 | USB_FS => usb::InterruptHandler<peripherals::USB>; | ||
| 36 | }); | ||
| 37 | |||
| 34 | #[embassy_executor::task] | 38 | #[embassy_executor::task] |
| 35 | async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! { | 39 | async 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; | |||
| 7 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 8 | use embassy_stm32::rcc::*; | 8 | use embassy_stm32::rcc::*; |
| 9 | use embassy_stm32::usb::Driver; | 9 | use embassy_stm32::usb::Driver; |
| 10 | use embassy_stm32::{interrupt, Config}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; |
| 11 | use embassy_time::{Duration, Timer}; | 11 | use embassy_time::{Duration, Timer}; |
| 12 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | 12 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; |
| 13 | use embassy_usb::control::OutResponse; | 13 | use embassy_usb::control::OutResponse; |
| @@ -15,6 +15,10 @@ use embassy_usb::Builder; | |||
| 15 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 15 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | USB_FS => usb::InterruptHandler<peripherals::USB>; | ||
| 20 | }); | ||
| 21 | |||
| 18 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 19 | async fn main(_spawner: Spawner) { | 23 | async 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; | |||
| 7 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 8 | use embassy_stm32::rcc::*; | 8 | use embassy_stm32::rcc::*; |
| 9 | use embassy_stm32::usb::{Driver, Instance}; | 9 | use embassy_stm32::usb::{Driver, Instance}; |
| 10 | use embassy_stm32::{interrupt, Config}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; |
| 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 12 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::Builder; | 13 | use embassy_usb::Builder; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | USB_FS => usb::InterruptHandler<peripherals::USB>; | ||
| 18 | }); | ||
| 19 | |||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async 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 | |||
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::rcc::*; | 8 | use embassy_stm32::rcc::*; |
| 9 | use embassy_stm32::usb_otg::{Driver, Instance}; | 9 | use embassy_stm32::usb_otg::{Driver, Instance}; |
| 10 | use embassy_stm32::{interrupt, Config}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; |
| 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 12 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::Builder; | 13 | use embassy_usb::Builder; |
| 14 | use futures::future::join; | 14 | use futures::future::join; |
| 15 | use panic_probe as _; | 15 | use panic_probe as _; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; | ||
| 19 | }); | ||
| 20 | |||
| 17 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 22 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::interrupt; | ||
| 8 | use embassy_stm32::ipcc::{Config, Ipcc}; | 7 | use embassy_stm32::ipcc::{Config, Ipcc}; |
| 9 | use embassy_stm32::tl_mbox::TlMbox; | 8 | use embassy_stm32::tl_mbox::TlMbox; |
| 9 | use embassy_stm32::{bind_interrupts, tl_mbox}; | ||
| 10 | use embassy_time::{Duration, Timer}; | 10 | use embassy_time::{Duration, Timer}; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | bind_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] |
| 14 | async fn main(_spawner: Spawner) { | 19 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::interrupt; | ||
| 8 | use embassy_stm32::ipcc::{Config, Ipcc}; | 7 | use embassy_stm32::ipcc::{Config, Ipcc}; |
| 9 | use embassy_stm32::tl_mbox::TlMbox; | 8 | use embassy_stm32::tl_mbox::TlMbox; |
| 9 | use embassy_stm32::{bind_interrupts, tl_mbox}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_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] |
| 13 | async fn main(_spawner: Spawner) { | 18 | async 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 | ||
| 8 | use defmt::info; | 8 | use defmt::info; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_lora::iv::Stm32wlInterfaceVariant; | 10 | use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant}; |
| 11 | use embassy_lora::LoraTimer; | 11 | use embassy_lora::LoraTimer; |
| 12 | use embassy_stm32::gpio::{Level, Output, Pin, Speed}; | 12 | use embassy_stm32::gpio::{Level, Output, Pin, Speed}; |
| 13 | use embassy_stm32::rng::Rng; | 13 | use embassy_stm32::rng::Rng; |
| 14 | use embassy_stm32::spi::Spi; | 14 | use embassy_stm32::spi::Spi; |
| 15 | use embassy_stm32::{interrupt, into_ref, pac, Peripheral}; | 15 | use embassy_stm32::{bind_interrupts, pac}; |
| 16 | use embassy_time::Delay; | 16 | use embassy_time::Delay; |
| 17 | use lora_phy::mod_params::*; | 17 | use lora_phy::mod_params::*; |
| 18 | use lora_phy::sx1261_2::SX1261_2; | 18 | use lora_phy::sx1261_2::SX1261_2; |
| @@ -24,6 +24,10 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 24 | 24 | ||
| 25 | const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region | 25 | const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region |
| 26 | 26 | ||
| 27 | bind_interrupts!(struct Irqs{ | ||
| 28 | SUBGHZ_RADIO => InterruptHandler; | ||
| 29 | }); | ||
| 30 | |||
| 27 | #[embassy_executor::main] | 31 | #[embassy_executor::main] |
| 28 | async fn main(_spawner: Spawner) { | 32 | async 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 | ||
| 8 | use defmt::info; | 8 | use defmt::info; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_lora::iv::Stm32wlInterfaceVariant; | 10 | use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant}; |
| 11 | use embassy_stm32::bind_interrupts; | ||
| 11 | use embassy_stm32::gpio::{Level, Output, Pin, Speed}; | 12 | use embassy_stm32::gpio::{Level, Output, Pin, Speed}; |
| 12 | use embassy_stm32::spi::Spi; | 13 | use embassy_stm32::spi::Spi; |
| 13 | use embassy_stm32::{interrupt, into_ref, Peripheral}; | ||
| 14 | use embassy_time::{Delay, Duration, Timer}; | 14 | use embassy_time::{Delay, Duration, Timer}; |
| 15 | use lora_phy::mod_params::*; | 15 | use lora_phy::mod_params::*; |
| 16 | use lora_phy::sx1261_2::SX1261_2; | 16 | use lora_phy::sx1261_2::SX1261_2; |
| @@ -19,6 +19,10 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 19 | 19 | ||
| 20 | const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region | 20 | const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region |
| 21 | 21 | ||
| 22 | bind_interrupts!(struct Irqs{ | ||
| 23 | SUBGHZ_RADIO => InterruptHandler; | ||
| 24 | }); | ||
| 25 | |||
| 22 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 23 | async fn main(_spawner: Spawner) { | 27 | async 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 | ||
| 8 | use defmt::info; | 8 | use defmt::info; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_lora::iv::Stm32wlInterfaceVariant; | 10 | use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant}; |
| 11 | use embassy_stm32::bind_interrupts; | ||
| 11 | use embassy_stm32::gpio::{Level, Output, Pin, Speed}; | 12 | use embassy_stm32::gpio::{Level, Output, Pin, Speed}; |
| 12 | use embassy_stm32::spi::Spi; | 13 | use embassy_stm32::spi::Spi; |
| 13 | use embassy_stm32::{interrupt, into_ref, Peripheral}; | ||
| 14 | use embassy_time::Delay; | 14 | use embassy_time::Delay; |
| 15 | use lora_phy::mod_params::*; | 15 | use lora_phy::mod_params::*; |
| 16 | use lora_phy::sx1261_2::SX1261_2; | 16 | use lora_phy::sx1261_2::SX1261_2; |
| @@ -19,6 +19,10 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 19 | 19 | ||
| 20 | const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region | 20 | const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region |
| 21 | 21 | ||
| 22 | bind_interrupts!(struct Irqs{ | ||
| 23 | SUBGHZ_RADIO => InterruptHandler; | ||
| 24 | }); | ||
| 25 | |||
| 22 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 23 | async fn main(_spawner: Spawner) { | 27 | async 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 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::interrupt; | 7 | use embassy_stm32::usart::{Config, InterruptHandler, Uart}; |
| 8 | use embassy_stm32::usart::{Config, Uart}; | 8 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs{ | ||
| 12 | USART1 => InterruptHandler<peripherals::USART1>; | ||
| 13 | LPUART1 => InterruptHandler<peripherals::LPUART1>; | ||
| 14 | }); | ||
| 15 | |||
| 11 | /* | 16 | /* |
| 12 | Pass Incoming data from LPUART1 to USART1 | 17 | Pass Incoming data from LPUART1 to USART1 |
| 13 | Example is written for the LoRa-E5 mini v1.0, | 18 | Example 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, *}; | |||
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; | 8 | use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; |
| 9 | use embassy_stm32::time::mhz; | 9 | use embassy_stm32::time::mhz; |
| 10 | use embassy_stm32::{interrupt, Config}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | bind_interrupts!(struct Irqs { | ||
| 14 | SDIO => sdmmc::InterruptHandler<peripherals::SDIO>; | ||
| 15 | }); | ||
| 16 | |||
| 13 | #[embassy_executor::main] | 17 | #[embassy_executor::main] |
| 14 | async fn main(_spawner: Spawner) { | 18 | async 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; | |||
| 7 | use defmt::assert_eq; | 7 | use defmt::assert_eq; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::dma::NoDma; | 9 | use embassy_stm32::dma::NoDma; |
| 10 | use embassy_stm32::interrupt; | ||
| 11 | use embassy_stm32::usart::{Config, Error, Uart}; | 10 | use embassy_stm32::usart::{Config, Error, Uart}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 12 | use embassy_time::{Duration, Instant}; | 12 | use embassy_time::{Duration, Instant}; |
| 13 | use example_common::*; | 13 | use example_common::*; |
| 14 | 14 | ||
| 15 | #[cfg(any( | ||
| 16 | feature = "stm32f103c8", | ||
| 17 | feature = "stm32g491re", | ||
| 18 | feature = "stm32g071rb", | ||
| 19 | feature = "stm32h755zi", | ||
| 20 | feature = "stm32c031c6", | ||
| 21 | ))] | ||
| 22 | bind_interrupts!(struct Irqs { | ||
| 23 | USART1 => usart::InterruptHandler<peripherals::USART1>; | ||
| 24 | }); | ||
| 25 | |||
| 26 | #[cfg(feature = "stm32u585ai")] | ||
| 27 | bind_interrupts!(struct Irqs { | ||
| 28 | USART3 => usart::InterruptHandler<peripherals::USART3>; | ||
| 29 | }); | ||
| 30 | |||
| 31 | #[cfg(feature = "stm32f429zi")] | ||
| 32 | bind_interrupts!(struct Irqs { | ||
| 33 | USART6 => usart::InterruptHandler<peripherals::USART6>; | ||
| 34 | }); | ||
| 35 | |||
| 36 | #[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))] | ||
| 37 | bind_interrupts!(struct Irqs { | ||
| 38 | LPUART1 => usart::InterruptHandler<peripherals::LPUART1>; | ||
| 39 | }); | ||
| 40 | |||
| 15 | #[embassy_executor::main] | 41 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 42 | async 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; | |||
| 7 | use defmt::assert_eq; | 7 | use defmt::assert_eq; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_futures::join::join; | 9 | use embassy_futures::join::join; |
| 10 | use embassy_stm32::interrupt; | ||
| 11 | use embassy_stm32::usart::{Config, Uart}; | 10 | use embassy_stm32::usart::{Config, Uart}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 12 | use example_common::*; | 12 | use example_common::*; |
| 13 | 13 | ||
| 14 | #[cfg(any( | ||
| 15 | feature = "stm32f103c8", | ||
| 16 | feature = "stm32g491re", | ||
| 17 | feature = "stm32g071rb", | ||
| 18 | feature = "stm32h755zi", | ||
| 19 | feature = "stm32c031c6", | ||
| 20 | ))] | ||
| 21 | bind_interrupts!(struct Irqs { | ||
| 22 | USART1 => usart::InterruptHandler<peripherals::USART1>; | ||
| 23 | }); | ||
| 24 | |||
| 25 | #[cfg(feature = "stm32u585ai")] | ||
| 26 | bind_interrupts!(struct Irqs { | ||
| 27 | USART3 => usart::InterruptHandler<peripherals::USART3>; | ||
| 28 | }); | ||
| 29 | |||
| 30 | #[cfg(feature = "stm32f429zi")] | ||
| 31 | bind_interrupts!(struct Irqs { | ||
| 32 | USART6 => usart::InterruptHandler<peripherals::USART6>; | ||
| 33 | }); | ||
| 34 | |||
| 35 | #[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))] | ||
| 36 | bind_interrupts!(struct Irqs { | ||
| 37 | LPUART1 => usart::InterruptHandler<peripherals::LPUART1>; | ||
| 38 | }); | ||
| 39 | |||
| 14 | #[embassy_executor::main] | 40 | #[embassy_executor::main] |
| 15 | async fn main(_spawner: Spawner) { | 41 | async 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 @@ | |||
| 8 | mod example_common; | 8 | mod example_common; |
| 9 | use defmt::{assert_eq, panic}; | 9 | use defmt::{assert_eq, panic}; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::interrupt; | ||
| 12 | use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx}; | 11 | use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx}; |
| 12 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 13 | use embassy_time::{Duration, Timer}; | 13 | use embassy_time::{Duration, Timer}; |
| 14 | use example_common::*; | 14 | use example_common::*; |
| 15 | use rand_chacha::ChaCha8Rng; | 15 | use rand_chacha::ChaCha8Rng; |
| 16 | use rand_core::{RngCore, SeedableRng}; | 16 | use 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 | ))] | ||
| 25 | bind_interrupts!(struct Irqs { | ||
| 26 | USART1 => usart::InterruptHandler<peripherals::USART1>; | ||
| 27 | }); | ||
| 28 | |||
| 29 | #[cfg(feature = "stm32u585ai")] | ||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | USART3 => usart::InterruptHandler<peripherals::USART3>; | ||
| 32 | }); | ||
| 33 | |||
| 34 | #[cfg(feature = "stm32f429zi")] | ||
| 35 | bind_interrupts!(struct Irqs { | ||
| 36 | USART1 => usart::InterruptHandler<peripherals::USART1>; | ||
| 37 | USART6 => usart::InterruptHandler<peripherals::USART6>; | ||
| 38 | }); | ||
| 39 | |||
| 40 | #[cfg(any(feature = "stm32wb55rg", feature = "stm32h563zi"))] | ||
| 41 | bind_interrupts!(struct Irqs { | ||
| 42 | LPUART1 => usart::InterruptHandler<peripherals::LPUART1>; | ||
| 43 | }); | ||
| 44 | |||
| 18 | #[cfg(feature = "stm32f103c8")] | 45 | #[cfg(feature = "stm32f103c8")] |
| 19 | mod board { | 46 | mod 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() }; |
