Skip to content

Commit 9f16750

Browse files
committed
Adds delays for start up times
1 parent 75bee83 commit 9f16750

File tree

5 files changed

+52
-16
lines changed

5 files changed

+52
-16
lines changed

examples/adc-dma-circ.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn main() -> ! {
3232
let dma_ch1 = p.DMA1.split(&mut rcc.ahb).1;
3333

3434
// Setup ADC
35-
let adc1 = adc::Adc::adc1(p.ADC1, &mut rcc.apb2, clocks.adcclk());
35+
let adc1 = adc::Adc::adc1(p.ADC1, &mut rcc.apb2, clocks);
3636

3737
// Setup GPIOA
3838
let mut gpioa = p.GPIOA.split(&mut rcc.apb2);

examples/adc-dma-rx.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn main() -> ! {
3131
let dma_ch1 = p.DMA1.split(&mut rcc.ahb).1;
3232

3333
// Setup ADC
34-
let adc1 = adc::Adc::adc1(p.ADC1, &mut rcc.apb2, clocks.adcclk());
34+
let adc1 = adc::Adc::adc1(p.ADC1, &mut rcc.apb2, clocks);
3535

3636
// Setup GPIOA
3737
let mut gpioa = p.GPIOA.split(&mut rcc.apb2);
@@ -42,9 +42,15 @@ fn main() -> ! {
4242
let adc_dma = adc1.with_dma(adc_ch0, dma_ch1);
4343
let buf = singleton!(: [u16; 8] = [0; 8]).unwrap();
4444

45+
// The read method consumes the buf and self, starts the adc and dma transfer and returns a
46+
// RxDma struct. The wait method consumes the RxDma struct, waits for the whole transfer to be
47+
// completed and then returns the updated buf and underlying adc_dma struct. For non blocking,
48+
// one can call the is_done method of RxDma and only call wait after that method returns true.
4549
let (_buf, adc_dma) = adc_dma.read(buf).wait();
4650
asm::bkpt();
4751

52+
// Consumes the AdcDma struct, restores adc configuration to previous state and returns the
53+
// Adc struct in normal mode.
4854
let (_adc1, _adc_ch0, _dma_ch1) = adc_dma.split();
4955
asm::bkpt();
5056

examples/adc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ fn main() -> ! {
2929
hprintln!("adc freq: {}", clocks.adcclk().0).unwrap();
3030

3131
// Setup ADC
32-
let mut adc1 = adc::Adc::adc1(p.ADC1, &mut rcc.apb2, clocks.adcclk());
32+
let mut adc1 = adc::Adc::adc1(p.ADC1, &mut rcc.apb2, clocks);
3333

3434
#[cfg(feature = "stm32f103")]
35-
let mut adc2 = adc::Adc::adc2(p.ADC2, &mut rcc.apb2, clocks.adcclk());
35+
let mut adc2 = adc::Adc::adc2(p.ADC2, &mut rcc.apb2, clocks);
3636

3737
// Setup GPIOB
3838
let mut gpiob = p.GPIOB.split(&mut rcc.apb2);

examples/adc_temperature.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fn main() -> ! {
2525
hprintln!("adc freq: {}", clocks.adcclk().0).unwrap();
2626

2727
// Setup ADC
28-
let mut adc = adc::Adc::adc1(p.ADC1, &mut rcc.apb2, clocks.adcclk());
28+
let mut adc = adc::Adc::adc1(p.ADC1, &mut rcc.apb2, clocks);
2929

3030
// Read temperature sensor
3131
loop {

src/adc.rs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use embedded_hal::adc::{Channel, OneShot};
44

55
use crate::gpio::Analog;
66
use crate::gpio::{gpioa, gpiob, gpioc};
7-
use crate::rcc::APB2;
8-
use crate::time::Hertz;
7+
use crate::rcc::{APB2, Clocks};
98
use crate::dma::{Receive, TransferPayload, dma1::C1, CircBuffer, Transfer, W, RxDma};
109
use core::sync::atomic::{self, Ordering};
10+
use cortex_m::asm::delay;
1111

1212
use crate::stm32::ADC1;
1313
#[cfg(any(
@@ -20,7 +20,7 @@ pub struct Adc<ADC> {
2020
rb: ADC,
2121
sample_time: AdcSampleTime,
2222
align: AdcAlign,
23-
clk: Hertz
23+
clocks: Clocks
2424
}
2525

2626
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -175,18 +175,29 @@ macro_rules! adc_hal {
175175
///
176176
/// Sets all configurable parameters to one-shot defaults,
177177
/// performs a boot-time calibration.
178-
pub fn $init(adc: $ADC, apb2: &mut APB2, clk: Hertz) -> Self {
178+
pub fn $init(adc: $ADC, apb2: &mut APB2, clocks: Clocks) -> Self {
179179
let mut s = Self {
180180
rb: adc,
181181
sample_time: AdcSampleTime::default(),
182182
align: AdcAlign::default(),
183-
clk: clk,
183+
clocks,
184184
};
185185
s.enable_clock(apb2);
186186
s.power_down();
187187
s.reset(apb2);
188188
s.setup_oneshot();
189189
s.power_up();
190+
191+
// The manual states that we need to wait two ADC clocks cycles after power-up
192+
// before starting calibration, we already delayed in the power-up process, but
193+
// if the adc clock is too low that was not enough.
194+
if s.clocks.adcclk().0 < 2_500_000 {
195+
let two_adc_cycles = s.clocks.sysclk().0 / s.clocks.adcclk().0 *2;
196+
let already_delayed = s.clocks.sysclk().0 / 800_000;
197+
if two_adc_cycles > already_delayed {
198+
delay(two_adc_cycles - already_delayed);
199+
}
200+
}
190201
s.calibrate();
191202
s
192203
}
@@ -234,6 +245,12 @@ macro_rules! adc_hal {
234245

235246
fn power_up(&mut self) {
236247
self.rb.cr2.modify(|_, w| w.adon().set_bit());
248+
249+
// The reference manual says that a stabilization time is needed after power_up,
250+
// this time can be found in the datasheets.
251+
// Here we are delaying for approximately 1us, considering 1.25 instructions per
252+
// cycle. Do we support a chip which needs more than 1us ?
253+
delay(self.clocks.sysclk().0 / 800_000);
237254
}
238255

239256
fn power_down(&mut self) {
@@ -249,6 +266,10 @@ macro_rules! adc_hal {
249266
apb2.enr().modify(|_, w| w.$adcxen().set_bit());
250267
}
251268

269+
fn disable_clock(&mut self, apb2: &mut APB2) {
270+
apb2.enr().modify(|_, w| w.$adcxen().clear_bit());
271+
}
272+
252273
fn calibrate(&mut self) {
253274
/* reset calibration */
254275
self.rb.cr2.modify(|_, w| w.rstcal().set_bit());
@@ -365,6 +386,13 @@ macro_rules! adc_hal {
365386
let res = self.rb.dr.read().data().bits();
366387
res
367388
}
389+
390+
/// Powers down the ADC, disables the ADC clock and releases the ADC Peripheral
391+
pub fn release(mut self, apb2: &mut APB2) -> $ADC {
392+
self.power_down();
393+
self.disable_clock(apb2);
394+
self.rb
395+
}
368396
}
369397

370398
impl<WORD, PIN> OneShot<$ADC, WORD, PIN> for Adc<$ADC>
@@ -375,9 +403,7 @@ macro_rules! adc_hal {
375403
type Error = ();
376404

377405
fn read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
378-
self.power_up();
379406
let res = self.convert(PIN::channel());
380-
self.power_down();
381407
Ok(res.into())
382408
}
383409
}
@@ -390,14 +416,18 @@ impl Adc<ADC1> {
390416
fn read_aux(&mut self, chan: u8) -> u16 {
391417
let tsv_off = if self.rb.cr2.read().tsvrefe().bit_is_clear() {
392418
self.rb.cr2.modify(|_, w| w.tsvrefe().set_bit());
419+
420+
// The reference manual says that a stabilization time is needed after the powering the
421+
// sensor, this time can be found in the datasheets.
422+
// Here we are delaying for approximately 10us, considering 1.25 instructions per
423+
// cycle. Do we support a chip which needs more than 10us ?
424+
delay(self.clocks.sysclk().0 / 80_000);
393425
true
394426
} else {
395427
false
396428
};
397429

398-
self.power_up();
399430
let val = self.convert(chan);
400-
self.power_down();
401431

402432
if tsv_off {
403433
self.rb.cr2.modify(|_, w| w.tsvrefe().clear_bit());
@@ -431,14 +461,14 @@ impl Adc<ADC1> {
431461
// recommended ADC sampling for temperature sensor is 17.1 usec,
432462
// so use the following approximate settings
433463
// to support all ADC frequencies
434-
let sample_time = match self.clk.0 {
464+
let sample_time = match self.clocks.adcclk().0 {
435465
0 ... 1_200_000 => AdcSampleTime::T_1,
436466
1_200_001 ... 1_500_000 => AdcSampleTime::T_7,
437467
1_500_001 ... 2_400_000 => AdcSampleTime::T_13,
438468
2_400_001 ... 3_100_000 => AdcSampleTime::T_28,
439469
3_100_001 ... 4_000_000 => AdcSampleTime::T_41,
440470
4_000_001 ... 5_000_000 => AdcSampleTime::T_55,
441-
5_000_001 ... 10_000_000 => AdcSampleTime::T_71,
471+
5_000_001 ... 14_000_000 => AdcSampleTime::T_71,
442472
_ => AdcSampleTime::T_239,
443473
};
444474

0 commit comments

Comments
 (0)