Skip to content

Commit 6600c2f

Browse files
authored
Merge pull request #4891 from xoviat/adc
adc: move enable after configure_sequence
2 parents a0e92cd + 8e9ec79 commit 6600c2f

File tree

3 files changed

+70
-34
lines changed

3 files changed

+70
-34
lines changed

embassy-stm32/src/adc/g4.rs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
#[cfg(stm32g4)]
22
use pac::adc::regs::Difsel as DifselReg;
33
#[allow(unused)]
4+
#[cfg(stm32g4)]
5+
pub use pac::adc::vals::{Adcaldif, Adstp, Difsel, Dmacfg, Dmaen, Exten, Rovsm, Trovs};
6+
#[allow(unused)]
47
#[cfg(stm32h7)]
58
use pac::adc::vals::{Adcaldif, Difsel, Exten};
6-
#[allow(unused)]
7-
#[cfg(stm32g4)]
8-
pub use pac::adc::vals::{Adcaldif, Difsel, Exten, Rovsm, Trovs};
9-
pub use pac::adccommon::vals::Presc;
10-
pub use stm32_metapac::adc::vals::{Adstp, Dmacfg, Dmaen};
11-
pub use stm32_metapac::adccommon::vals::Dual;
9+
pub use pac::adccommon::vals::{Dual, Presc};
1210

1311
use super::{
1412
Adc, AnyAdcChannel, ConversionMode, Instance, RegularConversionMode, Resolution, RxDma, SampleTime,
@@ -176,43 +174,43 @@ impl<T: Instance> super::SealedAnyInstance for T {
176174
}
177175

178176
fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
177+
T::regs().cr().modify(|w| w.set_aden(false));
178+
179179
// Set sequence length
180180
T::regs().sqr1().modify(|w| {
181181
w.set_l(sequence.len() as u8 - 1);
182182
});
183183

184184
#[cfg(stm32g4)]
185185
let mut difsel = DifselReg::default();
186+
let mut smpr = T::regs().smpr().read();
187+
let mut smpr2 = T::regs().smpr2().read();
188+
let mut sqr1 = T::regs().sqr1().read();
189+
let mut sqr2 = T::regs().sqr2().read();
190+
let mut sqr3 = T::regs().sqr3().read();
191+
let mut sqr4 = T::regs().sqr4().read();
186192

187193
// Configure channels and ranks
188194
for (_i, ((ch, is_differential), sample_time)) in sequence.enumerate() {
189195
let sample_time = sample_time.into();
190196
if ch <= 9 {
191-
T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time));
197+
smpr.set_smp(ch as _, sample_time);
192198
} else {
193-
T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
199+
smpr2.set_smp((ch - 10) as _, sample_time);
194200
}
195201

196202
match _i {
197203
0..=3 => {
198-
T::regs().sqr1().modify(|w| {
199-
w.set_sq(_i, ch);
200-
});
204+
sqr1.set_sq(_i, ch);
201205
}
202206
4..=8 => {
203-
T::regs().sqr2().modify(|w| {
204-
w.set_sq(_i - 4, ch);
205-
});
207+
sqr2.set_sq(_i - 4, ch);
206208
}
207209
9..=13 => {
208-
T::regs().sqr3().modify(|w| {
209-
w.set_sq(_i - 9, ch);
210-
});
210+
sqr3.set_sq(_i - 9, ch);
211211
}
212212
14..=15 => {
213-
T::regs().sqr4().modify(|w| {
214-
w.set_sq(_i - 14, ch);
215-
});
213+
sqr4.set_sq(_i - 14, ch);
216214
}
217215
_ => unreachable!(),
218216
}
@@ -232,12 +230,14 @@ impl<T: Instance> super::SealedAnyInstance for T {
232230
}
233231
}
234232

233+
T::regs().smpr().write_value(smpr);
234+
T::regs().smpr2().write_value(smpr2);
235+
T::regs().sqr1().write_value(sqr1);
236+
T::regs().sqr2().write_value(sqr2);
237+
T::regs().sqr3().write_value(sqr3);
238+
T::regs().sqr4().write_value(sqr4);
235239
#[cfg(stm32g4)]
236-
{
237-
T::regs().cr().modify(|w| w.set_aden(false));
238-
T::regs().difsel().write_value(difsel);
239-
T::enable();
240-
}
240+
T::regs().difsel().write_value(difsel);
241241
}
242242
}
243243

embassy-stm32/src/adc/mod.rs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,16 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
192192
#[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
193193
channel.setup();
194194

195-
#[cfg(not(adc_v4))]
195+
#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h7rs, adc_u0, adc_u5, adc_wba, adc_c0))]
196196
T::enable();
197197
T::configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter());
198198

199+
// On chips with differential channels, enable after configure_sequence to allow setting differential channels
200+
//
201+
// TODO: If hardware allows, enable after configure_sequence on all chips
202+
#[cfg(any(adc_g4, adc_h5))]
203+
T::enable();
204+
199205
T::convert()
200206
}
201207

