Skip to content

Commit 81adf1d

Browse files
committed
stm32/adc: reorder and unify
1 parent afc412d commit 81adf1d

File tree

3 files changed

+152
-230
lines changed

3 files changed

+152
-230
lines changed

embassy-stm32/src/adc/ringbuffered.rs

Lines changed: 36 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use core::sync::atomic::{Ordering, compiler_fence};
44
#[allow(unused_imports)]
55
use embassy_hal_internal::Peri;
66

7+
use crate::adc::Adc;
78
#[allow(unused_imports)]
89
use crate::adc::{Instance, RxDma};
910
#[allow(unused_imports)]
@@ -13,21 +14,12 @@ use crate::rcc;
1314
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1415
pub struct OverrunError;
1516

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-
2417
pub struct RingBufferedAdc<'d, T: Instance> {
25-
pub _phantom: PhantomData<T>,
26-
pub ring_buf: ReadableRingBuffer<'d, u16>,
18+
_phantom: PhantomData<T>,
19+
ring_buf: ReadableRingBuffer<'d, u16>,
2720
}
2821

2922
impl<'d, T: Instance> RingBufferedAdc<'d, T> {
30-
#[cfg(not(adc_v2))]
3123
pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self {
3224
//dma side setup
3325
let opts = TransferOptions {
@@ -48,161 +40,24 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
4840
}
4941
}
5042

51-
#[cfg(adc_v2)]
52-
fn is_on() -> bool {
53-
T::regs().cr2().read().adon()
54-
}
55-
56-
#[cfg(adc_v2)]
5743
/// Turns on ADC if it is not already turned on and starts continuous DMA transfer.
58-
pub fn start(&mut self) -> Result<(), OverrunError> {
59-
self.setup_adc();
60-
self.ring_buf.clear();
61-
62-
Ok(())
63-
}
44+
pub fn start(&mut self) {
45+
compiler_fence(Ordering::SeqCst);
46+
self.ring_buf.start();
6447

65-
#[cfg(adc_v2)]
66-
fn stop(&mut self, err: OverrunError) -> Result<usize, OverrunError> {
67-
self.teardown_adc();
68-
Err(err)
48+
Adc::<T>::start();
6949
}
7050

71-
#[cfg(adc_v2)]
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
51+
pub fn stop(&mut self) {
7952
self.ring_buf.request_pause();
8053

81-
let r = T::regs();
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);
54+
Adc::<T>::stop();
9955

10056
compiler_fence(Ordering::SeqCst);
10157
}
10258

103-
#[cfg(adc_v2)]
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();
59+
pub fn clear(&mut self) {
18560
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);
20661
}
20762

20863
/// Reads measurements from the DMA ring buffer.
@@ -257,31 +112,17 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
257112
"Buffer size must be half the size of the ring buffer"
258113
);
259114

260-
let r = T::regs();
115+
if !self.ring_buf.is_running() {
116+
self.start();
117+
}
261118

262119
#[cfg(adc_v2)]
263120
{
264-
// Start background receive if it was not already started
265-
if !r.cr2().read().dma() {
266-
self.start()?;
267-
}
268-
269121
// Clear overrun flag if set.
270-
if r.sr().read().ovr() {
271-
return self.stop(OverrunError);
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-
}
122+
if T::regs().sr().read().ovr() {
123+
self.stop();
279124

280-
#[cfg(not(adc_v2))]
281-
{
282-
// Start background receive if it was not already started
283-
if !r.cr().read().adstart() {
284-
self.start_continuous_sampling();
125+
return Err(OverrunError);
285126
}
286127
}
287128

@@ -297,50 +138,29 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
297138
/// Receive in the background is terminated if an error is returned.
298139
/// It must then manually be started again by calling `start_continuous_sampling()` or by re-calling `blocking_read()`.
299140
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+
}
301144

302145
#[cfg(adc_v2)]
303146
{
304-
// Start background receive if it was not already started
305-
if !r.cr2().read().dma() {
306-
self.start()?;
307-
}
308-
309147
// Clear overrun flag if set.
310-
if r.sr().read().ovr() {
311-
return self.stop(OverrunError);
312-
}
148+
if T::regs().sr().read().ovr() {
149+
self.stop();
313150

314-
loop {
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-
}
151+
return Err(OverrunError);
324152
}
325153
}
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();
326162

327-
#[cfg(not(adc_v2))]
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-
}
163+
return Err(OverrunError);
344164
}
345165
}
346166
}
@@ -349,7 +169,11 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
349169

350170
impl<T: Instance> Drop for RingBufferedAdc<'_, T> {
351171
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();
353177
rcc::disable::<T>();
354178
}
355179
}

0 commit comments

Comments
 (0)