aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/adc/u5_adc4.rs120
-rw-r--r--examples/stm32u5/src/bin/adc.rs102
2 files changed, 177 insertions, 45 deletions
diff --git a/embassy-stm32/src/adc/u5_adc4.rs b/embassy-stm32/src/adc/u5_adc4.rs
index 8d0c1abed..ddc1b58a2 100644
--- a/embassy-stm32/src/adc/u5_adc4.rs
+++ b/embassy-stm32/src/adc/u5_adc4.rs
@@ -4,13 +4,14 @@ pub use crate::pac::adc::vals::Adc4Presc as Presc;
4pub use crate::pac::adc::regs::Adc4Chselrmod0; 4pub use crate::pac::adc::regs::Adc4Chselrmod0;
5 5
6#[allow(unused)] 6#[allow(unused)]
7use pac::adc::vals::{Adc4Exten, Adc4OversamplingRatio}; 7use pac::adc::vals::{Adc4Exten, Adc4OversamplingRatio, Adc4Dmacfg};
8 8
9use super::{ 9use super::{
10 blocking_delay_us, AdcChannel, SealedAdcChannel 10 blocking_delay_us, AdcChannel, SealedAdcChannel, AnyAdcChannel, RxDma4
11}; 11};
12use crate::time::Hertz; 12use crate::time::Hertz;
13use crate::{pac, rcc, Peripheral}; 13use crate::{pac, rcc, Peripheral};
14use crate::dma::Transfer;
14 15
15const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); 16const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55);
16 17
@@ -182,6 +183,12 @@ pub struct Adc4<'d, T: Instance> {
182 adc: crate::PeripheralRef<'d, T>, 183 adc: crate::PeripheralRef<'d, T>,
183} 184}
184 185
186#[derive(Debug)]
187pub enum Adc4Error {
188 InvalidSequence,
189 DMAError
190}
191
185impl<'d, T: Instance> Adc4<'d, T> { 192impl<'d, T: Instance> Adc4<'d, T> {
186 /// Create a new ADC driver. 193 /// Create a new ADC driver.
187 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self { 194 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
@@ -244,6 +251,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
244 // single conversion mode, software trigger 251 // single conversion mode, software trigger
245 T::regs().cfgr1().modify(|w| { 252 T::regs().cfgr1().modify(|w| {
246 w.set_cont(false); 253 w.set_cont(false);
254 w.set_discen(false);
247 w.set_exten(Adc4Exten::DISABLED); 255 w.set_exten(Adc4Exten::DISABLED);
248 }); 256 });
249 257
@@ -336,8 +344,18 @@ impl<'d, T: Instance> Adc4<'d, T> {
336 }) 344 })
337 } 345 }
338 346
339 /// Perform a single conversion. 347 /// Read an ADC channel.
340 fn convert(&mut self) -> u16 { 348 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16{
349 channel.setup();
350 T::regs().cfgr1().modify(|reg| {
351 reg.set_chselrmod(false);
352 });
353
354 T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32));
355 T::regs().chselrmod0().modify(|w| {
356 w.set_chsel(channel.channel() as usize, true);
357 });
358
341 T::regs().isr().modify(|reg| { 359 T::regs().isr().modify(|reg| {
342 reg.set_eos(true); 360 reg.set_eos(true);
343 reg.set_eoc(true); 361 reg.set_eoc(true);
@@ -355,22 +373,92 @@ impl<'d, T: Instance> Adc4<'d, T> {
355 T::regs().dr().read().0 as u16 373 T::regs().dr().read().0 as u16
356 } 374 }
357 375
358 /// Read an ADC channel. 376 /// Channels can not be repeated and must be in ascending order!
359 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 377 /// TODO: broken
360 self.read_channel(channel) 378 pub async fn read(
361 } 379 &mut self,
380 rx_dma: &mut impl RxDma4<T>,
381 sequence: impl ExactSizeIterator<Item = &mut AnyAdcChannel<T>>,
382 readings: &mut [u16],
383 ) -> Result<(), Adc4Error> {
384 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
385 assert!(
386 sequence.len() == readings.len(),
387 "Sequence length must be equal to readings length"
388 );
389
390 // Ensure no conversions are ongoing
391 Self::cancel_conversions();
362 392
363 fn configure_channel(channel: &mut impl AdcChannel<T>) { 393 T::regs().isr().modify(|reg| {
364 channel.setup(); 394 reg.set_ovr(true);
395 reg.set_eos(true);
396 reg.set_eoc(true);
397 });
398
399 T::regs().cfgr1().modify(|reg| {
400 reg.set_dmaen(true);
401 reg.set_dmacfg(Adc4Dmacfg::ONESHOT);
402 reg.set_chselrmod(false);
403 });
404
405
406 let mut prev_channel: i16 = -1;
365 T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32)); 407 T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32));
366 T::regs().chselrmod0().modify(|w| { 408 for channel in sequence {
367 w.set_chsel(channel.channel() as usize, true); 409 let channel_num = channel.channel;
410 if channel_num as i16 <= prev_channel {
411 return Err(Adc4Error::InvalidSequence);
412 };
413 prev_channel = channel_num as i16;
414
415 T::regs().chselrmod0().modify(|w| {
416 w.set_chsel(channel.channel as usize, true);
417 });
418 };
419
420 let request = rx_dma.request();
421 let transfer = unsafe {
422 Transfer::new_read(
423 rx_dma,
424 request,
425 T::regs().dr().as_ptr() as *mut u16,
426 readings,
427 Default::default(),
428 )
429 };
430
431 // Start conversion
432 T::regs().cr().modify(|reg| {
433 reg.set_adstart(true);
368 }); 434 });
435
436 // Wait for conversion sequence to finish.
437 transfer.await;
438
439 blocking_delay_us(10);
440
441 // Ensure conversions are finished.
442 Self::cancel_conversions();
443
444 // Reset configuration.
445 T::regs().cfgr1().modify(|reg| {
446 reg.set_dmaen(false);
447 });
448
449 if T::regs().isr().read().ovr() {
450 Err(Adc4Error::DMAError)
451 } else {
452 Ok(())
453 }
369 } 454 }
370 455
371 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 456 fn cancel_conversions() {
372 Self::configure_channel(channel); 457 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
373 let ret = self.convert(); 458 T::regs().cr().modify(|reg| {
374 ret 459 reg.set_adstp(true);
460 });
461 while T::regs().cr().read().adstart() {}
462 }
375 } 463 }
376} \ No newline at end of file 464} \ No newline at end of file
diff --git a/examples/stm32u5/src/bin/adc.rs b/examples/stm32u5/src/bin/adc.rs
index 049b985cf..4632f2cd1 100644
--- a/examples/stm32u5/src/bin/adc.rs
+++ b/examples/stm32u5/src/bin/adc.rs
@@ -36,55 +36,99 @@ async fn main(spawner: embassy_executor::Spawner) {
36 36
37 let mut p = embassy_stm32::init(config); 37 let mut p = embassy_stm32::init(config);
38 38
39 let mut adc = adc::Adc::new(p.ADC1); 39 // **** ADC1 init ****
40 let mut adc_pin1 = p.PA3; // A0 on nucleo u5a5 40 let mut adc1 = adc::Adc::new(p.ADC1);
41 let mut adc_pin2 = p.PA2; // A1 on nucleo u5a5 41 let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5
42 adc.set_resolution(adc::Resolution::BITS14); 42 let mut adc1_pin2 = p.PA2; // A1
43 adc.set_averaging(adc::Averaging::Samples1024); 43 adc1.set_resolution(adc::Resolution::BITS14);
44 adc.set_sample_time(adc::SampleTime::CYCLES160_5); 44 adc1.set_averaging(adc::Averaging::Samples1024);
45 let max = adc::resolution_to_max_count(adc::Resolution::BITS14); 45 adc1.set_sample_time(adc::SampleTime::CYCLES160_5);
46 46 let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14);
47
48 // **** ADC2 init ****
49 let mut adc2 = adc::Adc::new(p.ADC2);
50 let mut adc2_pin1 = p.PC3; // A2
51 let mut adc2_pin2 = p.PB0; // A3
52 adc2.set_resolution(adc::Resolution::BITS14);
53 adc2.set_averaging(adc::Averaging::Samples1024);
54 adc2.set_sample_time(adc::SampleTime::CYCLES160_5);
55 let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14);
56
57 // **** ADC4 init ****
47 let mut adc4 = adc4::Adc4::new(p.ADC4); 58 let mut adc4 = adc4::Adc4::new(p.ADC4);
48 let mut adc4_pin1 = p.PD11; 59 let mut adc4_pin1 = p.PC1; // A4
49 let mut adc4_pin2 = p.PC0; 60 let mut adc4_pin2 = p.PC0; // A5
50 adc4.set_resolution(adc4::Resolution::BITS12); 61 adc4.set_resolution(adc4::Resolution::BITS12);
51 adc4.set_averaging(adc4::Averaging::Samples256); 62 adc4.set_averaging(adc4::Averaging::Samples256);
52 adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); 63 adc4.set_sample_time(adc4::SampleTime::CYCLES1_5);
53 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); 64 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
54 65
55 let raw: u16 = adc.blocking_read(&mut adc_pin1); 66 // **** ADC1 blocking read ****
56 let volt: f32 = 3.3 * raw as f32 / max as f32; 67 let raw: u16 = adc1.blocking_read(&mut adc1_pin1);
57 info!("Read 1 pin 1 {}", volt); 68 let volt: f32 = 3.3 * raw as f32 / max1 as f32;
69 info!("Read adc1 pin 1 {}", volt);
70
71 let raw: u16 = adc1.blocking_read(&mut adc1_pin2);
72 let volt: f32 = 3.3 * raw as f32 / max1 as f32;
73 info!("Read adc1 pin 2 {}", volt);
74
75 // **** ADC2 blocking read ****
76 let raw: u16 = adc2.blocking_read(&mut adc2_pin1);
77 let volt: f32 = 3.3 * raw as f32 / max2 as f32;
78 info!("Read adc2 pin 1 {}", volt);
58 79
59 let raw: u16 = adc.blocking_read(&mut adc_pin2); 80 let raw: u16 = adc2.blocking_read(&mut adc2_pin2);
60 let volt: f32 = 3.3 * raw as f32 / max as f32; 81 let volt: f32 = 3.3 * raw as f32 / max2 as f32;
61 info!("Read 1 pin 2 {}", volt); 82 info!("Read adc2 pin 2 {}", volt);
62 83
63 let raw4: u16 = adc4.blocking_read(&mut adc4_pin1); 84 // **** ADC4 blocking read ****
64 let volt4: f32 = 3.3 * raw4 as f32 / max4 as f32; 85 let raw: u16 = adc4.blocking_read(&mut adc4_pin1);
65 info!("Read 4 pin 1 {}", volt4); 86 let volt: f32 = 3.3 * raw as f32 / max4 as f32;
87 info!("Read adc4 pin 1 {}", volt);
66 88
67 let raw4: u16 = adc4.blocking_read(&mut adc4_pin2); 89 let raw: u16 = adc4.blocking_read(&mut adc4_pin2);
68 let volt4: f32 = 3.3 * raw4 as f32 / max4 as f32; 90 let volt: f32 = 3.3 * raw as f32 / max4 as f32;
69 info!("Read 4 pin 2 {}", volt4); 91 info!("Read adc4 pin 2 {}", volt);
70 92
71 let mut degraded1 = adc_pin1.degrade_adc(); 93 // **** ADC1 async read ****
72 let mut degraded2 = adc_pin2.degrade_adc(); 94 let mut degraded11 = adc1_pin1.degrade_adc();
95 let mut degraded12 = adc1_pin2.degrade_adc();
73 let mut measurements = [0u16; 2]; 96 let mut measurements = [0u16; 2];
74 97
75 adc.read( 98 adc1.read(
76 &mut p.GPDMA1_CH0, 99 &mut p.GPDMA1_CH0,
77 [ 100 [
78 (&mut degraded2, adc::SampleTime::CYCLES160_5), 101 (&mut degraded11, adc::SampleTime::CYCLES160_5),
79 (&mut degraded1, adc::SampleTime::CYCLES160_5), 102 (&mut degraded12, adc::SampleTime::CYCLES160_5),
80 ] 103 ]
81 .into_iter(), 104 .into_iter(),
82 &mut measurements, 105 &mut measurements,
83 ).await; 106 ).await;
84 let volt1: f32 = 3.3 * measurements[1] as f32 / max as f32; 107 let volt1: f32 = 3.3 * measurements[0] as f32 / max1 as f32;
85 let volt2: f32 = 3.3 * measurements[0] as f32 / max as f32; 108 let volt2: f32 = 3.3 * measurements[1] as f32 / max1 as f32;
86 109
87 info!("Async read 1 pin 1 {}", volt1); 110 info!("Async read 1 pin 1 {}", volt1);
88 info!("Async read 1 pin 2 {}", volt2); 111 info!("Async read 1 pin 2 {}", volt2);
89 112
113 // **** ADC2 does not support async read ****
114
115 // **** ADC4 async read ****
116 let mut degraded41 = adc4_pin1.degrade_adc();
117 let mut degraded42 = adc4_pin2.degrade_adc();
118 let mut measurements = [0u16; 2];
119
120 // The channels must be in ascending order and can't repeat for ADC4
121 adc4.read(
122 &mut p.GPDMA1_CH1,
123 [
124 &mut degraded42,
125 &mut degraded41,
126 ]
127 .into_iter(),
128 &mut measurements,
129 ).await.unwrap();
130 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32;
131 let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32;
132 info!("Async read 4 pin 1 {}", volt1);
133 info!("Async read 4 pin 2 {}", volt2);
90} \ No newline at end of file 134} \ No newline at end of file