aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreZio Pan <[email protected]>2024-01-02 11:55:09 +0800
committerGitHub <[email protected]>2024-01-02 11:55:09 +0800
commitf5a218a018d3ecd899db0ec5460a4e00dac78abe (patch)
treef4bce8b63044bf2de9277385d229b4dbaf4c53e2
parent873ee0615147b4a4e0aacd069ce8ac8df611bbbf (diff)
parent9c2d2ff64d302437e2e0568372c76bf37bbfacf4 (diff)
Merge branch 'embassy-rs:main' into simplepwm-dma
-rw-r--r--README.md3
-rwxr-xr-xci.sh3
-rw-r--r--docs/modules/ROOT/pages/index.adoc2
-rw-r--r--embassy-executor-macros/src/macros/task.rs19
-rw-r--r--embassy-executor/tests/test.rs14
-rw-r--r--embassy-net/src/udp.rs5
-rw-r--r--embassy-nrf/src/buffered_uarte.rs1
-rw-r--r--embassy-nrf/src/gpio.rs34
-rw-r--r--embassy-stm32/src/i2c/v1.rs20
-rw-r--r--embassy-stm32/src/lib.rs50
-rw-r--r--embassy-stm32/src/rtc/mod.rs20
-rw-r--r--embassy-stm32/src/rtc/v3.rs6
-rw-r--r--embassy-stm32/src/usart/mod.rs87
-rw-r--r--embassy-stm32/src/usb/usb.rs6
-rw-r--r--rust-toolchain.toml2
15 files changed, 222 insertions, 50 deletions
diff --git a/README.md b/README.md
index 7ae40fe59..714104331 100644
--- a/README.md
+++ b/README.md
@@ -35,8 +35,7 @@ The <a href="https://docs.embassy.dev/embassy-net/">embassy-net</a> network stac
35The <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. 35The <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.
36The <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. 36The <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.
diff --git a/ci.sh b/ci.sh
index 933e54a80..75640e384 100755
--- a/ci.sh
+++ b/ci.sh
@@ -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.
211rm out/tests/rpi-pico/i2c
212
210rm out/tests/stm32wb55rg/wpan_mac 213rm out/tests/stm32wb55rg/wpan_mac
211rm out/tests/stm32wb55rg/wpan_ble 214rm 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
41The link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. 41The 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
44link: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. 44link: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
47link: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. 47link: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]
140fn 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
227impl Drop for UdpSocket<'_> { 232impl 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
579impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> { 613impl<'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
1use core::future::poll_fn; 7use core::future::poll_fn;
2use core::task::Poll; 8use core::task::Poll;
3 9
@@ -10,6 +16,17 @@ use crate::dma::Transfer;
10use crate::pac::i2c; 16use crate::pac::i2c;
11use crate::time::Hertz; 17use 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!
13pub unsafe fn on_interrupt<T: Instance>() { 30pub 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")]
28mod _version; 28mod _version;
29#[allow(unused_imports)] 29#[allow(unused_imports)]
30pub use _version::*; 30pub 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))]
47impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { 47impl 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))]
61impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { 61impl 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]
2channel = "beta-2023-12-17" 2channel = "1.75"
3components = [ "rust-src", "rustfmt", "llvm-tools" ] 3components = [ "rust-src", "rustfmt", "llvm-tools" ]
4targets = [ 4targets = [
5 "thumbv7em-none-eabi", 5 "thumbv7em-none-eabi",