@@ -229,10 +235,10 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
229235
/// Note: This is not very efficient as the ADC needs to be reconfigured for each read. Use
230236
/// `into_ring_buffered`, `into_ring_buffered_and_injected`
231237
///
232-
/// In STM32C0, channels bigger than 14 cannot be read using sequencer, so you have to use
233-
/// either blocking reads or use the mechanism to read in HW order (CHSELRMOD=0).
234-
///
235-
/// In addtion, on STM320, this method will panic if the channels are not passed in order
238+
/// Note: Depending on hardware limitations, this method may require channels to be passed
239+
/// in order or require the sequence to have the same sample time for all channnels, depending
240+
/// on the number and properties of the channels in the sequence. This method will panic if
241+
/// the hardware cannot deliver the requested configuration.
236242
pub async fn read(
237243
&mut self,
238244
rx_dma: embassy_hal_internal::Peri<'_, impl RxDma<T>>,
@@ -249,14 +255,20 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
249255
"Asynchronous read sequence cannot be more than 16 in length"
250256
);
251257

252-
// Ensure no conversions are ongoing and ADC is enabled.
258+
// Ensure no conversions are ongoing
253259
T::stop();
260+
#[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
254261
T::enable();
255262

256263
T::configure_sequence(
257264
sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
258265
);
259266

267+
// On chips with differential channels, enable after configure_sequence to allow setting differential channels
268+
//
269+
// TODO: If hardware allows, enable after configure_sequence on all chips
270+
#[cfg(any(adc_g4, adc_h5))]
271+
T::enable();
260272
T::configure_dma(ConversionMode::Singular);
261273

262274
let request = rx_dma.request();
@@ -294,6 +306,11 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
294306
///
295307
/// # Returns
296308
/// A `RingBufferedAdc<'a, T>` instance configured for continuous DMA-based sampling.
309+
///
310+
/// Note: Depending on hardware limitations, this method may require channels to be passed
311+
/// in order or require the sequence to have the same sample time for all channnels, depending
312+
/// on the number and properties of the channels in the sequence. This method will panic if
313+
/// the hardware cannot deliver the requested configuration.
297314
pub fn into_ring_buffered<'a>(
298315
self,
299316
dma: embassy_hal_internal::Peri<'a, impl RxDma<T>>,
@@ -307,15 +324,20 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
307324
sequence.len() <= 16,
308325
"Asynchronous read sequence cannot be more than 16 in length"
309326
);
310-
// reset conversions and enable the adc
327+
// Ensure no conversions are ongoing
311328
T::stop();
329+
#[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
312330
T::enable();
313331

314-
//adc side setup
315332
T::configure_sequence(
316333
sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
317334
);
318335

336+
// On chips with differential channels, enable after configure_sequence to allow setting differential channels
337+
//
338+
// TODO: If hardware allows, enable after configure_sequence on all chips
339+
#[cfg(any(adc_g4, adc_h5))]
340+
T::enable();
319341
T::configure_dma(ConversionMode::Repeated(mode));
320342

321343
core::mem::forget(self);

embassy-stm32/src/adc/v3.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ impl<T: Instance> super::SealedAnyInstance for T {
260260
}
261261

262262
fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
263+
#[cfg(adc_h5)]
264+
T::regs().cr().modify(|w| w.set_aden(false));
265+
263266
// Set sequence length
264267
#[cfg(not(any(adc_g0, adc_u0)))]
265268
T::regs().sqr1().modify(|w| {
@@ -294,8 +297,11 @@ impl<T: Instance> super::SealedAnyInstance for T {
294297
#[cfg(adc_u0)]
295298
let mut channel_mask = 0;
296299

300+
#[cfg(adc_h5)]
301+
let mut difsel = 0u32;
302+
297303
// Configure channels and ranks
298-
for (_i, ((channel, _), sample_time)) in sequence.enumerate() {
304+
for (_i, ((channel, _is_differential), sample_time)) in sequence.enumerate() {
299305
// RM0492, RM0481, etc.
300306
// "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
301307
#[cfg(any(adc_h5, adc_h7rs))]
@@ -357,12 +363,20 @@ impl<T: Instance> super::SealedAnyInstance for T {
357363
_ => unreachable!(),
358364
}
359365

366+
#[cfg(adc_h5)]
367+
{
368+
difsel |= (_is_differential as u32) << channel;
369+
}
370+
360371
#[cfg(adc_u0)]
361372
{
362373
channel_mask |= 1 << channel;
363374
}
364375
}
365376

377+
#[cfg(adc_h5)]
378+
T::regs().difsel().write(|w| w.set_difsel(difsel));
379+
366380
// On G0 and U0 enabled channels are sampled from 0 to last channel.
367381
// It is possible to add up to 8 sequences if CHSELRMOD = 1.
368382
// However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used.

0 commit comments

Comments
 (0)