diff options
| author | eZio Pan <[email protected]> | 2024-01-02 11:55:09 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-01-02 11:55:09 +0800 |
| commit | f5a218a018d3ecd899db0ec5460a4e00dac78abe (patch) | |
| tree | f4bce8b63044bf2de9277385d229b4dbaf4c53e2 | |
| parent | 873ee0615147b4a4e0aacd069ce8ac8df611bbbf (diff) | |
| parent | 9c2d2ff64d302437e2e0568372c76bf37bbfacf4 (diff) | |
Merge branch 'embassy-rs:main' into simplepwm-dma
| -rw-r--r-- | README.md | 3 | ||||
| -rwxr-xr-x | ci.sh | 3 | ||||
| -rw-r--r-- | docs/modules/ROOT/pages/index.adoc | 2 | ||||
| -rw-r--r-- | embassy-executor-macros/src/macros/task.rs | 19 | ||||
| -rw-r--r-- | embassy-executor/tests/test.rs | 14 | ||||
| -rw-r--r-- | embassy-net/src/udp.rs | 5 | ||||
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 1 | ||||
| -rw-r--r-- | embassy-nrf/src/gpio.rs | 34 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v1.rs | 20 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 50 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/mod.rs | 20 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/v3.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 87 | ||||
| -rw-r--r-- | embassy-stm32/src/usb/usb.rs | 6 | ||||
| -rw-r--r-- | rust-toolchain.toml | 2 |
15 files changed, 222 insertions, 50 deletions
| @@ -35,8 +35,7 @@ The <a href="https://docs.embassy.dev/embassy-net/">embassy-net</a> network stac | |||
| 35 | The <a href="https://github.com/embassy-rs/nrf-softdevice">nrf-softdevice</a> crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. | 35 | The <a href="https://github.com/embassy-rs/nrf-softdevice">nrf-softdevice</a> crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. |
| 36 | The <a href="https://github.com/embassy-rs/embassy/tree/main/embassy-stm32-wpan">embassy-stm32-wpan</a> crate provides Bluetooth Low Energy 5.x support for stm32wb microcontrollers. | 36 | The <a href="https://github.com/embassy-rs/embassy/tree/main/embassy-stm32-wpan">embassy-stm32-wpan</a> crate provides Bluetooth Low Energy 5.x support for stm32wb microcontrollers. |
| 37 | 37 | ||
| 38 | - **LoRa** - | 38 | - **LoRa** - The <a href="https://github.com/lora-rs/lora-rs">lora-rs</a> project provides an async LoRa and LoRaWAN stack that works well on Embassy. |
| 39 | <a href="hthttps://github.com/lora-rs/lora-rs">The lora-rs project</a> provides an async LoRa and LoRaWAN stack that works well on Embassy. | ||
| 40 | 39 | ||
| 41 | - **USB** - | 40 | - **USB** - |
| 42 | <a href="https://docs.embassy.dev/embassy-usb/">embassy-usb</a> implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own. | 41 | <a href="https://docs.embassy.dev/embassy-usb/">embassy-usb</a> implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own. |
| @@ -207,6 +207,9 @@ cargo batch \ | |||
| 207 | $BUILD_EXTRA | 207 | $BUILD_EXTRA |
| 208 | 208 | ||
| 209 | 209 | ||
| 210 | # failed, a wire must've come loose, will check asap. | ||
| 211 | rm out/tests/rpi-pico/i2c | ||
| 212 | |||
| 210 | rm out/tests/stm32wb55rg/wpan_mac | 213 | rm out/tests/stm32wb55rg/wpan_mac |
| 211 | rm out/tests/stm32wb55rg/wpan_ble | 214 | rm out/tests/stm32wb55rg/wpan_ble |
| 212 | 215 | ||
diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 6fba80eda..e17adbbd7 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc | |||
| @@ -41,7 +41,7 @@ The link:https://docs.embassy.dev/embassy-net/[embassy-net] network stack implem | |||
| 41 | The link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. | 41 | The link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. |
| 42 | 42 | ||
| 43 | === LoRa | 43 | === LoRa |
| 44 | link:https://github.com/embassy-rs/lora-phy[lora-phy] and link:https://docs.embassy.dev/embassy-lora/[embassy-lora] supports LoRa networking on a wide range of LoRa radios, fully integrated with a Rust link:https://github.com/ivajloip/rust-lorawan[LoRaWAN] implementation. | 44 | link:https://github.com/lora-rs/lora-rs[lora-rs] supports LoRa networking on a wide range of LoRa radios, fully integrated with a Rust LoRaWAN implementation. It provides four crates — lora-phy, lora-modulation, lorawan-encoding, and lorawan-device — and basic examples for various development boards. It has support for STM32WL wireless microcontrollers or Semtech SX127x transceivers, among others. |
| 45 | 45 | ||
| 46 | === USB | 46 | === USB |
| 47 | link:https://docs.embassy.dev/embassy-usb/[embassy-usb] implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own. | 47 | link:https://docs.embassy.dev/embassy-usb/[embassy-usb] implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own. |
diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index 5161e1020..1efb2788b 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs | |||
| @@ -49,7 +49,7 @@ pub fn run(args: &[NestedMeta], f: syn::ItemFn) -> Result<TokenStream, TokenStre | |||
| 49 | }, | 49 | }, |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | let mut arg_names = Vec::new(); | 52 | let mut args = Vec::new(); |
| 53 | let mut fargs = f.sig.inputs.clone(); | 53 | let mut fargs = f.sig.inputs.clone(); |
| 54 | 54 | ||
| 55 | for arg in fargs.iter_mut() { | 55 | for arg in fargs.iter_mut() { |
| @@ -59,8 +59,8 @@ pub fn run(args: &[NestedMeta], f: syn::ItemFn) -> Result<TokenStream, TokenStre | |||
| 59 | } | 59 | } |
| 60 | syn::FnArg::Typed(t) => match t.pat.as_mut() { | 60 | syn::FnArg::Typed(t) => match t.pat.as_mut() { |
| 61 | syn::Pat::Ident(id) => { | 61 | syn::Pat::Ident(id) => { |
| 62 | arg_names.push(id.ident.clone()); | ||
| 63 | id.mutability = None; | 62 | id.mutability = None; |
| 63 | args.push((id.clone(), t.attrs.clone())); | ||
| 64 | } | 64 | } |
| 65 | _ => { | 65 | _ => { |
| 66 | ctxt.error_spanned_by(arg, "pattern matching in task arguments is not yet supported"); | 66 | ctxt.error_spanned_by(arg, "pattern matching in task arguments is not yet supported"); |
| @@ -79,13 +79,24 @@ pub fn run(args: &[NestedMeta], f: syn::ItemFn) -> Result<TokenStream, TokenStre | |||
| 79 | task_inner.vis = syn::Visibility::Inherited; | 79 | task_inner.vis = syn::Visibility::Inherited; |
| 80 | task_inner.sig.ident = task_inner_ident.clone(); | 80 | task_inner.sig.ident = task_inner_ident.clone(); |
| 81 | 81 | ||
| 82 | // assemble the original input arguments, | ||
| 83 | // including any attributes that may have | ||
| 84 | // been applied previously | ||
| 85 | let mut full_args = Vec::new(); | ||
| 86 | for (arg, cfgs) in args { | ||
| 87 | full_args.push(quote!( | ||
| 88 | #(#cfgs)* | ||
| 89 | #arg | ||
| 90 | )); | ||
| 91 | } | ||
| 92 | |||
| 82 | #[cfg(feature = "nightly")] | 93 | #[cfg(feature = "nightly")] |
| 83 | let mut task_outer: ItemFn = parse_quote! { | 94 | let mut task_outer: ItemFn = parse_quote! { |
| 84 | #visibility fn #task_ident(#fargs) -> ::embassy_executor::SpawnToken<impl Sized> { | 95 | #visibility fn #task_ident(#fargs) -> ::embassy_executor::SpawnToken<impl Sized> { |
| 85 | type Fut = impl ::core::future::Future + 'static; | 96 | type Fut = impl ::core::future::Future + 'static; |
| 86 | const POOL_SIZE: usize = #pool_size; | 97 | const POOL_SIZE: usize = #pool_size; |
| 87 | static POOL: ::embassy_executor::raw::TaskPool<Fut, POOL_SIZE> = ::embassy_executor::raw::TaskPool::new(); | 98 | static POOL: ::embassy_executor::raw::TaskPool<Fut, POOL_SIZE> = ::embassy_executor::raw::TaskPool::new(); |
| 88 | unsafe { POOL._spawn_async_fn(move || #task_inner_ident(#(#arg_names,)*)) } | 99 | unsafe { POOL._spawn_async_fn(move || #task_inner_ident(#(#full_args,)*)) } |
| 89 | } | 100 | } |
| 90 | }; | 101 | }; |
| 91 | #[cfg(not(feature = "nightly"))] | 102 | #[cfg(not(feature = "nightly"))] |
| @@ -93,7 +104,7 @@ pub fn run(args: &[NestedMeta], f: syn::ItemFn) -> Result<TokenStream, TokenStre | |||
| 93 | #visibility fn #task_ident(#fargs) -> ::embassy_executor::SpawnToken<impl Sized> { | 104 | #visibility fn #task_ident(#fargs) -> ::embassy_executor::SpawnToken<impl Sized> { |
| 94 | const POOL_SIZE: usize = #pool_size; | 105 | const POOL_SIZE: usize = #pool_size; |
| 95 | static POOL: ::embassy_executor::_export::TaskPoolRef = ::embassy_executor::_export::TaskPoolRef::new(); | 106 | static POOL: ::embassy_executor::_export::TaskPoolRef = ::embassy_executor::_export::TaskPoolRef::new(); |
| 96 | unsafe { POOL.get::<_, POOL_SIZE>()._spawn_async_fn(move || #task_inner_ident(#(#arg_names,)*)) } | 107 | unsafe { POOL.get::<_, POOL_SIZE>()._spawn_async_fn(move || #task_inner_ident(#(#full_args,)*)) } |
| 97 | } | 108 | } |
| 98 | }; | 109 | }; |
| 99 | 110 | ||
diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index 0dbd391e8..2c2441dd5 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs | |||
| @@ -135,3 +135,17 @@ fn executor_task_self_wake_twice() { | |||
| 135 | ] | 135 | ] |
| 136 | ) | 136 | ) |
| 137 | } | 137 | } |
| 138 | |||
| 139 | #[test] | ||
| 140 | fn executor_task_cfg_args() { | ||
| 141 | // simulate cfg'ing away argument c | ||
| 142 | #[task] | ||
| 143 | async fn task1(a: u32, b: u32, #[cfg(any())] c: u32) { | ||
| 144 | let (_, _) = (a, b); | ||
| 145 | } | ||
| 146 | |||
| 147 | #[task] | ||
| 148 | async fn task2(a: u32, b: u32, #[cfg(all())] c: u32) { | ||
| 149 | let (_, _, _) = (a, b, c); | ||
| 150 | } | ||
| 151 | } | ||
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index d9df5b29d..a22cd8827 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs | |||
| @@ -222,6 +222,11 @@ impl<'a> UdpSocket<'a> { | |||
| 222 | pub fn payload_send_capacity(&self) -> usize { | 222 | pub fn payload_send_capacity(&self) -> usize { |
| 223 | self.with(|s, _| s.payload_send_capacity()) | 223 | self.with(|s, _| s.payload_send_capacity()) |
| 224 | } | 224 | } |
| 225 | |||
| 226 | /// Set the hop limit field in the IP header of sent packets. | ||
| 227 | pub fn set_hop_limit(&mut self, hop_limit: Option<u8>) { | ||
| 228 | self.with_mut(|s, _| s.set_hop_limit(hop_limit)) | ||
| 229 | } | ||
| 225 | } | 230 | } |
| 226 | 231 | ||
| 227 | impl Drop for UdpSocket<'_> { | 232 | impl Drop for UdpSocket<'_> { |
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 4ac622d34..2c620798d 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -342,6 +342,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 342 | s.tx_count.store(0, Ordering::Relaxed); | 342 | s.tx_count.store(0, Ordering::Relaxed); |
| 343 | s.rx_started_count.store(0, Ordering::Relaxed); | 343 | s.rx_started_count.store(0, Ordering::Relaxed); |
| 344 | s.rx_ended_count.store(0, Ordering::Relaxed); | 344 | s.rx_ended_count.store(0, Ordering::Relaxed); |
| 345 | s.rx_started.store(false, Ordering::Relaxed); | ||
| 345 | let len = tx_buffer.len(); | 346 | let len = tx_buffer.len(); |
| 346 | unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; | 347 | unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; |
| 347 | let len = rx_buffer.len(); | 348 | let len = rx_buffer.len(); |
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index a47fb8350..27c18383f 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -152,6 +152,12 @@ impl<'d, T: Pin> Output<'d, T> { | |||
| 152 | self.pin.set_low() | 152 | self.pin.set_low() |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | /// Toggle the output level. | ||
| 156 | #[inline] | ||
| 157 | pub fn toggle(&mut self) { | ||
| 158 | self.pin.toggle() | ||
| 159 | } | ||
| 160 | |||
| 155 | /// Set the output level. | 161 | /// Set the output level. |
| 156 | #[inline] | 162 | #[inline] |
| 157 | pub fn set_level(&mut self, level: Level) { | 163 | pub fn set_level(&mut self, level: Level) { |
| @@ -310,6 +316,16 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 310 | self.pin.set_low() | 316 | self.pin.set_low() |
| 311 | } | 317 | } |
| 312 | 318 | ||
| 319 | /// Toggle the output level. | ||
| 320 | #[inline] | ||
| 321 | pub fn toggle(&mut self) { | ||
| 322 | if self.is_set_low() { | ||
| 323 | self.set_high() | ||
| 324 | } else { | ||
| 325 | self.set_low() | ||
| 326 | } | ||
| 327 | } | ||
| 328 | |||
| 313 | /// Set the output level. | 329 | /// Set the output level. |
| 314 | #[inline] | 330 | #[inline] |
| 315 | pub fn set_level(&mut self, level: Level) { | 331 | pub fn set_level(&mut self, level: Level) { |
| @@ -538,6 +554,15 @@ mod eh02 { | |||
| 538 | } | 554 | } |
| 539 | } | 555 | } |
| 540 | 556 | ||
| 557 | impl<'d, T: Pin> embedded_hal_02::digital::v2::ToggleableOutputPin for Output<'d, T> { | ||
| 558 | type Error = Infallible; | ||
| 559 | #[inline] | ||
| 560 | fn toggle(&mut self) -> Result<(), Self::Error> { | ||
| 561 | self.toggle(); | ||
| 562 | Ok(()) | ||
| 563 | } | ||
| 564 | } | ||
| 565 | |||
| 541 | /// Implement [`embedded_hal_02::digital::v2::InputPin`] for [`Flex`]; | 566 | /// Implement [`embedded_hal_02::digital::v2::InputPin`] for [`Flex`]; |
| 542 | /// | 567 | /// |
| 543 | /// If the pin is not in input mode the result is unspecified. | 568 | /// If the pin is not in input mode the result is unspecified. |
| @@ -574,6 +599,15 @@ mod eh02 { | |||
| 574 | Ok(self.ref_is_set_low()) | 599 | Ok(self.ref_is_set_low()) |
| 575 | } | 600 | } |
| 576 | } | 601 | } |
| 602 | |||
| 603 | impl<'d, T: Pin> embedded_hal_02::digital::v2::ToggleableOutputPin for Flex<'d, T> { | ||
| 604 | type Error = Infallible; | ||
| 605 | #[inline] | ||
| 606 | fn toggle(&mut self) -> Result<(), Self::Error> { | ||
| 607 | self.toggle(); | ||
| 608 | Ok(()) | ||
| 609 | } | ||
| 610 | } | ||
| 577 | } | 611 | } |
| 578 | 612 | ||
| 579 | impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> { | 613 | impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> { |
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index df5b44c2d..cbbc201de 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | //! # I2Cv1 | ||
| 2 | //! | ||
| 3 | //! This implementation is used for STM32F1, STM32F2, STM32F4, and STM32L1 devices. | ||
| 4 | //! | ||
| 5 | //! All other devices (as of 2023-12-28) use [`v2`](super::v2) instead. | ||
| 6 | |||
| 1 | use core::future::poll_fn; | 7 | use core::future::poll_fn; |
| 2 | use core::task::Poll; | 8 | use core::task::Poll; |
| 3 | 9 | ||
| @@ -10,6 +16,17 @@ use crate::dma::Transfer; | |||
| 10 | use crate::pac::i2c; | 16 | use crate::pac::i2c; |
| 11 | use crate::time::Hertz; | 17 | use crate::time::Hertz; |
| 12 | 18 | ||
| 19 | // /!\ /!\ | ||
| 20 | // /!\ Implementation note! /!\ | ||
| 21 | // /!\ /!\ | ||
| 22 | // | ||
| 23 | // It's somewhat unclear whether using interrupts here in a *strictly* one-shot style is actually | ||
| 24 | // what we want! If you are looking in this file because you are doing async I2C and your code is | ||
| 25 | // just totally hanging (sometimes), maybe swing by this issue: | ||
| 26 | // <https://github.com/embassy-rs/embassy/issues/2372>. | ||
| 27 | // | ||
| 28 | // There's some more details there, and we might have a fix for you. But please let us know if you | ||
| 29 | // hit a case like this! | ||
| 13 | pub unsafe fn on_interrupt<T: Instance>() { | 30 | pub unsafe fn on_interrupt<T: Instance>() { |
| 14 | let regs = T::regs(); | 31 | let regs = T::regs(); |
| 15 | // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of | 32 | // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of |
| @@ -375,6 +392,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 375 | T::regs().sr2().read(); | 392 | T::regs().sr2().read(); |
| 376 | Poll::Ready(Ok(())) | 393 | Poll::Ready(Ok(())) |
| 377 | } else { | 394 | } else { |
| 395 | // If we need to go around, then re-enable the interrupts, otherwise nothing | ||
| 396 | // can wake us up and we'll hang. | ||
| 397 | Self::enable_interrupts(); | ||
| 378 | Poll::Pending | 398 | Poll::Pending |
| 379 | } | 399 | } |
| 380 | } | 400 | } |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 207f7ed8f..f10e9d50d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -208,32 +208,30 @@ pub fn init(config: Config) -> Peripherals { | |||
| 208 | let p = Peripherals::take_with_cs(cs); | 208 | let p = Peripherals::take_with_cs(cs); |
| 209 | 209 | ||
| 210 | #[cfg(dbgmcu)] | 210 | #[cfg(dbgmcu)] |
| 211 | if config.enable_debug_during_sleep { | 211 | crate::pac::DBGMCU.cr().modify(|cr| { |
| 212 | crate::pac::DBGMCU.cr().modify(|cr| { | 212 | #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))] |
| 213 | #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))] | 213 | { |
| 214 | { | 214 | cr.set_dbg_stop(config.enable_debug_during_sleep); |
| 215 | cr.set_dbg_stop(true); | 215 | cr.set_dbg_standby(config.enable_debug_during_sleep); |
| 216 | cr.set_dbg_standby(true); | 216 | } |
| 217 | } | 217 | #[cfg(any( |
| 218 | #[cfg(any( | 218 | dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, |
| 219 | dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, | 219 | dbgmcu_l4, dbgmcu_wb, dbgmcu_wl |
| 220 | dbgmcu_l4, dbgmcu_wb, dbgmcu_wl | 220 | ))] |
| 221 | ))] | 221 | { |
| 222 | { | 222 | cr.set_dbg_sleep(config.enable_debug_during_sleep); |
| 223 | cr.set_dbg_sleep(true); | 223 | cr.set_dbg_stop(config.enable_debug_during_sleep); |
| 224 | cr.set_dbg_stop(true); | 224 | cr.set_dbg_standby(config.enable_debug_during_sleep); |
| 225 | cr.set_dbg_standby(true); | 225 | } |
| 226 | } | 226 | #[cfg(dbgmcu_h7)] |
| 227 | #[cfg(dbgmcu_h7)] | 227 | { |
| 228 | { | 228 | cr.set_d1dbgcken(config.enable_debug_during_sleep); |
| 229 | cr.set_d1dbgcken(true); | 229 | cr.set_d3dbgcken(config.enable_debug_during_sleep); |
| 230 | cr.set_d3dbgcken(true); | 230 | cr.set_dbgsleep_d1(config.enable_debug_during_sleep); |
| 231 | cr.set_dbgsleep_d1(true); | 231 | cr.set_dbgstby_d1(config.enable_debug_during_sleep); |
| 232 | cr.set_dbgstby_d1(true); | 232 | cr.set_dbgstop_d1(config.enable_debug_during_sleep); |
| 233 | cr.set_dbgstop_d1(true); | 233 | } |
| 234 | } | 234 | }); |
| 235 | }); | ||
| 236 | } | ||
| 237 | 235 | ||
| 238 | #[cfg(not(any(stm32f1, stm32wb, stm32wl)))] | 236 | #[cfg(not(any(stm32f1, stm32wb, stm32wl)))] |
| 239 | peripherals::SYSCFG::enable_and_reset_with_cs(cs); | 237 | peripherals::SYSCFG::enable_and_reset_with_cs(cs); |
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 65e8713f0..1ffb567b3 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs | |||
| @@ -24,7 +24,7 @@ use crate::time::Hertz; | |||
| 24 | ), | 24 | ), |
| 25 | path = "v2.rs" | 25 | path = "v2.rs" |
| 26 | )] | 26 | )] |
| 27 | #[cfg_attr(any(rtc_v3, rtc_v3u5), path = "v3.rs")] | 27 | #[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5), path = "v3.rs")] |
| 28 | mod _version; | 28 | mod _version; |
| 29 | #[allow(unused_imports)] | 29 | #[allow(unused_imports)] |
| 30 | pub use _version::*; | 30 | pub use _version::*; |
| @@ -43,7 +43,7 @@ pub(crate) enum WakeupPrescaler { | |||
| 43 | Div16 = 16, | 43 | Div16 = 16, |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4))] | 46 | #[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4, stm32l5))] |
| 47 | impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { | 47 | impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { |
| 48 | fn from(val: WakeupPrescaler) -> Self { | 48 | fn from(val: WakeupPrescaler) -> Self { |
| 49 | use crate::pac::rtc::vals::Wucksel; | 49 | use crate::pac::rtc::vals::Wucksel; |
| @@ -57,7 +57,7 @@ impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { | |||
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | #[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4))] | 60 | #[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4, stm32l5))] |
| 61 | impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { | 61 | impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { |
| 62 | fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { | 62 | fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { |
| 63 | use crate::pac::rtc::vals::Wucksel; | 63 | use crate::pac::rtc::vals::Wucksel; |
| @@ -348,7 +348,7 @@ impl Rtc { | |||
| 348 | ) { | 348 | ) { |
| 349 | use embassy_time::{Duration, TICK_HZ}; | 349 | use embassy_time::{Duration, TICK_HZ}; |
| 350 | 350 | ||
| 351 | #[cfg(any(rtc_v3, rtc_v3u5))] | 351 | #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))] |
| 352 | use crate::pac::rtc::vals::Calrf; | 352 | use crate::pac::rtc::vals::Calrf; |
| 353 | 353 | ||
| 354 | // Panic if the rcc mod knows we're not using low-power rtc | 354 | // Panic if the rcc mod knows we're not using low-power rtc |
| @@ -375,7 +375,7 @@ impl Rtc { | |||
| 375 | while !regs.isr().read().wutwf() {} | 375 | while !regs.isr().read().wutwf() {} |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | #[cfg(any(rtc_v3, rtc_v3u5))] | 378 | #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))] |
| 379 | { | 379 | { |
| 380 | regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); | 380 | regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); |
| 381 | while !regs.icsr().read().wutwf() {} | 381 | while !regs.icsr().read().wutwf() {} |
| @@ -404,7 +404,7 @@ impl Rtc { | |||
| 404 | /// was called, otherwise none | 404 | /// was called, otherwise none |
| 405 | pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> { | 405 | pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> { |
| 406 | use crate::interrupt::typelevel::Interrupt; | 406 | use crate::interrupt::typelevel::Interrupt; |
| 407 | #[cfg(any(rtc_v3, rtc_v3u5))] | 407 | #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))] |
| 408 | use crate::pac::rtc::vals::Calrf; | 408 | use crate::pac::rtc::vals::Calrf; |
| 409 | 409 | ||
| 410 | let instant = self.instant().unwrap(); | 410 | let instant = self.instant().unwrap(); |
| @@ -420,13 +420,19 @@ impl Rtc { | |||
| 420 | ))] | 420 | ))] |
| 421 | regs.isr().modify(|w| w.set_wutf(false)); | 421 | regs.isr().modify(|w| w.set_wutf(false)); |
| 422 | 422 | ||
| 423 | #[cfg(any(rtc_v3, rtc_v3u5))] | 423 | #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))] |
| 424 | regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); | 424 | regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); |
| 425 | 425 | ||
| 426 | #[cfg(not(stm32l5))] | ||
| 426 | crate::pac::EXTI | 427 | crate::pac::EXTI |
| 427 | .pr(0) | 428 | .pr(0) |
| 428 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); | 429 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); |
| 429 | 430 | ||
| 431 | #[cfg(stm32l5)] | ||
| 432 | crate::pac::EXTI | ||
| 433 | .fpr(0) | ||
| 434 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); | ||
| 435 | |||
| 430 | <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend(); | 436 | <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend(); |
| 431 | }); | 437 | }); |
| 432 | } | 438 | } |
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 902776b0a..114141b64 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs | |||
| @@ -135,6 +135,12 @@ impl sealed::Instance for crate::peripherals::RTC { | |||
| 135 | #[cfg(all(feature = "low-power", stm32g4))] | 135 | #[cfg(all(feature = "low-power", stm32g4))] |
| 136 | type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; | 136 | type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; |
| 137 | 137 | ||
| 138 | #[cfg(all(feature = "low-power", stm32l5))] | ||
| 139 | const EXTI_WAKEUP_LINE: usize = 17; | ||
| 140 | |||
| 141 | #[cfg(all(feature = "low-power", stm32l5))] | ||
| 142 | type WakeupInterrupt = crate::interrupt::typelevel::RTC; | ||
| 143 | |||
| 138 | fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> { | 144 | fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> { |
| 139 | #[allow(clippy::if_same_then_else)] | 145 | #[allow(clippy::if_same_then_else)] |
| 140 | if register < Self::BACKUP_REGISTER_COUNT { | 146 | if register < Self::BACKUP_REGISTER_COUNT { |
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 8a0c85d2c..ea727b010 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -743,7 +743,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 743 | T::enable_and_reset(); | 743 | T::enable_and_reset(); |
| 744 | T::enable_and_reset(); | 744 | T::enable_and_reset(); |
| 745 | 745 | ||
| 746 | Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) | 746 | Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config) |
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins | 749 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins |
| @@ -770,7 +770,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 770 | w.set_rtse(true); | 770 | w.set_rtse(true); |
| 771 | w.set_ctse(true); | 771 | w.set_ctse(true); |
| 772 | }); | 772 | }); |
| 773 | Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) | 773 | Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config) |
| 774 | } | 774 | } |
| 775 | 775 | ||
| 776 | #[cfg(not(any(usart_v1, usart_v2)))] | 776 | #[cfg(not(any(usart_v1, usart_v2)))] |
| @@ -795,10 +795,76 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 795 | T::regs().cr3().write(|w| { | 795 | T::regs().cr3().write(|w| { |
| 796 | w.set_dem(true); | 796 | w.set_dem(true); |
| 797 | }); | 797 | }); |
| 798 | Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) | 798 | Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config) |
| 799 | } | 799 | } |
| 800 | 800 | ||
| 801 | fn new_inner( | 801 | /// Create a single-wire half-duplex Uart transceiver on a single Tx pin. |
| 802 | /// | ||
| 803 | /// See [`new_half_duplex_on_rx`][`Self::new_half_duplex_on_rx`] if you would prefer to use an Rx pin. | ||
| 804 | /// There is no functional difference between these methods, as both allow bidirectional communication. | ||
| 805 | /// | ||
| 806 | /// The pin is always released when no data is transmitted. Thus, it acts as a standard | ||
| 807 | /// I/O in idle or in reception. | ||
| 808 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict | ||
| 809 | /// on the line must be managed by software (for instance by using a centralized arbiter). | ||
| 810 | #[cfg(not(any(usart_v1, usart_v2)))] | ||
| 811 | #[doc(alias("HDSEL"))] | ||
| 812 | pub fn new_half_duplex( | ||
| 813 | peri: impl Peripheral<P = T> + 'd, | ||
| 814 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | ||
| 815 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||
| 816 | tx_dma: impl Peripheral<P = TxDma> + 'd, | ||
| 817 | rx_dma: impl Peripheral<P = RxDma> + 'd, | ||
| 818 | mut config: Config, | ||
| 819 | ) -> Result<Self, ConfigError> { | ||
| 820 | // UartRx and UartTx have one refcount ea. | ||
| 821 | T::enable_and_reset(); | ||
| 822 | T::enable_and_reset(); | ||
| 823 | |||
| 824 | config.swap_rx_tx = false; | ||
| 825 | |||
| 826 | into_ref!(peri, tx, tx_dma, rx_dma); | ||
| 827 | |||
| 828 | T::regs().cr3().write(|w| w.set_hdsel(true)); | ||
| 829 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | ||
| 830 | |||
| 831 | Self::new_inner(peri, tx_dma, rx_dma, config) | ||
| 832 | } | ||
| 833 | |||
| 834 | /// Create a single-wire half-duplex Uart transceiver on a single Rx pin. | ||
| 835 | /// | ||
| 836 | /// See [`new_half_duplex`][`Self::new_half_duplex`] if you would prefer to use an Tx pin. | ||
| 837 | /// There is no functional difference between these methods, as both allow bidirectional communication. | ||
| 838 | /// | ||
| 839 | /// The pin is always released when no data is transmitted. Thus, it acts as a standard | ||
| 840 | /// I/O in idle or in reception. | ||
| 841 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict | ||
| 842 | /// on the line must be managed by software (for instance by using a centralized arbiter). | ||
| 843 | #[cfg(not(any(usart_v1, usart_v2)))] | ||
| 844 | #[doc(alias("HDSEL"))] | ||
| 845 | pub fn new_half_duplex_on_rx( | ||
| 846 | peri: impl Peripheral<P = T> + 'd, | ||
| 847 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | ||
| 848 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||
| 849 | tx_dma: impl Peripheral<P = TxDma> + 'd, | ||
| 850 | rx_dma: impl Peripheral<P = RxDma> + 'd, | ||
| 851 | mut config: Config, | ||
| 852 | ) -> Result<Self, ConfigError> { | ||
| 853 | // UartRx and UartTx have one refcount ea. | ||
| 854 | T::enable_and_reset(); | ||
| 855 | T::enable_and_reset(); | ||
| 856 | |||
| 857 | config.swap_rx_tx = true; | ||
| 858 | |||
| 859 | into_ref!(peri, rx, tx_dma, rx_dma); | ||
| 860 | |||
| 861 | T::regs().cr3().write(|w| w.set_hdsel(true)); | ||
| 862 | rx.set_as_af(rx.af_num(), AFType::OutputPushPull); | ||
| 863 | |||
| 864 | Self::new_inner(peri, tx_dma, rx_dma, config) | ||
| 865 | } | ||
| 866 | |||
| 867 | fn new_inner_configure( | ||
| 802 | peri: impl Peripheral<P = T> + 'd, | 868 | peri: impl Peripheral<P = T> + 'd, |
| 803 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 869 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 804 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 870 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| @@ -808,8 +874,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 808 | ) -> Result<Self, ConfigError> { | 874 | ) -> Result<Self, ConfigError> { |
| 809 | into_ref!(peri, rx, tx, tx_dma, rx_dma); | 875 | into_ref!(peri, rx, tx, tx_dma, rx_dma); |
| 810 | 876 | ||
| 811 | let r = T::regs(); | ||
| 812 | |||
| 813 | // Some chips do not have swap_rx_tx bit | 877 | // Some chips do not have swap_rx_tx bit |
| 814 | cfg_if::cfg_if! { | 878 | cfg_if::cfg_if! { |
| 815 | if #[cfg(any(usart_v3, usart_v4))] { | 879 | if #[cfg(any(usart_v3, usart_v4))] { |
| @@ -827,6 +891,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 827 | } | 891 | } |
| 828 | } | 892 | } |
| 829 | 893 | ||
| 894 | Self::new_inner(peri, tx_dma, rx_dma, config) | ||
| 895 | } | ||
| 896 | |||
| 897 | fn new_inner( | ||
| 898 | peri: PeripheralRef<'d, T>, | ||
| 899 | tx_dma: PeripheralRef<'d, TxDma>, | ||
| 900 | rx_dma: PeripheralRef<'d, RxDma>, | ||
| 901 | config: Config, | ||
| 902 | ) -> Result<Self, ConfigError> { | ||
| 903 | let r = T::regs(); | ||
| 904 | |||
| 830 | configure(r, &config, T::frequency(), T::KIND, true, true)?; | 905 | configure(r, &config, T::frequency(), T::KIND, true, true)?; |
| 831 | 906 | ||
| 832 | T::Interrupt::unpend(); | 907 | T::Interrupt::unpend(); |
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index a8aebfe1f..04b1b35e8 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs | |||
| @@ -701,10 +701,10 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> { | |||
| 701 | } | 701 | } |
| 702 | 702 | ||
| 703 | async fn wait_enabled(&mut self) { | 703 | async fn wait_enabled(&mut self) { |
| 704 | trace!("wait_enabled OUT WAITING"); | 704 | trace!("wait_enabled IN WAITING"); |
| 705 | let index = self.info.addr.index(); | 705 | let index = self.info.addr.index(); |
| 706 | poll_fn(|cx| { | 706 | poll_fn(|cx| { |
| 707 | EP_OUT_WAKERS[index].register(cx.waker()); | 707 | EP_IN_WAKERS[index].register(cx.waker()); |
| 708 | let regs = T::regs(); | 708 | let regs = T::regs(); |
| 709 | if regs.epr(index).read().stat_tx() == Stat::DISABLED { | 709 | if regs.epr(index).read().stat_tx() == Stat::DISABLED { |
| 710 | Poll::Pending | 710 | Poll::Pending |
| @@ -713,7 +713,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> { | |||
| 713 | } | 713 | } |
| 714 | }) | 714 | }) |
| 715 | .await; | 715 | .await; |
| 716 | trace!("wait_enabled OUT OK"); | 716 | trace!("wait_enabled IN OK"); |
| 717 | } | 717 | } |
| 718 | } | 718 | } |
| 719 | 719 | ||
diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e1af0b647..a6fe52ee2 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [toolchain] | 1 | [toolchain] |
| 2 | channel = "beta-2023-12-17" | 2 | channel = "1.75" |
| 3 | components = [ "rust-src", "rustfmt", "llvm-tools" ] | 3 | components = [ "rust-src", "rustfmt", "llvm-tools" ] |
| 4 | targets = [ | 4 | targets = [ |
| 5 | "thumbv7em-none-eabi", | 5 | "thumbv7em-none-eabi", |
