diff options
| author | xoviat <[email protected]> | 2025-11-25 16:53:26 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-11-25 16:53:26 -0600 |
| commit | 0847f4ca4657ea2174fc160f96a69f4c916d146e (patch) | |
| tree | c0d2a2bed6c9a5b2007fe9f312fb5d1de5eab2de /embassy-stm32/src | |
| parent | 5298671b0c132f58f3f76273bcd35656dc6e6d3d (diff) | |
stm32: extract busychannel into common api
Diffstat (limited to 'embassy-stm32/src')
| -rw-r--r-- | embassy-stm32/src/dma/dma_bdma.rs | 15 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/mod.rs | 10 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/ringbuffered.rs | 11 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 50 | ||||
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 22 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 68 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 12 |
7 files changed, 105 insertions, 83 deletions
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs index b46ae2813..adc084474 100644 --- a/embassy-stm32/src/dma/dma_bdma.rs +++ b/embassy-stm32/src/dma/dma_bdma.rs | |||
| @@ -8,8 +8,9 @@ use embassy_sync::waitqueue::AtomicWaker; | |||
| 8 | 8 | ||
| 9 | use super::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; | 9 | use super::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; |
| 10 | use super::word::{Word, WordSize}; | 10 | use super::word::{Word, WordSize}; |
| 11 | use super::{AnyChannel, BusyChannel, Channel, Dir, Request, STATE}; | 11 | use super::{AnyChannel, Channel, Dir, Request, STATE}; |
| 12 | use crate::interrupt::typelevel::Interrupt; | 12 | use crate::interrupt::typelevel::Interrupt; |
| 13 | use crate::rcc::BusyPeripheral; | ||
| 13 | use crate::{interrupt, pac}; | 14 | use crate::{interrupt, pac}; |
| 14 | 15 | ||
| 15 | pub(crate) struct ChannelInfo { | 16 | pub(crate) struct ChannelInfo { |
| @@ -602,7 +603,7 @@ impl AnyChannel { | |||
| 602 | /// DMA transfer. | 603 | /// DMA transfer. |
| 603 | #[must_use = "futures do nothing unless you `.await` or poll them"] | 604 | #[must_use = "futures do nothing unless you `.await` or poll them"] |
| 604 | pub struct Transfer<'a> { | 605 | pub struct Transfer<'a> { |
| 605 | channel: BusyChannel<'a>, | 606 | channel: BusyPeripheral<Peri<'a, AnyChannel>>, |
| 606 | } | 607 | } |
| 607 | 608 | ||
| 608 | impl<'a> Transfer<'a> { | 609 | impl<'a> Transfer<'a> { |
| @@ -714,7 +715,7 @@ impl<'a> Transfer<'a> { | |||
| 714 | ); | 715 | ); |
| 715 | channel.start(); | 716 | channel.start(); |
| 716 | Self { | 717 | Self { |
| 717 | channel: BusyChannel::new(channel), | 718 | channel: BusyPeripheral::new(channel), |
| 718 | } | 719 | } |
| 719 | } | 720 | } |
| 720 | 721 | ||
| @@ -818,7 +819,7 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { | |||
| 818 | 819 | ||
| 819 | /// Ringbuffer for receiving data using DMA circular mode. | 820 | /// Ringbuffer for receiving data using DMA circular mode. |
| 820 | pub struct ReadableRingBuffer<'a, W: Word> { | 821 | pub struct ReadableRingBuffer<'a, W: Word> { |
| 821 | channel: BusyChannel<'a>, | 822 | channel: BusyPeripheral<Peri<'a, AnyChannel>>, |
| 822 | ringbuf: ReadableDmaRingBuffer<'a, W>, | 823 | ringbuf: ReadableDmaRingBuffer<'a, W>, |
| 823 | } | 824 | } |
| 824 | 825 | ||
| @@ -855,7 +856,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 855 | ); | 856 | ); |
| 856 | 857 | ||
| 857 | Self { | 858 | Self { |
| 858 | channel: BusyChannel::new(channel), | 859 | channel: BusyPeripheral::new(channel), |
| 859 | ringbuf: ReadableDmaRingBuffer::new(buffer), | 860 | ringbuf: ReadableDmaRingBuffer::new(buffer), |
| 860 | } | 861 | } |
| 861 | } | 862 | } |
| @@ -974,7 +975,7 @@ impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { | |||
| 974 | 975 | ||
| 975 | /// Ringbuffer for writing data using DMA circular mode. | 976 | /// Ringbuffer for writing data using DMA circular mode. |
| 976 | pub struct WritableRingBuffer<'a, W: Word> { | 977 | pub struct WritableRingBuffer<'a, W: Word> { |
| 977 | channel: BusyChannel<'a>, | 978 | channel: BusyPeripheral<Peri<'a, AnyChannel>>, |
| 978 | ringbuf: WritableDmaRingBuffer<'a, W>, | 979 | ringbuf: WritableDmaRingBuffer<'a, W>, |
| 979 | } | 980 | } |
| 980 | 981 | ||
| @@ -1011,7 +1012,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 1011 | ); | 1012 | ); |
| 1012 | 1013 | ||
| 1013 | Self { | 1014 | Self { |
| 1014 | channel: BusyChannel::new(channel), | 1015 | channel: BusyPeripheral::new(channel), |
| 1015 | ringbuf: WritableDmaRingBuffer::new(buffer), | 1016 | ringbuf: WritableDmaRingBuffer::new(buffer), |
| 1016 | } | 1017 | } |
| 1017 | } | 1018 | } |
diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 383c74a78..bfd0570f8 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs | |||
| @@ -11,10 +11,10 @@ use linked_list::Table; | |||
| 11 | 11 | ||
| 12 | use super::word::{Word, WordSize}; | 12 | use super::word::{Word, WordSize}; |
| 13 | use super::{AnyChannel, Channel, Dir, Request, STATE}; | 13 | use super::{AnyChannel, Channel, Dir, Request, STATE}; |
| 14 | use crate::dma::BusyChannel; | ||
| 15 | use crate::interrupt::typelevel::Interrupt; | 14 | use crate::interrupt::typelevel::Interrupt; |
| 16 | use crate::pac; | 15 | use crate::pac; |
| 17 | use crate::pac::gpdma::vals; | 16 | use crate::pac::gpdma::vals; |
| 17 | use crate::rcc::BusyPeripheral; | ||
| 18 | 18 | ||
| 19 | pub mod linked_list; | 19 | pub mod linked_list; |
| 20 | pub mod ringbuffered; | 20 | pub mod ringbuffered; |
| @@ -409,7 +409,7 @@ impl AnyChannel { | |||
| 409 | /// Linked-list DMA transfer. | 409 | /// Linked-list DMA transfer. |
| 410 | #[must_use = "futures do nothing unless you `.await` or poll them"] | 410 | #[must_use = "futures do nothing unless you `.await` or poll them"] |
| 411 | pub struct LinkedListTransfer<'a, const ITEM_COUNT: usize> { | 411 | pub struct LinkedListTransfer<'a, const ITEM_COUNT: usize> { |
| 412 | channel: BusyChannel<'a>, | 412 | channel: BusyPeripheral<Peri<'a, AnyChannel>>, |
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { | 415 | impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { |
| @@ -431,7 +431,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { | |||
| 431 | channel.start(); | 431 | channel.start(); |
| 432 | 432 | ||
| 433 | Self { | 433 | Self { |
| 434 | channel: BusyChannel::new(channel), | 434 | channel: BusyPeripheral::new(channel), |
| 435 | } | 435 | } |
| 436 | } | 436 | } |
| 437 | 437 | ||
| @@ -508,7 +508,7 @@ impl<'a, const ITEM_COUNT: usize> Future for LinkedListTransfer<'a, ITEM_COUNT> | |||
| 508 | /// DMA transfer. | 508 | /// DMA transfer. |
| 509 | #[must_use = "futures do nothing unless you `.await` or poll them"] | 509 | #[must_use = "futures do nothing unless you `.await` or poll them"] |
| 510 | pub struct Transfer<'a> { | 510 | pub struct Transfer<'a> { |
| 511 | channel: BusyChannel<'a>, | 511 | channel: BusyPeripheral<Peri<'a, AnyChannel>>, |
| 512 | } | 512 | } |
| 513 | 513 | ||
| 514 | impl<'a> Transfer<'a> { | 514 | impl<'a> Transfer<'a> { |
| @@ -629,7 +629,7 @@ impl<'a> Transfer<'a> { | |||
| 629 | channel.start(); | 629 | channel.start(); |
| 630 | 630 | ||
| 631 | Self { | 631 | Self { |
| 632 | channel: BusyChannel::new(channel), | 632 | channel: BusyPeripheral::new(channel), |
| 633 | } | 633 | } |
| 634 | } | 634 | } |
| 635 | 635 | ||
diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 54e4d5f71..c150d0b95 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs | |||
| @@ -12,7 +12,8 @@ use super::{AnyChannel, STATE, TransferOptions}; | |||
| 12 | use crate::dma::gpdma::linked_list::{RunMode, Table}; | 12 | use crate::dma::gpdma::linked_list::{RunMode, Table}; |
| 13 | use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; | 13 | use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; |
| 14 | use crate::dma::word::Word; | 14 | use crate::dma::word::Word; |
| 15 | use crate::dma::{BusyChannel, Channel, Dir, Request}; | 15 | use crate::dma::{Channel, Dir, Request}; |
| 16 | use crate::rcc::BusyPeripheral; | ||
| 16 | 17 | ||
| 17 | struct DmaCtrlImpl<'a>(Peri<'a, AnyChannel>); | 18 | struct DmaCtrlImpl<'a>(Peri<'a, AnyChannel>); |
| 18 | 19 | ||
| @@ -49,7 +50,7 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { | |||
| 49 | 50 | ||
| 50 | /// Ringbuffer for receiving data using GPDMA linked-list mode. | 51 | /// Ringbuffer for receiving data using GPDMA linked-list mode. |
| 51 | pub struct ReadableRingBuffer<'a, W: Word> { | 52 | pub struct ReadableRingBuffer<'a, W: Word> { |
| 52 | channel: BusyChannel<'a>, | 53 | channel: BusyPeripheral<Peri<'a, AnyChannel>>, |
| 53 | ringbuf: ReadableDmaRingBuffer<'a, W>, | 54 | ringbuf: ReadableDmaRingBuffer<'a, W>, |
| 54 | table: Table<2>, | 55 | table: Table<2>, |
| 55 | options: TransferOptions, | 56 | options: TransferOptions, |
| @@ -70,7 +71,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 70 | let table = Table::<2>::new_ping_pong::<W>(request, peri_addr, buffer, Dir::PeripheralToMemory); | 71 | let table = Table::<2>::new_ping_pong::<W>(request, peri_addr, buffer, Dir::PeripheralToMemory); |
| 71 | 72 | ||
| 72 | Self { | 73 | Self { |
| 73 | channel: BusyChannel::new(channel), | 74 | channel: BusyPeripheral::new(channel), |
| 74 | ringbuf: ReadableDmaRingBuffer::new(buffer), | 75 | ringbuf: ReadableDmaRingBuffer::new(buffer), |
| 75 | table, | 76 | table, |
| 76 | options, | 77 | options, |
| @@ -189,7 +190,7 @@ impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { | |||
| 189 | 190 | ||
| 190 | /// Ringbuffer for writing data using GPDMA linked-list mode. | 191 | /// Ringbuffer for writing data using GPDMA linked-list mode. |
| 191 | pub struct WritableRingBuffer<'a, W: Word> { | 192 | pub struct WritableRingBuffer<'a, W: Word> { |
| 192 | channel: BusyChannel<'a>, | 193 | channel: BusyPeripheral<Peri<'a, AnyChannel>>, |
| 193 | ringbuf: WritableDmaRingBuffer<'a, W>, | 194 | ringbuf: WritableDmaRingBuffer<'a, W>, |
| 194 | table: Table<2>, | 195 | table: Table<2>, |
| 195 | options: TransferOptions, | 196 | options: TransferOptions, |
| @@ -210,7 +211,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 210 | let table = Table::<2>::new_ping_pong::<W>(request, peri_addr, buffer, Dir::MemoryToPeripheral); | 211 | let table = Table::<2>::new_ping_pong::<W>(request, peri_addr, buffer, Dir::MemoryToPeripheral); |
| 211 | 212 | ||
| 212 | Self { | 213 | Self { |
| 213 | channel: BusyChannel::new(channel), | 214 | channel: BusyPeripheral::new(channel), |
| 214 | ringbuf: WritableDmaRingBuffer::new(buffer), | 215 | ringbuf: WritableDmaRingBuffer::new(buffer), |
| 215 | table, | 216 | table, |
| 216 | options, | 217 | options, |
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 4becc2d87..efb324fa6 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -3,14 +3,12 @@ | |||
| 3 | 3 | ||
| 4 | #[cfg(any(bdma, dma))] | 4 | #[cfg(any(bdma, dma))] |
| 5 | mod dma_bdma; | 5 | mod dma_bdma; |
| 6 | use core::ops; | ||
| 7 | 6 | ||
| 8 | #[cfg(any(bdma, dma))] | 7 | #[cfg(any(bdma, dma))] |
| 9 | pub use dma_bdma::*; | 8 | pub use dma_bdma::*; |
| 10 | 9 | ||
| 11 | #[cfg(gpdma)] | 10 | #[cfg(gpdma)] |
| 12 | pub(crate) mod gpdma; | 11 | pub(crate) mod gpdma; |
| 13 | use embassy_hal_internal::Peri; | ||
| 14 | #[cfg(gpdma)] | 12 | #[cfg(gpdma)] |
| 15 | pub use gpdma::ringbuffered::*; | 13 | pub use gpdma::ringbuffered::*; |
| 16 | #[cfg(gpdma)] | 14 | #[cfg(gpdma)] |
| @@ -27,9 +25,10 @@ pub(crate) use util::*; | |||
| 27 | pub(crate) mod ringbuffer; | 25 | pub(crate) mod ringbuffer; |
| 28 | pub mod word; | 26 | pub mod word; |
| 29 | 27 | ||
| 30 | use embassy_hal_internal::{PeripheralType, impl_peripheral}; | 28 | use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral}; |
| 31 | 29 | ||
| 32 | use crate::interrupt; | 30 | use crate::interrupt; |
| 31 | use crate::rcc::StoppablePeripheral; | ||
| 33 | 32 | ||
| 34 | /// The direction of a DMA transfer. | 33 | /// The direction of a DMA transfer. |
| 35 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 34 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| @@ -48,6 +47,13 @@ pub type Request = u8; | |||
| 48 | #[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))] | 47 | #[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))] |
| 49 | pub type Request = (); | 48 | pub type Request = (); |
| 50 | 49 | ||
| 50 | impl<'a> StoppablePeripheral for Peri<'a, AnyChannel> { | ||
| 51 | #[cfg(feature = "low-power")] | ||
| 52 | fn stop_mode(&self) -> crate::rcc::StopMode { | ||
| 53 | self.stop_mode | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 51 | pub(crate) trait SealedChannel { | 57 | pub(crate) trait SealedChannel { |
| 52 | #[cfg(not(stm32n6))] | 58 | #[cfg(not(stm32n6))] |
| 53 | fn id(&self) -> u8; | 59 | fn id(&self) -> u8; |
| @@ -103,44 +109,6 @@ macro_rules! dma_channel_impl { | |||
| 103 | }; | 109 | }; |
| 104 | } | 110 | } |
| 105 | 111 | ||
| 106 | pub(crate) struct BusyChannel<'a> { | ||
| 107 | channel: Peri<'a, AnyChannel>, | ||
| 108 | } | ||
| 109 | |||
| 110 | impl<'a> BusyChannel<'a> { | ||
| 111 | pub fn new(channel: Peri<'a, AnyChannel>) -> Self { | ||
| 112 | #[cfg(feature = "low-power")] | ||
| 113 | critical_section::with(|cs| { | ||
| 114 | crate::rcc::increment_stop_refcount(cs, channel.stop_mode); | ||
| 115 | }); | ||
| 116 | |||
| 117 | Self { channel } | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | impl<'a> Drop for BusyChannel<'a> { | ||
| 122 | fn drop(&mut self) { | ||
| 123 | #[cfg(feature = "low-power")] | ||
| 124 | critical_section::with(|cs| { | ||
| 125 | crate::rcc::decrement_stop_refcount(cs, self.stop_mode); | ||
| 126 | }); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | impl<'a> ops::Deref for BusyChannel<'a> { | ||
| 131 | type Target = Peri<'a, AnyChannel>; | ||
| 132 | |||
| 133 | fn deref(&self) -> &Self::Target { | ||
| 134 | &self.channel | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | impl<'a> ops::DerefMut for BusyChannel<'a> { | ||
| 139 | fn deref_mut(&mut self) -> &mut Self::Target { | ||
| 140 | &mut self.channel | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | /// Type-erased DMA channel. | 112 | /// Type-erased DMA channel. |
| 145 | pub struct AnyChannel { | 113 | pub struct AnyChannel { |
| 146 | pub(crate) id: u8, | 114 | pub(crate) id: u8, |
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index bd8290da0..cdf3323fb 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs | |||
| @@ -51,7 +51,7 @@ use embassy_executor::*; | |||
| 51 | 51 | ||
| 52 | use crate::interrupt; | 52 | use crate::interrupt; |
| 53 | pub use crate::rcc::StopMode; | 53 | pub use crate::rcc::StopMode; |
| 54 | use crate::rcc::{RCC_CONFIG, REFCOUNT_STOP1, REFCOUNT_STOP2, decrement_stop_refcount, increment_stop_refcount}; | 54 | use crate::rcc::{BusyPeripheral, RCC_CONFIG, REFCOUNT_STOP1, REFCOUNT_STOP2}; |
| 55 | use crate::time_driver::get_driver; | 55 | use crate::time_driver::get_driver; |
| 56 | 56 | ||
| 57 | const THREAD_PENDER: usize = usize::MAX; | 57 | const THREAD_PENDER: usize = usize::MAX; |
| @@ -59,7 +59,9 @@ const THREAD_PENDER: usize = usize::MAX; | |||
| 59 | static mut EXECUTOR_TAKEN: bool = false; | 59 | static mut EXECUTOR_TAKEN: bool = false; |
| 60 | 60 | ||
| 61 | /// Prevent the device from going into the stop mode if held | 61 | /// Prevent the device from going into the stop mode if held |
| 62 | pub struct DeviceBusy(StopMode); | 62 | pub struct DeviceBusy { |
| 63 | _stop_mode: BusyPeripheral<StopMode>, | ||
| 64 | } | ||
| 63 | 65 | ||
| 64 | impl DeviceBusy { | 66 | impl DeviceBusy { |
| 65 | /// Create a new DeviceBusy with stop1. | 67 | /// Create a new DeviceBusy with stop1. |
| @@ -74,19 +76,9 @@ impl DeviceBusy { | |||
| 74 | 76 | ||
| 75 | /// Create a new DeviceBusy. | 77 | /// Create a new DeviceBusy. |
| 76 | pub fn new(stop_mode: StopMode) -> Self { | 78 | pub fn new(stop_mode: StopMode) -> Self { |
| 77 | critical_section::with(|cs| { | 79 | Self { |
| 78 | increment_stop_refcount(cs, stop_mode); | 80 | _stop_mode: BusyPeripheral::new(stop_mode), |
| 79 | }); | 81 | } |
| 80 | |||
| 81 | Self(stop_mode) | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | impl Drop for DeviceBusy { | ||
| 86 | fn drop(&mut self) { | ||
| 87 | critical_section::with(|cs| { | ||
| 88 | decrement_stop_refcount(cs, self.0); | ||
| 89 | }); | ||
| 90 | } | 82 | } |
| 91 | } | 83 | } |
| 92 | 84 | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index b6ecc6c18..1dd634cfe 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #![allow(missing_docs)] // TODO | 4 | #![allow(missing_docs)] // TODO |
| 5 | 5 | ||
| 6 | use core::mem::MaybeUninit; | 6 | use core::mem::MaybeUninit; |
| 7 | use core::ops; | ||
| 7 | 8 | ||
| 8 | mod bd; | 9 | mod bd; |
| 9 | pub use bd::*; | 10 | pub use bd::*; |
| @@ -112,7 +113,7 @@ pub fn clocks<'a>(_rcc: &'a crate::Peri<'a, crate::peripherals::RCC>) -> &'a Clo | |||
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | #[cfg(feature = "low-power")] | 115 | #[cfg(feature = "low-power")] |
| 115 | pub(crate) fn increment_stop_refcount(_cs: CriticalSection, stop_mode: StopMode) { | 116 | fn increment_stop_refcount(_cs: CriticalSection, stop_mode: StopMode) { |
| 116 | match stop_mode { | 117 | match stop_mode { |
| 117 | StopMode::Standby => {} | 118 | StopMode::Standby => {} |
| 118 | StopMode::Stop2 => unsafe { | 119 | StopMode::Stop2 => unsafe { |
| @@ -125,7 +126,7 @@ pub(crate) fn increment_stop_refcount(_cs: CriticalSection, stop_mode: StopMode) | |||
| 125 | } | 126 | } |
| 126 | 127 | ||
| 127 | #[cfg(feature = "low-power")] | 128 | #[cfg(feature = "low-power")] |
| 128 | pub(crate) fn decrement_stop_refcount(_cs: CriticalSection, stop_mode: StopMode) { | 129 | fn decrement_stop_refcount(_cs: CriticalSection, stop_mode: StopMode) { |
| 129 | match stop_mode { | 130 | match stop_mode { |
| 130 | StopMode::Standby => {} | 131 | StopMode::Standby => {} |
| 131 | StopMode::Stop2 => unsafe { | 132 | StopMode::Stop2 => unsafe { |
| @@ -182,6 +183,12 @@ pub enum StopMode { | |||
| 182 | Standby, | 183 | Standby, |
| 183 | } | 184 | } |
| 184 | 185 | ||
| 186 | #[cfg(feature = "low-power")] | ||
| 187 | type BusyRccPeripheral = BusyPeripheral<StopMode>; | ||
| 188 | |||
| 189 | #[cfg(not(feature = "low-power"))] | ||
| 190 | type BusyRccPeripheral = (); | ||
| 191 | |||
| 185 | impl RccInfo { | 192 | impl RccInfo { |
| 186 | /// Safety: | 193 | /// Safety: |
| 187 | /// - `reset_offset_and_bit`, if set, must correspond to valid xxxRST bit | 194 | /// - `reset_offset_and_bit`, if set, must correspond to valid xxxRST bit |
| @@ -297,6 +304,7 @@ impl RccInfo { | |||
| 297 | } | 304 | } |
| 298 | } | 305 | } |
| 299 | 306 | ||
| 307 | #[allow(dead_code)] | ||
| 300 | pub(crate) fn increment_stop_refcount_with_cs(&self, _cs: CriticalSection) { | 308 | pub(crate) fn increment_stop_refcount_with_cs(&self, _cs: CriticalSection) { |
| 301 | #[cfg(feature = "low-power")] | 309 | #[cfg(feature = "low-power")] |
| 302 | increment_stop_refcount(_cs, self.stop_mode); | 310 | increment_stop_refcount(_cs, self.stop_mode); |
| @@ -304,9 +312,11 @@ impl RccInfo { | |||
| 304 | 312 | ||
| 305 | #[allow(dead_code)] | 313 | #[allow(dead_code)] |
| 306 | pub(crate) fn increment_stop_refcount(&self) { | 314 | pub(crate) fn increment_stop_refcount(&self) { |
| 315 | #[cfg(feature = "low-power")] | ||
| 307 | critical_section::with(|cs| self.increment_stop_refcount_with_cs(cs)) | 316 | critical_section::with(|cs| self.increment_stop_refcount_with_cs(cs)) |
| 308 | } | 317 | } |
| 309 | 318 | ||
| 319 | #[allow(dead_code)] | ||
| 310 | pub(crate) fn decrement_stop_refcount_with_cs(&self, _cs: CriticalSection) { | 320 | pub(crate) fn decrement_stop_refcount_with_cs(&self, _cs: CriticalSection) { |
| 311 | #[cfg(feature = "low-power")] | 321 | #[cfg(feature = "low-power")] |
| 312 | decrement_stop_refcount(_cs, self.stop_mode); | 322 | decrement_stop_refcount(_cs, self.stop_mode); |
| @@ -314,6 +324,7 @@ impl RccInfo { | |||
| 314 | 324 | ||
| 315 | #[allow(dead_code)] | 325 | #[allow(dead_code)] |
| 316 | pub(crate) fn decrement_stop_refcount(&self) { | 326 | pub(crate) fn decrement_stop_refcount(&self) { |
| 327 | #[cfg(feature = "low-power")] | ||
| 317 | critical_section::with(|cs| self.decrement_stop_refcount_with_cs(cs)) | 328 | critical_section::with(|cs| self.decrement_stop_refcount_with_cs(cs)) |
| 318 | } | 329 | } |
| 319 | 330 | ||
| @@ -344,6 +355,12 @@ impl RccInfo { | |||
| 344 | critical_section::with(|cs| self.disable_with_cs(cs)) | 355 | critical_section::with(|cs| self.disable_with_cs(cs)) |
| 345 | } | 356 | } |
| 346 | 357 | ||
| 358 | #[allow(dead_code)] | ||
| 359 | pub(crate) fn block_stop(&self) -> BusyRccPeripheral { | ||
| 360 | #[cfg(feature = "low-power")] | ||
| 361 | BusyPeripheral::new(self.stop_mode) | ||
| 362 | } | ||
| 363 | |||
| 347 | fn reset_ptr(&self) -> Option<*mut u32> { | 364 | fn reset_ptr(&self) -> Option<*mut u32> { |
| 348 | if self.reset_offset_or_0xff != 0xff { | 365 | if self.reset_offset_or_0xff != 0xff { |
| 349 | Some(unsafe { (RCC.as_ptr() as *mut u32).add(self.reset_offset_or_0xff as _) }) | 366 | Some(unsafe { (RCC.as_ptr() as *mut u32).add(self.reset_offset_or_0xff as _) }) |
| @@ -357,6 +374,53 @@ impl RccInfo { | |||
| 357 | } | 374 | } |
| 358 | } | 375 | } |
| 359 | 376 | ||
| 377 | pub(crate) trait StoppablePeripheral { | ||
| 378 | #[cfg(feature = "low-power")] | ||
| 379 | #[allow(dead_code)] | ||
| 380 | fn stop_mode(&self) -> StopMode; | ||
| 381 | } | ||
| 382 | |||
| 383 | #[cfg(feature = "low-power")] | ||
| 384 | impl<'a> StoppablePeripheral for StopMode { | ||
| 385 | fn stop_mode(&self) -> StopMode { | ||
| 386 | *self | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | pub(crate) struct BusyPeripheral<T: StoppablePeripheral> { | ||
| 391 | peripheral: T, | ||
| 392 | } | ||
| 393 | |||
| 394 | impl<T: StoppablePeripheral> BusyPeripheral<T> { | ||
| 395 | pub fn new(peripheral: T) -> Self { | ||
| 396 | #[cfg(feature = "low-power")] | ||
| 397 | critical_section::with(|cs| increment_stop_refcount(cs, peripheral.stop_mode())); | ||
| 398 | |||
| 399 | Self { peripheral } | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | impl<T: StoppablePeripheral> Drop for BusyPeripheral<T> { | ||
| 404 | fn drop(&mut self) { | ||
| 405 | #[cfg(feature = "low-power")] | ||
| 406 | critical_section::with(|cs| decrement_stop_refcount(cs, self.peripheral.stop_mode())); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | impl<T: StoppablePeripheral> ops::Deref for BusyPeripheral<T> { | ||
| 411 | type Target = T; | ||
| 412 | |||
| 413 | fn deref(&self) -> &Self::Target { | ||
| 414 | &self.peripheral | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | impl<T: StoppablePeripheral> ops::DerefMut for BusyPeripheral<T> { | ||
| 419 | fn deref_mut(&mut self) -> &mut Self::Target { | ||
| 420 | &mut self.peripheral | ||
| 421 | } | ||
| 422 | } | ||
| 423 | |||
| 360 | #[allow(unused)] | 424 | #[allow(unused)] |
| 361 | mod util { | 425 | mod util { |
| 362 | use crate::time::Hertz; | 426 | use crate::time::Hertz; |
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 1af78b358..8047d6005 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -491,8 +491,7 @@ 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(); | 494 | let _ = self.info.rcc.block_stop(); |
| 495 | let _ = OnDrop::new(|| self.info.rcc.decrement_stop_refcount()); | ||
| 496 | 495 | ||
| 497 | let r = self.info.regs; | 496 | let r = self.info.regs; |
| 498 | 497 | ||
| @@ -511,8 +510,7 @@ impl<'d> UartTx<'d, Async> { | |||
| 511 | 510 | ||
| 512 | /// Wait until transmission complete | 511 | /// Wait until transmission complete |
| 513 | pub async fn flush(&mut self) -> Result<(), Error> { | 512 | pub async fn flush(&mut self) -> Result<(), Error> { |
| 514 | self.info.rcc.increment_stop_refcount(); | 513 | let _ = self.info.rcc.block_stop(); |
| 515 | let _ = OnDrop::new(|| self.info.rcc.decrement_stop_refcount()); | ||
| 516 | 514 | ||
| 517 | flush(&self.info, &self.state).await | 515 | flush(&self.info, &self.state).await |
| 518 | } | 516 | } |
| @@ -732,8 +730,7 @@ impl<'d> UartRx<'d, Async> { | |||
| 732 | 730 | ||
| 733 | /// Initiate an asynchronous UART read | 731 | /// Initiate an asynchronous UART read |
| 734 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | 732 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 735 | self.info.rcc.increment_stop_refcount(); | 733 | let _ = self.info.rcc.block_stop(); |
| 736 | let _ = OnDrop::new(|| self.info.rcc.decrement_stop_refcount()); | ||
| 737 | 734 | ||
| 738 | self.inner_read(buffer, false).await?; | 735 | self.inner_read(buffer, false).await?; |
| 739 | 736 | ||
| @@ -742,8 +739,7 @@ impl<'d> UartRx<'d, Async> { | |||
| 742 | 739 | ||
| 743 | /// Initiate an asynchronous read with idle line detection enabled | 740 | /// Initiate an asynchronous read with idle line detection enabled |
| 744 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { | 741 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
| 745 | self.info.rcc.increment_stop_refcount(); | 742 | let _ = self.info.rcc.block_stop(); |
| 746 | let _ = OnDrop::new(|| self.info.rcc.decrement_stop_refcount()); | ||
| 747 | 743 | ||
| 748 | self.inner_read(buffer, true).await | 744 | self.inner_read(buffer, true).await |
| 749 | } | 745 | } |
