diff options
| -rw-r--r-- | embassy-stm32/src/adc/ringbuffered.rs | 248 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v2.rs | 102 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v3.rs | 32 |
3 files changed, 152 insertions, 230 deletions
diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs index 931ebc2b7..790eff422 100644 --- a/embassy-stm32/src/adc/ringbuffered.rs +++ b/embassy-stm32/src/adc/ringbuffered.rs | |||
| @@ -4,6 +4,7 @@ use core::sync::atomic::{Ordering, compiler_fence}; | |||
| 4 | #[allow(unused_imports)] | 4 | #[allow(unused_imports)] |
| 5 | use embassy_hal_internal::Peri; | 5 | use embassy_hal_internal::Peri; |
| 6 | 6 | ||
| 7 | use crate::adc::Adc; | ||
| 7 | #[allow(unused_imports)] | 8 | #[allow(unused_imports)] |
| 8 | use crate::adc::{Instance, RxDma}; | 9 | use crate::adc::{Instance, RxDma}; |
| 9 | #[allow(unused_imports)] | 10 | #[allow(unused_imports)] |
| @@ -13,21 +14,12 @@ use crate::rcc; | |||
| 13 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 14 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 14 | pub struct OverrunError; | 15 | pub struct OverrunError; |
| 15 | 16 | ||
| 16 | #[cfg(adc_v2)] | ||
| 17 | fn clear_interrupt_flags(r: crate::pac::adc::Adc) { | ||
| 18 | r.sr().modify(|regs| { | ||
| 19 | regs.set_eoc(false); | ||
| 20 | regs.set_ovr(false); | ||
| 21 | }); | ||
| 22 | } | ||
| 23 | |||
| 24 | pub struct RingBufferedAdc<'d, T: Instance> { | 17 | pub struct RingBufferedAdc<'d, T: Instance> { |
| 25 | pub _phantom: PhantomData<T>, | 18 | _phantom: PhantomData<T>, |
| 26 | pub ring_buf: ReadableRingBuffer<'d, u16>, | 19 | ring_buf: ReadableRingBuffer<'d, u16>, |
| 27 | } | 20 | } |
| 28 | 21 | ||
| 29 | impl<'d, T: Instance> RingBufferedAdc<'d, T> { | 22 | impl<'d, T: Instance> RingBufferedAdc<'d, T> { |
| 30 | #[cfg(not(adc_v2))] | ||
| 31 | pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self { | 23 | pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self { |
| 32 | //dma side setup | 24 | //dma side setup |
| 33 | let opts = TransferOptions { | 25 | let opts = TransferOptions { |
| @@ -48,161 +40,24 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> { | |||
| 48 | } | 40 | } |
| 49 | } | 41 | } |
| 50 | 42 | ||
| 51 | #[cfg(adc_v2)] | ||
| 52 | fn is_on() -> bool { | ||
| 53 | T::regs().cr2().read().adon() | ||
| 54 | } | ||
| 55 | |||
| 56 | #[cfg(adc_v2)] | ||
| 57 | /// Turns on ADC if it is not already turned on and starts continuous DMA transfer. | 43 | /// Turns on ADC if it is not already turned on and starts continuous DMA transfer. |
| 58 | pub fn start(&mut self) -> Result<(), OverrunError> { | 44 | pub fn start(&mut self) { |
| 59 | self.setup_adc(); | 45 | compiler_fence(Ordering::SeqCst); |
| 60 | self.ring_buf.clear(); | 46 | self.ring_buf.start(); |
| 61 | |||
| 62 | Ok(()) | ||
| 63 | } | ||
| 64 | 47 | ||
| 65 | #[cfg(adc_v2)] | 48 | Adc::<T>::start(); |
| 66 | fn stop(&mut self, err: OverrunError) -> Result<usize, OverrunError> { | ||
| 67 | self.teardown_adc(); | ||
| 68 | Err(err) | ||
| 69 | } | 49 | } |
| 70 | 50 | ||
| 71 | #[cfg(adc_v2)] | 51 | pub fn stop(&mut self) { |
| 72 | /// Stops DMA transfer. | ||
| 73 | /// It does not turn off ADC. | ||
| 74 | /// Calling `start` restarts continuous DMA transfer. | ||
| 75 | /// | ||
| 76 | /// [`start`]: #method.start | ||
| 77 | pub fn teardown_adc(&mut self) { | ||
| 78 | // Stop the DMA transfer | ||
| 79 | self.ring_buf.request_pause(); | 52 | self.ring_buf.request_pause(); |
| 80 | 53 | ||
| 81 | let r = T::regs(); | 54 | Adc::<T>::stop(); |
| 82 | |||
| 83 | // Stop ADC | ||
| 84 | r.cr2().modify(|reg| { | ||
| 85 | // Stop ADC | ||
| 86 | reg.set_swstart(false); | ||
| 87 | // Stop DMA | ||
| 88 | reg.set_dma(false); | ||
| 89 | }); | ||
| 90 | |||
| 91 | r.cr1().modify(|w| { | ||
| 92 | // Disable interrupt for end of conversion | ||
| 93 | w.set_eocie(false); | ||
| 94 | // Disable interrupt for overrun | ||
| 95 | w.set_ovrie(false); | ||
| 96 | }); | ||
| 97 | |||
| 98 | clear_interrupt_flags(r); | ||
| 99 | 55 | ||
| 100 | compiler_fence(Ordering::SeqCst); | 56 | compiler_fence(Ordering::SeqCst); |
| 101 | } | 57 | } |
| 102 | 58 | ||
| 103 | #[cfg(adc_v2)] | 59 | pub fn clear(&mut self) { |
| 104 | fn setup_adc(&mut self) { | ||
| 105 | use crate::pac::adc::vals; | ||
| 106 | |||
| 107 | compiler_fence(Ordering::SeqCst); | ||
| 108 | |||
| 109 | self.ring_buf.start(); | ||
| 110 | |||
| 111 | let r = T::regs(); | ||
| 112 | |||
| 113 | // Enable ADC | ||
| 114 | let was_on = Self::is_on(); | ||
| 115 | if !was_on { | ||
| 116 | r.cr2().modify(|reg| { | ||
| 117 | reg.set_adon(false); | ||
| 118 | reg.set_swstart(false); | ||
| 119 | }); | ||
| 120 | } | ||
| 121 | |||
| 122 | // Clear all interrupts | ||
| 123 | r.sr().modify(|regs| { | ||
| 124 | regs.set_eoc(false); | ||
| 125 | regs.set_ovr(false); | ||
| 126 | regs.set_strt(false); | ||
| 127 | }); | ||
| 128 | |||
| 129 | r.cr1().modify(|w| { | ||
| 130 | // Enable interrupt for end of conversion | ||
| 131 | w.set_eocie(true); | ||
| 132 | // Enable interrupt for overrun | ||
| 133 | w.set_ovrie(true); | ||
| 134 | // Scanning converisons of multiple channels | ||
| 135 | w.set_scan(true); | ||
| 136 | // Continuous conversion mode | ||
| 137 | w.set_discen(false); | ||
| 138 | }); | ||
| 139 | |||
| 140 | r.cr2().modify(|w| { | ||
| 141 | // Enable DMA mode | ||
| 142 | w.set_dma(true); | ||
| 143 | // Enable continuous conversions | ||
| 144 | w.set_cont(true); | ||
| 145 | // DMA requests are issues as long as DMA=1 and data are converted. | ||
| 146 | w.set_dds(vals::Dds::CONTINUOUS); | ||
| 147 | // EOC flag is set at the end of each conversion. | ||
| 148 | w.set_eocs(vals::Eocs::EACH_CONVERSION); | ||
| 149 | }); | ||
| 150 | |||
| 151 | // Begin ADC conversions | ||
| 152 | T::regs().cr2().modify(|reg| { | ||
| 153 | reg.set_adon(true); | ||
| 154 | reg.set_swstart(true); | ||
| 155 | }); | ||
| 156 | |||
| 157 | super::blocking_delay_us(3); | ||
| 158 | } | ||
| 159 | |||
| 160 | #[cfg(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0))] | ||
| 161 | #[inline] | ||
| 162 | fn start_continuous_sampling(&mut self) { | ||
| 163 | // Start adc conversion | ||
| 164 | T::regs().cr().modify(|reg| { | ||
| 165 | reg.set_adstart(true); | ||
| 166 | }); | ||
| 167 | self.ring_buf.start(); | ||
| 168 | } | ||
| 169 | |||
| 170 | #[cfg(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0))] | ||
| 171 | #[inline] | ||
| 172 | pub fn stop_continuous_sampling(&mut self) { | ||
| 173 | // Stop adc conversion | ||
| 174 | if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { | ||
| 175 | T::regs().cr().modify(|reg| { | ||
| 176 | reg.set_adstp(true); | ||
| 177 | }); | ||
| 178 | while T::regs().cr().read().adstart() {} | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | #[cfg(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0))] | ||
| 183 | pub fn disable_adc(&mut self) { | ||
| 184 | self.stop_continuous_sampling(); | ||
| 185 | self.ring_buf.clear(); | 60 | self.ring_buf.clear(); |
| 186 | self.ring_buf.request_pause(); | ||
| 187 | } | ||
| 188 | |||
| 189 | #[cfg(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0))] | ||
| 190 | pub fn teardown_adc(&mut self) { | ||
| 191 | self.disable_adc(); | ||
| 192 | |||
| 193 | //disable dma control | ||
| 194 | #[cfg(not(any(adc_g0, adc_u0)))] | ||
| 195 | T::regs().cfgr().modify(|reg| { | ||
| 196 | reg.set_dmaen(false); | ||
| 197 | }); | ||
| 198 | #[cfg(any(adc_g0, adc_u0))] | ||
| 199 | T::regs().cfgr1().modify(|reg| { | ||
| 200 | reg.set_dmaen(false); | ||
| 201 | }); | ||
| 202 | |||
| 203 | //TODO: do we need to cleanup the DMA request here? | ||
| 204 | |||
| 205 | compiler_fence(Ordering::SeqCst); | ||
| 206 | } | 61 | } |
| 207 | 62 | ||
| 208 | /// Reads measurements from the DMA ring buffer. | 63 | /// Reads measurements from the DMA ring buffer. |
| @@ -257,31 +112,17 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> { | |||
| 257 | "Buffer size must be half the size of the ring buffer" | 112 | "Buffer size must be half the size of the ring buffer" |
| 258 | ); | 113 | ); |
| 259 | 114 | ||
| 260 | let r = T::regs(); | 115 | if !self.ring_buf.is_running() { |
| 116 | self.start(); | ||
| 117 | } | ||
| 261 | 118 | ||
| 262 | #[cfg(adc_v2)] | 119 | #[cfg(adc_v2)] |
| 263 | { | 120 | { |
| 264 | // Start background receive if it was not already started | ||
| 265 | if !r.cr2().read().dma() { | ||
| 266 | self.start()?; | ||
| 267 | } | ||
| 268 | |||
| 269 | // Clear overrun flag if set. | 121 | // Clear overrun flag if set. |
| 270 | if r.sr().read().ovr() { | 122 | if T::regs().sr().read().ovr() { |
| 271 | return self.stop(OverrunError); | 123 | self.stop(); |
| 272 | } | ||
| 273 | |||
| 274 | // Start background receive if it was not already started | ||
| 275 | if !r.cr().read().adstart() { | ||
| 276 | self.start_continuous_sampling(); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | 124 | ||
| 280 | #[cfg(not(adc_v2))] | 125 | return Err(OverrunError); |
| 281 | { | ||
| 282 | // Start background receive if it was not already started | ||
| 283 | if !r.cr().read().adstart() { | ||
| 284 | self.start_continuous_sampling(); | ||
| 285 | } | 126 | } |
| 286 | } | 127 | } |
| 287 | 128 | ||
| @@ -297,50 +138,29 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> { | |||
| 297 | /// Receive in the background is terminated if an error is returned. | 138 | /// Receive in the background is terminated if an error is returned. |
| 298 | /// It must then manually be started again by calling `start_continuous_sampling()` or by re-calling `blocking_read()`. | 139 | /// It must then manually be started again by calling `start_continuous_sampling()` or by re-calling `blocking_read()`. |
| 299 | pub fn blocking_read(&mut self, buf: &mut [u16]) -> Result<usize, OverrunError> { | 140 | pub fn blocking_read(&mut self, buf: &mut [u16]) -> Result<usize, OverrunError> { |
| 300 | let r = T::regs(); | 141 | if !self.ring_buf.is_running() { |
| 142 | self.start(); | ||
| 143 | } | ||
| 301 | 144 | ||
| 302 | #[cfg(adc_v2)] | 145 | #[cfg(adc_v2)] |
| 303 | { | 146 | { |
| 304 | // Start background receive if it was not already started | ||
| 305 | if !r.cr2().read().dma() { | ||
| 306 | self.start()?; | ||
| 307 | } | ||
| 308 | |||
| 309 | // Clear overrun flag if set. | 147 | // Clear overrun flag if set. |
| 310 | if r.sr().read().ovr() { | 148 | if T::regs().sr().read().ovr() { |
| 311 | return self.stop(OverrunError); | 149 | self.stop(); |
| 312 | } | ||
| 313 | 150 | ||
| 314 | loop { | 151 | return Err(OverrunError); |
| 315 | match self.ring_buf.read(buf) { | ||
| 316 | Ok((0, _)) => {} | ||
| 317 | Ok((len, _)) => { | ||
| 318 | return Ok(len); | ||
| 319 | } | ||
| 320 | Err(_) => { | ||
| 321 | return self.stop(OverrunError); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | } | 152 | } |
| 325 | } | 153 | } |
| 154 | loop { | ||
| 155 | match self.ring_buf.read(buf) { | ||
| 156 | Ok((0, _)) => {} | ||
| 157 | Ok((len, _)) => { | ||
| 158 | return Ok(len); | ||
| 159 | } | ||
| 160 | Err(_) => { | ||
| 161 | self.stop(); | ||
| 326 | 162 | ||
| 327 | #[cfg(not(adc_v2))] | 163 | return Err(OverrunError); |
| 328 | { | ||
| 329 | // Start background receive if it was not already started | ||
| 330 | if !r.cr().read().adstart() { | ||
| 331 | self.start_continuous_sampling(); | ||
| 332 | } | ||
| 333 | |||
| 334 | loop { | ||
| 335 | match self.ring_buf.read(buf) { | ||
| 336 | Ok((0, _)) => {} | ||
| 337 | Ok((len, _)) => { | ||
| 338 | return Ok(len); | ||
| 339 | } | ||
| 340 | Err(_) => { | ||
| 341 | self.stop_continuous_sampling(); | ||
| 342 | return Err(OverrunError); | ||
| 343 | } | ||
| 344 | } | 164 | } |
| 345 | } | 165 | } |
| 346 | } | 166 | } |
| @@ -349,7 +169,11 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> { | |||
| 349 | 169 | ||
| 350 | impl<T: Instance> Drop for RingBufferedAdc<'_, T> { | 170 | impl<T: Instance> Drop for RingBufferedAdc<'_, T> { |
| 351 | fn drop(&mut self) { | 171 | fn drop(&mut self) { |
| 352 | self.teardown_adc(); | 172 | Adc::<T>::teardown_adc(); |
| 173 | |||
| 174 | compiler_fence(Ordering::SeqCst); | ||
| 175 | |||
| 176 | self.ring_buf.request_pause(); | ||
| 353 | rcc::disable::<T>(); | 177 | rcc::disable::<T>(); |
| 354 | } | 178 | } |
| 355 | } | 179 | } |
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index e57cd19b3..90c6294d2 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | use core::mem; | 1 | use core::mem; |
| 2 | use core::sync::atomic::{Ordering, compiler_fence}; | ||
| 3 | 3 | ||
| 4 | use super::blocking_delay_us; | 4 | use super::blocking_delay_us; |
| 5 | use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; | 5 | use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; |
| 6 | use crate::dma::{Priority, ReadableRingBuffer, TransferOptions}; | 6 | use crate::pac::adc::vals; |
| 7 | use crate::peripherals::ADC1; | 7 | use crate::peripherals::ADC1; |
| 8 | use crate::time::Hertz; | 8 | use crate::time::Hertz; |
| 9 | use crate::{Peri, rcc}; | 9 | use crate::{Peri, rcc}; |
| @@ -11,6 +11,13 @@ use crate::{Peri, rcc}; | |||
| 11 | mod ringbuffered; | 11 | mod ringbuffered; |
| 12 | pub use ringbuffered::RingBufferedAdc; | 12 | pub use ringbuffered::RingBufferedAdc; |
| 13 | 13 | ||
| 14 | fn clear_interrupt_flags(r: crate::pac::adc::Adc) { | ||
| 15 | r.sr().modify(|regs| { | ||
| 16 | regs.set_eoc(false); | ||
| 17 | regs.set_ovr(false); | ||
| 18 | }); | ||
| 19 | } | ||
| 20 | |||
| 14 | /// Default VREF voltage used for sample conversion to millivolts. | 21 | /// Default VREF voltage used for sample conversion to millivolts. |
| 15 | pub const VREF_DEFAULT_MV: u32 = 3300; | 22 | pub const VREF_DEFAULT_MV: u32 = 3300; |
| 16 | /// VREF voltage used for factory calibration of VREFINTCAL register. | 23 | /// VREF voltage used for factory calibration of VREFINTCAL register. |
| @@ -134,18 +141,6 @@ where | |||
| 134 | ) -> RingBufferedAdc<'d, T> { | 141 | ) -> RingBufferedAdc<'d, T> { |
| 135 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); | 142 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); |
| 136 | 143 | ||
| 137 | let opts: crate::dma::TransferOptions = TransferOptions { | ||
| 138 | half_transfer_ir: true, | ||
| 139 | priority: Priority::VeryHigh, | ||
| 140 | ..Default::default() | ||
| 141 | }; | ||
| 142 | |||
| 143 | // Safety: we forget the struct before this function returns. | ||
| 144 | let rx_src = T::regs().dr().as_ptr() as *mut u16; | ||
| 145 | let request = dma.request(); | ||
| 146 | |||
| 147 | let ring_buf = unsafe { ReadableRingBuffer::new(dma, request, rx_src, dma_buf, opts) }; | ||
| 148 | |||
| 149 | T::regs().cr2().modify(|reg| { | 144 | T::regs().cr2().modify(|reg| { |
| 150 | reg.set_adon(true); | 145 | reg.set_adon(true); |
| 151 | }); | 146 | }); |
| @@ -165,13 +160,59 @@ where | |||
| 165 | Self::set_channel_sample_time(channel.channel(), sample_time); | 160 | Self::set_channel_sample_time(channel.channel(), sample_time); |
| 166 | } | 161 | } |
| 167 | 162 | ||
| 163 | compiler_fence(Ordering::SeqCst); | ||
| 164 | |||
| 165 | let r = T::regs(); | ||
| 166 | |||
| 167 | // Clear all interrupts | ||
| 168 | r.sr().modify(|regs| { | ||
| 169 | regs.set_eoc(false); | ||
| 170 | regs.set_ovr(false); | ||
| 171 | regs.set_strt(false); | ||
| 172 | }); | ||
| 173 | |||
| 174 | r.cr1().modify(|w| { | ||
| 175 | // Enable interrupt for end of conversion | ||
| 176 | w.set_eocie(true); | ||
| 177 | // Enable interrupt for overrun | ||
| 178 | w.set_ovrie(true); | ||
| 179 | // Scanning converisons of multiple channels | ||
| 180 | w.set_scan(true); | ||
| 181 | // Continuous conversion mode | ||
| 182 | w.set_discen(false); | ||
| 183 | }); | ||
| 184 | |||
| 185 | r.cr2().modify(|w| { | ||
| 186 | // Enable DMA mode | ||
| 187 | w.set_dma(true); | ||
| 188 | // Enable continuous conversions | ||
| 189 | w.set_cont(true); | ||
| 190 | // DMA requests are issues as long as DMA=1 and data are converted. | ||
| 191 | w.set_dds(vals::Dds::CONTINUOUS); | ||
| 192 | // EOC flag is set at the end of each conversion. | ||
| 193 | w.set_eocs(vals::Eocs::EACH_CONVERSION); | ||
| 194 | }); | ||
| 195 | |||
| 168 | // Don't disable the clock | 196 | // Don't disable the clock |
| 169 | mem::forget(self); | 197 | mem::forget(self); |
| 170 | 198 | ||
| 171 | RingBufferedAdc { | 199 | RingBufferedAdc::new(dma, dma_buf) |
| 172 | _phantom: PhantomData, | 200 | } |
| 173 | ring_buf, | 201 | |
| 174 | } | 202 | pub(super) fn start() { |
| 203 | // Begin ADC conversions | ||
| 204 | T::regs().cr2().modify(|reg| { | ||
| 205 | reg.set_adon(true); | ||
| 206 | reg.set_swstart(true); | ||
| 207 | }); | ||
| 208 | } | ||
| 209 | |||
| 210 | pub(super) fn stop() { | ||
| 211 | // Stop ADC | ||
| 212 | T::regs().cr2().modify(|reg| { | ||
| 213 | // Stop ADC | ||
| 214 | reg.set_swstart(false); | ||
| 215 | }); | ||
| 175 | } | 216 | } |
| 176 | 217 | ||
| 177 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | 218 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { |
| @@ -260,6 +301,31 @@ where | |||
| 260 | T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); | 301 | T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); |
| 261 | } | 302 | } |
| 262 | } | 303 | } |
| 304 | |||
| 305 | pub(super) fn teardown_adc() { | ||
| 306 | let r = T::regs(); | ||
| 307 | |||
| 308 | // Stop ADC | ||
| 309 | r.cr2().modify(|reg| { | ||
| 310 | // Stop ADC | ||
| 311 | reg.set_swstart(false); | ||
| 312 | // Stop ADC | ||
| 313 | reg.set_adon(false); | ||
| 314 | // Stop DMA | ||
| 315 | reg.set_dma(false); | ||
| 316 | }); | ||
| 317 | |||
| 318 | r.cr1().modify(|w| { | ||
| 319 | // Disable interrupt for end of conversion | ||
| 320 | w.set_eocie(false); | ||
| 321 | // Disable interrupt for overrun | ||
| 322 | w.set_ovrie(false); | ||
| 323 | }); | ||
| 324 | |||
| 325 | clear_interrupt_flags(r); | ||
| 326 | |||
| 327 | compiler_fence(Ordering::SeqCst); | ||
| 328 | } | ||
| 263 | } | 329 | } |
| 264 | 330 | ||
| 265 | impl<'d, T: Instance> Drop for Adc<'d, T> { | 331 | impl<'d, T: Instance> Drop for Adc<'d, T> { |
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 8a0cc0fcf..6da0adb44 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs | |||
| @@ -181,6 +181,38 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 181 | blocking_delay_us(1); | 181 | blocking_delay_us(1); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | #[cfg(any(adc_v3, adc_g0, adc_u0))] | ||
| 185 | pub(super) fn start() { | ||
| 186 | // Start adc conversion | ||
| 187 | T::regs().cr().modify(|reg| { | ||
| 188 | reg.set_adstart(true); | ||
| 189 | }); | ||
| 190 | } | ||
| 191 | |||
| 192 | #[cfg(any(adc_v3, adc_g0, adc_u0))] | ||
| 193 | pub(super) fn stop() { | ||
| 194 | // Stop adc conversion | ||
| 195 | if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { | ||
| 196 | T::regs().cr().modify(|reg| { | ||
| 197 | reg.set_adstp(true); | ||
| 198 | }); | ||
| 199 | while T::regs().cr().read().adstart() {} | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | #[cfg(any(adc_v3, adc_g0, adc_u0))] | ||
| 204 | pub(super) fn teardown_adc() { | ||
| 205 | //disable dma control | ||
| 206 | #[cfg(not(any(adc_g0, adc_u0)))] | ||
| 207 | T::regs().cfgr().modify(|reg| { | ||
| 208 | reg.set_dmaen(false); | ||
| 209 | }); | ||
| 210 | #[cfg(any(adc_g0, adc_u0))] | ||
| 211 | T::regs().cfgr1().modify(|reg| { | ||
| 212 | reg.set_dmaen(false); | ||
| 213 | }); | ||
| 214 | } | ||
| 215 | |||
| 184 | /// Initialize the ADC leaving any analog clock at reset value. | 216 | /// Initialize the ADC leaving any analog clock at reset value. |
| 185 | /// For G0 and WL, this is the async clock without prescaler. | 217 | /// For G0 and WL, this is the async clock without prescaler. |
| 186 | pub fn new(adc: Peri<'d, T>) -> Self { | 218 | pub fn new(adc: Peri<'d, T>) -> Self { |
