aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-25 11:47:44 -0600
committerxoviat <[email protected]>2025-11-25 11:47:44 -0600
commitd2d00b57c8bf5b6879c5df5021f44652d1fd52ee (patch)
treeca5111fbd03afd8238a5061a1e0f824d3a60a650 /embassy-stm32
parent906eaee53f84381dd10583894edf2de67275f083 (diff)
stm32: allow granular stop for uart
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/src/rcc/mod.rs39
-rw-r--r--embassy-stm32/src/usart/mod.rs20
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs3
4 files changed, 53 insertions, 10 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index d3e5ba48d..5c31b5a11 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7 7
8## Unreleased - ReleaseDate 8## Unreleased - ReleaseDate
9 9
10- feat: allow granular stop for regular usart
10- feat: Add continuous waveform method to SimplePWM 11- feat: Add continuous waveform method to SimplePWM
11- change: remove waveform timer method 12- change: remove waveform timer method
12- change: low power: store stop mode for dma channels 13- change: low power: store stop mode for dma channels
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 85434fa83..f38d9078d 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -234,9 +234,6 @@ impl RccInfo {
234 } 234 }
235 } 235 }
236 236
237 #[cfg(feature = "low-power")]
238 increment_stop_refcount(_cs, self.stop_mode);
239
240 // set the xxxRST bit 237 // set the xxxRST bit
241 let reset_ptr = self.reset_ptr(); 238 let reset_ptr = self.reset_ptr();
242 if let Some(reset_ptr) = reset_ptr { 239 if let Some(reset_ptr) = reset_ptr {
@@ -292,9 +289,6 @@ impl RccInfo {
292 } 289 }
293 } 290 }
294 291
295 #[cfg(feature = "low-power")]
296 decrement_stop_refcount(_cs, self.stop_mode);
297
298 // clear the xxxEN bit 292 // clear the xxxEN bit
299 let enable_ptr = self.enable_ptr(); 293 let enable_ptr = self.enable_ptr();
300 unsafe { 294 unsafe {
@@ -303,13 +297,46 @@ impl RccInfo {
303 } 297 }
304 } 298 }
305 299
300 pub(crate) fn increment_stop_refcount_with_cs(&self, _cs: CriticalSection) {
301 #[cfg(feature = "low-power")]
302 increment_stop_refcount(_cs, self.stop_mode);
303 }
304
305 pub(crate) fn increment_stop_refcount(&self) {
306 critical_section::with(|cs| self.increment_stop_refcount_with_cs(cs))
307 }
308
309 pub(crate) fn decrement_stop_refcount_with_cs(&self, _cs: CriticalSection) {
310 #[cfg(feature = "low-power")]
311 decrement_stop_refcount(_cs, self.stop_mode);
312 }
313
314 pub(crate) fn decrement_stop_refcount(&self) {
315 critical_section::with(|cs| self.decrement_stop_refcount_with_cs(cs))
316 }
317
306 // TODO: should this be `unsafe`? 318 // TODO: should this be `unsafe`?
307 pub(crate) fn enable_and_reset(&self) { 319 pub(crate) fn enable_and_reset(&self) {
320 critical_section::with(|cs| {
321 self.enable_and_reset_with_cs(cs);
322 self.increment_stop_refcount_with_cs(cs);
323 })
324 }
325
326 pub(crate) fn enable_and_reset_without_stop(&self) {
308 critical_section::with(|cs| self.enable_and_reset_with_cs(cs)) 327 critical_section::with(|cs| self.enable_and_reset_with_cs(cs))
309 } 328 }
310 329
311 // TODO: should this be `unsafe`? 330 // TODO: should this be `unsafe`?
312 pub(crate) fn disable(&self) { 331 pub(crate) fn disable(&self) {
332 critical_section::with(|cs| {
333 self.disable_with_cs(cs);
334 self.decrement_stop_refcount_with_cs(cs);
335 })
336 }
337
338 // TODO: should this be `unsafe`?
339 pub(crate) fn disable_without_stop(&self) {
313 critical_section::with(|cs| self.disable_with_cs(cs)) 340 critical_section::with(|cs| self.disable_with_cs(cs))
314 } 341 }
315 342
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 0e7da634d..1af78b358 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -491,6 +491,9 @@ impl<'d> UartTx<'d, Async> {
491 491
492 /// Initiate an asynchronous UART write 492 /// Initiate an asynchronous UART write
493 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 493 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
494 self.info.rcc.increment_stop_refcount();
495 let _ = OnDrop::new(|| self.info.rcc.decrement_stop_refcount());
496
494 let r = self.info.regs; 497 let r = self.info.regs;
495 498
496 half_duplex_set_rx_tx_before_write(&r, self.duplex == Duplex::Half(HalfDuplexReadback::Readback)); 499 half_duplex_set_rx_tx_before_write(&r, self.duplex == Duplex::Half(HalfDuplexReadback::Readback));
@@ -508,6 +511,9 @@ impl<'d> UartTx<'d, Async> {
508 511
509 /// Wait until transmission complete 512 /// Wait until transmission complete
510 pub async fn flush(&mut self) -> Result<(), Error> { 513 pub async fn flush(&mut self) -> Result<(), Error> {
514 self.info.rcc.increment_stop_refcount();
515 let _ = OnDrop::new(|| self.info.rcc.decrement_stop_refcount());
516
511 flush(&self.info, &self.state).await 517 flush(&self.info, &self.state).await
512 } 518 }
513} 519}
@@ -569,7 +575,7 @@ impl<'d, M: Mode> UartTx<'d, M> {
569 let state = self.state; 575 let state = self.state;
570 state.tx_rx_refcount.store(1, Ordering::Relaxed); 576 state.tx_rx_refcount.store(1, Ordering::Relaxed);
571 577
572 info.rcc.enable_and_reset(); 578 info.rcc.enable_and_reset_without_stop();
573 579
574 info.regs.cr3().modify(|w| { 580 info.regs.cr3().modify(|w| {
575 w.set_ctse(self.cts.is_some()); 581 w.set_ctse(self.cts.is_some());
@@ -726,6 +732,9 @@ impl<'d> UartRx<'d, Async> {
726 732
727 /// Initiate an asynchronous UART read 733 /// Initiate an asynchronous UART read
728 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 734 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
735 self.info.rcc.increment_stop_refcount();
736 let _ = OnDrop::new(|| self.info.rcc.decrement_stop_refcount());
737
729 self.inner_read(buffer, false).await?; 738 self.inner_read(buffer, false).await?;
730 739
731 Ok(()) 740 Ok(())
@@ -733,6 +742,9 @@ impl<'d> UartRx<'d, Async> {
733 742
734 /// Initiate an asynchronous read with idle line detection enabled 743 /// Initiate an asynchronous read with idle line detection enabled
735 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 744 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
745 self.info.rcc.increment_stop_refcount();
746 let _ = OnDrop::new(|| self.info.rcc.decrement_stop_refcount());
747
736 self.inner_read(buffer, true).await 748 self.inner_read(buffer, true).await
737 } 749 }
738 750
@@ -1004,7 +1016,7 @@ impl<'d, M: Mode> UartRx<'d, M> {
1004 .eager_reads 1016 .eager_reads
1005 .store(config.eager_reads.unwrap_or(0), Ordering::Relaxed); 1017 .store(config.eager_reads.unwrap_or(0), Ordering::Relaxed);
1006 1018
1007 info.rcc.enable_and_reset(); 1019 info.rcc.enable_and_reset_without_stop();
1008 1020
1009 info.regs.cr3().write(|w| { 1021 info.regs.cr3().write(|w| {
1010 w.set_rtse(self.rts.is_some()); 1022 w.set_rtse(self.rts.is_some());
@@ -1143,7 +1155,7 @@ fn drop_tx_rx(info: &Info, state: &State) {
1143 refcount == 1 1155 refcount == 1
1144 }); 1156 });
1145 if is_last_drop { 1157 if is_last_drop {
1146 info.rcc.disable(); 1158 info.rcc.disable_without_stop();
1147 } 1159 }
1148} 1160}
1149 1161
@@ -1506,7 +1518,7 @@ impl<'d, M: Mode> Uart<'d, M> {
1506 .eager_reads 1518 .eager_reads
1507 .store(config.eager_reads.unwrap_or(0), Ordering::Relaxed); 1519 .store(config.eager_reads.unwrap_or(0), Ordering::Relaxed);
1508 1520
1509 info.rcc.enable_and_reset(); 1521 info.rcc.enable_and_reset_without_stop();
1510 1522
1511 info.regs.cr3().write(|w| { 1523 info.regs.cr3().write(|w| {
1512 w.set_rtse(self.rx.rts.is_some()); 1524 w.set_rtse(self.rx.rts.is_some());
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index bac570d27..cc5224b69 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -117,6 +117,8 @@ impl<'d> UartRx<'d, Async> {
117 let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) }; 117 let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) };
118 let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) }; 118 let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) };
119 119
120 info.rcc.increment_stop_refcount();
121
120 // Don't disable the clock 122 // Don't disable the clock
121 mem::forget(self); 123 mem::forget(self);
122 124
@@ -324,6 +326,7 @@ impl<'d> RingBufferedUartRx<'d> {
324 326
325impl Drop for RingBufferedUartRx<'_> { 327impl Drop for RingBufferedUartRx<'_> {
326 fn drop(&mut self) { 328 fn drop(&mut self) {
329 self.info.rcc.decrement_stop_refcount();
327 self.stop_uart(); 330 self.stop_uart();
328 self.rx.as_ref().map(|x| x.set_as_disconnected()); 331 self.rx.as_ref().map(|x| x.set_as_disconnected());
329 self.rts.as_ref().map(|x| x.set_as_disconnected()); 332 self.rts.as_ref().map(|x| x.set_as_disconnected());