aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/build.rs1
-rw-r--r--embassy-stm32/src/adc/v4.rs137
2 files changed, 126 insertions, 12 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 24e2226a2..df866b5ff 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -1182,6 +1182,7 @@ fn main() {
1182 (("adc", "ADC1"), quote!(crate::adc::RxDma)), 1182 (("adc", "ADC1"), quote!(crate::adc::RxDma)),
1183 (("adc", "ADC2"), quote!(crate::adc::RxDma)), 1183 (("adc", "ADC2"), quote!(crate::adc::RxDma)),
1184 (("adc", "ADC3"), quote!(crate::adc::RxDma)), 1184 (("adc", "ADC3"), quote!(crate::adc::RxDma)),
1185 (("adc", "ADC4"), quote!(crate::adc::RxDma)),
1185 (("ucpd", "RX"), quote!(crate::ucpd::RxDma)), 1186 (("ucpd", "RX"), quote!(crate::ucpd::RxDma)),
1186 (("ucpd", "TX"), quote!(crate::ucpd::TxDma)), 1187 (("ucpd", "TX"), quote!(crate::ucpd::TxDma)),
1187 (("usart", "RX"), quote!(crate::usart::RxDma)), 1188 (("usart", "RX"), quote!(crate::usart::RxDma)),
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index 50db646fe..f4b62d80e 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -1,8 +1,12 @@
1#[allow(unused)] 1#[allow(unused)]
2use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel}; 2use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel};
3use pac::adc::vals::{Adstp, Dmngt};
3use pac::adccommon::vals::Presc; 4use pac::adccommon::vals::Presc;
4 5
5use super::{blocking_delay_us, Adc, AdcChannel, Instance, Resolution, SampleTime}; 6use super::{
7 blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel,
8};
9use crate::dma::Transfer;
6use crate::time::Hertz; 10use crate::time::Hertz;
7use crate::{pac, rcc, Peripheral}; 11use crate::{pac, rcc, Peripheral};
8 12
@@ -34,7 +38,7 @@ const VBAT_CHANNEL: u8 = 17;
34/// Internal voltage reference channel. 38/// Internal voltage reference channel.
35pub struct VrefInt; 39pub struct VrefInt;
36impl<T: Instance> AdcChannel<T> for VrefInt {} 40impl<T: Instance> AdcChannel<T> for VrefInt {}
37impl<T: Instance> super::SealedAdcChannel<T> for VrefInt { 41impl<T: Instance> SealedAdcChannel<T> for VrefInt {
38 fn channel(&self) -> u8 { 42 fn channel(&self) -> u8 {
39 VREF_CHANNEL 43 VREF_CHANNEL
40 } 44 }
@@ -43,7 +47,7 @@ impl<T: Instance> super::SealedAdcChannel<T> for VrefInt {
43/// Internal temperature channel. 47/// Internal temperature channel.
44pub struct Temperature; 48pub struct Temperature;
45impl<T: Instance> AdcChannel<T> for Temperature {} 49impl<T: Instance> AdcChannel<T> for Temperature {}
46impl<T: Instance> super::SealedAdcChannel<T> for Temperature { 50impl<T: Instance> SealedAdcChannel<T> for Temperature {
47 fn channel(&self) -> u8 { 51 fn channel(&self) -> u8 {
48 TEMP_CHANNEL 52 TEMP_CHANNEL
49 } 53 }
@@ -52,7 +56,7 @@ impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
52/// Internal battery voltage channel. 56/// Internal battery voltage channel.
53pub struct Vbat; 57pub struct Vbat;
54impl<T: Instance> AdcChannel<T> for Vbat {} 58impl<T: Instance> AdcChannel<T> for Vbat {}
55impl<T: Instance> super::SealedAdcChannel<T> for Vbat { 59impl<T: Instance> SealedAdcChannel<T> for Vbat {
56 fn channel(&self) -> u8 { 60 fn channel(&self) -> u8 {
57 VBAT_CHANNEL 61 VBAT_CHANNEL
58 } 62 }
@@ -247,6 +251,11 @@ impl<'d, T: Instance> Adc<'d, T> {
247 self.sample_time = sample_time; 251 self.sample_time = sample_time;
248 } 252 }
249 253
254 /// Get the ADC sample time.
255 pub fn sample_time(&self) -> SampleTime {
256 self.sample_time
257 }
258
250 /// Set the ADC resolution. 259 /// Set the ADC resolution.
251 pub fn set_resolution(&mut self, resolution: Resolution) { 260 pub fn set_resolution(&mut self, resolution: Resolution) {
252 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); 261 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
@@ -273,25 +282,120 @@ impl<'d, T: Instance> Adc<'d, T> {
273 282
274 /// Read an ADC channel. 283 /// Read an ADC channel.
275 pub fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 284 pub fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
276 channel.setup(); 285 self.read_channel(channel)
286 }
287
288 /// Asynchronously read from sequence of ADC channels.
289 pub async fn read_async(
290 &mut self,
291 rx_dma: &mut impl RxDma<T>,
292 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>,
293 data: &mut [u16],
294 ) {
295 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
296
297 assert!(
298 sequence.len() <= 16,
299 "Asynchronous read sequence cannot be more than 16 in length"
300 );
301
302 // Ensure no conversions are ongoing
303 Self::cancel_conversions();
304
305 // Set sequence length
306 T::regs().sqr1().modify(|w| {
307 w.set_l(sequence.len() as u8 - 1);
308 });
309
310 // Configure channels and ranks
311 for (i, (channel, sample_time)) in sequence.enumerate() {
312 Self::configure_channel(channel, sample_time);
313 match i {
314 0..=3 => {
315 T::regs().sqr1().modify(|w| {
316 w.set_sq(i, channel.channel());
317 });
318 }
319 4..=8 => {
320 T::regs().sqr2().modify(|w| {
321 w.set_sq(i - 4, channel.channel());
322 });
323 }
324 9..=13 => {
325 T::regs().sqr3().modify(|w| {
326 w.set_sq(i - 9, channel.channel());
327 });
328 }
329 14..=15 => {
330 T::regs().sqr4().modify(|w| {
331 w.set_sq(i - 14, channel.channel());
332 });
333 }
334 _ => unreachable!(),
335 }
336 }
337
338 // Set continuous mode with oneshot dma.
339 // Clear overrun flag before starting transfer.
340
341 T::regs().isr().modify(|reg| {
342 reg.set_ovr(true);
343 });
344 T::regs().cfgr().modify(|reg| {
345 reg.set_cont(true);
346 reg.set_dmngt(Dmngt::DMA_ONESHOT);
347 });
348
349 let request = rx_dma.request();
350 let transfer = unsafe {
351 Transfer::new_read(
352 rx_dma,
353 request,
354 T::regs().dr().as_ptr() as *mut u16,
355 data,
356 Default::default(),
357 )
358 };
277 359
278 self.read_channel(channel.channel()) 360 // Start conversion
361 T::regs().cr().modify(|reg| {
362 reg.set_adstart(true);
363 });
364
365 // Wait for conversion sequence to finish.
366 transfer.await;
367
368 // Ensure conversions are finished.
369 Self::cancel_conversions();
370
371 // Reset configuration.
372 T::regs().cfgr().modify(|reg| {
373 reg.set_cont(false);
374 reg.set_dmngt(Dmngt::from_bits(0));
375 });
279 } 376 }
280 377
281 fn read_channel(&mut self, channel: u8) -> u16 { 378 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
282 // Configure channel 379 channel.setup();
283 Self::set_channel_sample_time(channel, self.sample_time); 380
381 let channel = channel.channel();
382
383 Self::set_channel_sample_time(channel, sample_time);
284 384
285 #[cfg(stm32h7)] 385 #[cfg(stm32h7)]
286 { 386 {
287 T::regs().cfgr2().modify(|w| w.set_lshift(0)); 387 T::regs().cfgr2().modify(|w| w.set_lshift(0));
288 T::regs() 388 T::regs()
289 .pcsel() 389 .pcsel()
290 .write(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED)); 390 .modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
291 } 391 }
392 }
292 393
293 T::regs().sqr1().write(|reg| { 394 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
294 reg.set_sq(0, channel); 395 Self::configure_channel(channel, self.sample_time);
396
397 T::regs().sqr1().modify(|reg| {
398 reg.set_sq(0, channel.channel());
295 reg.set_l(0); 399 reg.set_l(0);
296 }); 400 });
297 401
@@ -306,4 +410,13 @@ impl<'d, T: Instance> Adc<'d, T> {
306 T::regs().smpr(1).modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); 410 T::regs().smpr(1).modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
307 } 411 }
308 } 412 }
413
414 fn cancel_conversions() {
415 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
416 T::regs().cr().modify(|reg| {
417 reg.set_adstp(Adstp::STOP);
418 });
419 while T::regs().cr().read().adstart() {}
420 }
421 }
309} 422}