diff options
| author | xoviat <[email protected]> | 2025-11-25 11:47:44 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-11-25 11:47:44 -0600 |
| commit | d2d00b57c8bf5b6879c5df5021f44652d1fd52ee (patch) | |
| tree | ca5111fbd03afd8238a5061a1e0f824d3a60a650 /embassy-stm32/src | |
| parent | 906eaee53f84381dd10583894edf2de67275f083 (diff) | |
stm32: allow granular stop for uart
Diffstat (limited to 'embassy-stm32/src')
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 39 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 20 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 3 |
3 files changed, 52 insertions, 10 deletions
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 | ||
| 325 | impl Drop for RingBufferedUartRx<'_> { | 327 | impl 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()); |
