aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-09-05 16:28:53 +0200
committerGitHub <[email protected]>2025-09-05 16:28:53 +0200
commit4ac4452c16e1b75bcf70814a9530b7724cc16e7d (patch)
treebf7114837ad77c185e98055a3f0c6bfc469a2872
parentb8577a31338358d10b1fdb7dd374b0c7eafe86b5 (diff)
parent46ce5ab6973f62c48a4de0e69a0a6c5d57d9dbb5 (diff)
Merge pull request #4599 from universalhandle/4577-dropped-channel-disables-dac
fix(embassy-stm32): Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope
-rw-r--r--embassy-stm32/CHANGELOG.md3
-rw-r--r--embassy-stm32/src/dac/mod.rs55
2 files changed, 57 insertions, 1 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index 50bdc1072..69f15013d 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13- fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received 13- fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received
14- feat: stm32/timer: add set_polarity functions for main and complementary outputs in complementary_pwm 14- feat: stm32/timer: add set_polarity functions for main and complementary outputs in complementary_pwm
15- Add I2S support for STM32F1, STM32C0, STM32F0, STM32F3, STM32F7, STM32G0, STM32WL, STM32H5, STM32H7RS 15- Add I2S support for STM32F1, STM32C0, STM32F0, STM32F3, STM32F7, STM32G0, STM32WL, STM32H5, STM32H7RS
16### Fixed
17
18- STM32: Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope ([#4577](https://github.com/embassy-rs/embassy/pull/4577))
16 19
17## 0.4.0 - 2025-08-26 20## 0.4.0 - 2025-08-26
18 21
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index d8f1f96f2..bc6c3cd34 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -12,6 +12,7 @@ use crate::{peripherals, Peri};
12 12
13mod tsel; 13mod tsel;
14use embassy_hal_internal::PeripheralType; 14use embassy_hal_internal::PeripheralType;
15use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
15pub use tsel::TriggerSel; 16pub use tsel::TriggerSel;
16 17
17/// Operating mode for DAC channel 18/// Operating mode for DAC channel
@@ -96,6 +97,41 @@ pub enum ValueArray<'a> {
96 Bit12Right(&'a [u16]), 97 Bit12Right(&'a [u16]),
97} 98}
98 99
100#[derive(Debug)]
101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
102enum ChannelEvent {
103 Enable,
104 Disable,
105}
106
107struct InnerState {
108 channel_count: usize,
109}
110
111type SharedState = embassy_sync::blocking_mutex::Mutex<CriticalSectionRawMutex, core::cell::RefCell<InnerState>>;
112struct State {
113 state: SharedState,
114}
115
116impl State {
117 /// Adjusts the channel count in response to a `ChannelEvent`, returning the updated value.
118 pub fn adjust_channel_count(&self, event: ChannelEvent) -> usize {
119 self.state.lock(|state| {
120 {
121 let mut mut_state = state.borrow_mut();
122 match event {
123 ChannelEvent::Enable => {
124 mut_state.channel_count += 1;
125 }
126 ChannelEvent::Disable => {
127 mut_state.channel_count -= 1;
128 }
129 };
130 }
131 state.borrow().channel_count
132 })
133 }
134}
99/// Driver for a single DAC channel. 135/// Driver for a single DAC channel.
100/// 136///
101/// If you want to use both channels, either together or independently, 137/// If you want to use both channels, either together or independently,
@@ -249,6 +285,16 @@ impl<'d, T: Instance, C: Channel, M: PeriMode> DacChannel<'d, T, C, M> {
249 reg.set_en(C::IDX, on); 285 reg.set_en(C::IDX, on);
250 }); 286 });
251 }); 287 });
288 let event = if on {
289 ChannelEvent::Enable
290 } else {
291 ChannelEvent::Disable
292 };
293 let channel_count = T::state().adjust_channel_count(event);
294 // Disable the DAC only if no more channels are using it.
295 if channel_count == 0 {
296 rcc::disable::<T>();
297 }
252 } 298 }
253 299
254 /// Enable this channel. 300 /// Enable this channel.
@@ -354,7 +400,7 @@ impl<'d, T: Instance, C: Channel, M: PeriMode> DacChannel<'d, T, C, M> {
354 400
355impl<'d, T: Instance, C: Channel, M: PeriMode> Drop for DacChannel<'d, T, C, M> { 401impl<'d, T: Instance, C: Channel, M: PeriMode> Drop for DacChannel<'d, T, C, M> {
356 fn drop(&mut self) { 402 fn drop(&mut self) {
357 rcc::disable::<T>(); 403 self.disable();
358 } 404 }
359} 405}
360 406
@@ -597,6 +643,13 @@ impl<'d, T: Instance, M: PeriMode> Dac<'d, T, M> {
597 643
598trait SealedInstance { 644trait SealedInstance {
599 fn regs() -> crate::pac::dac::Dac; 645 fn regs() -> crate::pac::dac::Dac;
646
647 fn state() -> &'static State {
648 static STATE: State = State {
649 state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(InnerState { channel_count: 0 })),
650 };
651 &STATE
652 }
600} 653}
601 654
602/// DAC instance. 655/// DAC instance.