stm32 adc: remove DelayNs
This commit is contained in:
parent
fd802ffdfd
commit
68b1a840c6
6 changed files with 70 additions and 41 deletions
|
@ -3,7 +3,6 @@ use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_hal_internal::into_ref;
|
use embassy_hal_internal::into_ref;
|
||||||
use embedded_hal_1::delay::DelayNs;
|
|
||||||
|
|
||||||
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
|
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
@ -48,14 +47,18 @@ impl<T: Instance> super::SealedAdcPin<T> for Temperature {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Adc<'d, T> {
|
impl<'d, T: Instance> Adc<'d, T> {
|
||||||
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayNs) -> Self {
|
pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
|
||||||
into_ref!(adc);
|
into_ref!(adc);
|
||||||
T::enable_and_reset();
|
T::enable_and_reset();
|
||||||
T::regs().cr2().modify(|reg| reg.set_adon(true));
|
T::regs().cr2().modify(|reg| reg.set_adon(true));
|
||||||
|
|
||||||
// 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’)
|
// 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’)
|
||||||
// for at least two ADC clock cycles
|
// for at least two ADC clock cycles.
|
||||||
delay.delay_us((1_000_000 * 2) / Self::freq().0 + 1);
|
let us = (1_000_000 * 2) / Self::freq().0 + 1;
|
||||||
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(us));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / (1000_000 / us));
|
||||||
|
|
||||||
// Reset calibration
|
// Reset calibration
|
||||||
T::regs().cr2().modify(|reg| reg.set_rstcal(true));
|
T::regs().cr2().modify(|reg| reg.set_rstcal(true));
|
||||||
|
@ -70,7 +73,11 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// One cycle after calibration
|
// One cycle after calibration
|
||||||
delay.delay_us((1_000_000) / Self::freq().0 + 1);
|
let us = (1_000_000 * 1) / Self::freq().0 + 1;
|
||||||
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(us));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / (1000_000 / us));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
adc,
|
adc,
|
||||||
|
@ -95,7 +102,7 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_vref(&self, _delay: &mut impl DelayNs) -> Vref {
|
pub fn enable_vref(&self) -> Vref {
|
||||||
T::regs().cr2().modify(|reg| {
|
T::regs().cr2().modify(|reg| {
|
||||||
reg.set_tsvrefe(true);
|
reg.set_tsvrefe(true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,6 @@ use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_hal_internal::into_ref;
|
use embassy_hal_internal::into_ref;
|
||||||
use embedded_hal_1::delay::DelayNs;
|
|
||||||
|
|
||||||
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
|
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
|
@ -58,7 +57,6 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
adc: impl Peripheral<P = T> + 'd,
|
adc: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
delay: &mut impl DelayNs,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
use crate::pac::adc::vals;
|
use crate::pac::adc::vals;
|
||||||
|
|
||||||
|
@ -71,7 +69,10 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::ENABLED));
|
T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::ENABLED));
|
||||||
|
|
||||||
// Wait for the regulator to stabilize
|
// Wait for the regulator to stabilize
|
||||||
delay.delay_us(10);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(10));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 100_000);
|
||||||
|
|
||||||
assert!(!T::regs().cr().read().aden());
|
assert!(!T::regs().cr().read().aden());
|
||||||
|
|
||||||
|
@ -81,8 +82,12 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
|
|
||||||
while T::regs().cr().read().adcal() {}
|
while T::regs().cr().read().adcal() {}
|
||||||
|
|
||||||
// Wait more than 4 clock cycles after adcal is cleared (RM0364 p. 223)
|
// Wait more than 4 clock cycles after adcal is cleared (RM0364 p. 223).
|
||||||
delay.delay_us(1 + (6 * 1_000_000 / Self::freq().0));
|
let us = (1_000_000 * 4) / Self::freq().0 + 1;
|
||||||
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(us));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / (1000_000 / us));
|
||||||
|
|
||||||
// Enable the adc
|
// Enable the adc
|
||||||
T::regs().cr().modify(|w| w.set_aden(true));
|
T::regs().cr().modify(|w| w.set_aden(true));
|
||||||
|
@ -117,7 +122,7 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_vref(&self, _delay: &mut impl DelayNs) -> Vref {
|
pub fn enable_vref(&self) -> Vref {
|
||||||
T::common_regs().ccr().modify(|w| w.set_vrefen(true));
|
T::common_regs().ccr().modify(|w| w.set_vrefen(true));
|
||||||
|
|
||||||
Vref {}
|
Vref {}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_hal_internal::into_ref;
|
use embassy_hal_internal::into_ref;
|
||||||
use embedded_hal_1::delay::DelayNs;
|
|
||||||
#[cfg(adc_l0)]
|
#[cfg(adc_l0)]
|
||||||
use stm32_metapac::adc::vals::Ckmode;
|
use stm32_metapac::adc::vals::Ckmode;
|
||||||
|
|
||||||
|
@ -65,7 +64,6 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
adc: impl Peripheral<P = T> + 'd,
|
adc: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
delay: &mut impl DelayNs,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(adc);
|
into_ref!(adc);
|
||||||
T::enable_and_reset();
|
T::enable_and_reset();
|
||||||
|
@ -74,7 +72,10 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
//
|
//
|
||||||
// Table 57. ADC characteristics
|
// Table 57. ADC characteristics
|
||||||
// tstab = 14 * 1/fadc
|
// tstab = 14 * 1/fadc
|
||||||
delay.delay_us(1);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(1));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 1000_000);
|
||||||
|
|
||||||
// set default PCKL/2 on L0s because HSI is disabled in the default clock config
|
// set default PCKL/2 on L0s because HSI is disabled in the default clock config
|
||||||
#[cfg(adc_l0)]
|
#[cfg(adc_l0)]
|
||||||
|
@ -114,7 +115,7 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(adc_l0))]
|
#[cfg(not(adc_l0))]
|
||||||
pub fn enable_vbat(&self, _delay: &mut impl DelayNs) -> Vbat {
|
pub fn enable_vbat(&self) -> Vbat {
|
||||||
// SMP must be ≥ 56 ADC clock cycles when using HSI14.
|
// SMP must be ≥ 56 ADC clock cycles when using HSI14.
|
||||||
//
|
//
|
||||||
// 6.3.20 Vbat monitoring characteristics
|
// 6.3.20 Vbat monitoring characteristics
|
||||||
|
@ -123,22 +124,28 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
Vbat
|
Vbat
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_vref(&self, delay: &mut impl DelayNs) -> Vref {
|
pub fn enable_vref(&self) -> Vref {
|
||||||
// Table 28. Embedded internal reference voltage
|
// Table 28. Embedded internal reference voltage
|
||||||
// tstart = 10μs
|
// tstart = 10μs
|
||||||
T::regs().ccr().modify(|reg| reg.set_vrefen(true));
|
T::regs().ccr().modify(|reg| reg.set_vrefen(true));
|
||||||
delay.delay_us(10);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(10));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 100_000);
|
||||||
Vref
|
Vref
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_temperature(&self, delay: &mut impl DelayNs) -> Temperature {
|
pub fn enable_temperature(&self) -> Temperature {
|
||||||
// SMP must be ≥ 56 ADC clock cycles when using HSI14.
|
// SMP must be ≥ 56 ADC clock cycles when using HSI14.
|
||||||
//
|
//
|
||||||
// 6.3.19 Temperature sensor characteristics
|
// 6.3.19 Temperature sensor characteristics
|
||||||
// tstart ≤ 10μs
|
// tstart ≤ 10μs
|
||||||
// ts_temp ≥ 4μs
|
// ts_temp ≥ 4μs
|
||||||
T::regs().ccr().modify(|reg| reg.set_tsen(true));
|
T::regs().ccr().modify(|reg| reg.set_tsen(true));
|
||||||
delay.delay_us(10);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(10));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 100_000);
|
||||||
Temperature
|
Temperature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use embassy_hal_internal::into_ref;
|
use embassy_hal_internal::into_ref;
|
||||||
use embedded_hal_1::delay::DelayNs;
|
|
||||||
|
|
||||||
use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
|
use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
|
||||||
use crate::peripherals::ADC1;
|
use crate::peripherals::ADC1;
|
||||||
|
@ -11,9 +10,6 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
|
||||||
/// VREF voltage used for factory calibration of VREFINTCAL register.
|
/// VREF voltage used for factory calibration of VREFINTCAL register.
|
||||||
pub const VREF_CALIB_MV: u32 = 3300;
|
pub const VREF_CALIB_MV: u32 = 3300;
|
||||||
|
|
||||||
/// ADC turn-on time
|
|
||||||
pub const ADC_POWERUP_TIME_US: u32 = 3;
|
|
||||||
|
|
||||||
pub struct VrefInt;
|
pub struct VrefInt;
|
||||||
impl AdcPin<ADC1> for VrefInt {}
|
impl AdcPin<ADC1> for VrefInt {}
|
||||||
impl super::SealedAdcPin<ADC1> for VrefInt {
|
impl super::SealedAdcPin<ADC1> for VrefInt {
|
||||||
|
@ -97,7 +93,7 @@ impl<'d, T> Adc<'d, T>
|
||||||
where
|
where
|
||||||
T: Instance,
|
T: Instance,
|
||||||
{
|
{
|
||||||
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayNs) -> Self {
|
pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
|
||||||
into_ref!(adc);
|
into_ref!(adc);
|
||||||
T::enable_and_reset();
|
T::enable_and_reset();
|
||||||
|
|
||||||
|
@ -107,7 +103,10 @@ where
|
||||||
reg.set_adon(true);
|
reg.set_adon(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
delay.delay_us(ADC_POWERUP_TIME_US);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(5));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 200_000);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
adc,
|
adc,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use embassy_hal_internal::into_ref;
|
use embassy_hal_internal::into_ref;
|
||||||
use embedded_hal_1::delay::DelayNs;
|
|
||||||
|
|
||||||
use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
|
use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
@ -74,7 +73,7 @@ cfg_if! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Adc<'d, T> {
|
impl<'d, T: Instance> Adc<'d, T> {
|
||||||
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayNs) -> Self {
|
pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
|
||||||
into_ref!(adc);
|
into_ref!(adc);
|
||||||
T::enable_and_reset();
|
T::enable_and_reset();
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
|
@ -88,7 +87,10 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
reg.set_chselrmod(false);
|
reg.set_chselrmod(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
delay.delay_us(20);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(20));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 50_000);
|
||||||
|
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
reg.set_adcal(true);
|
reg.set_adcal(true);
|
||||||
|
@ -98,7 +100,10 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
// spin
|
// spin
|
||||||
}
|
}
|
||||||
|
|
||||||
delay.delay_us(1);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(1));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 1000_000);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
adc,
|
adc,
|
||||||
|
@ -106,7 +111,7 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_vrefint(&self, delay: &mut impl DelayNs) -> VrefInt {
|
pub fn enable_vrefint(&self) -> VrefInt {
|
||||||
#[cfg(not(adc_g0))]
|
#[cfg(not(adc_g0))]
|
||||||
T::common_regs().ccr().modify(|reg| {
|
T::common_regs().ccr().modify(|reg| {
|
||||||
reg.set_vrefen(true);
|
reg.set_vrefen(true);
|
||||||
|
@ -117,10 +122,11 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
});
|
});
|
||||||
|
|
||||||
// "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
|
// "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
|
||||||
// to stabilize the internal voltage reference, we wait a little more.
|
// to stabilize the internal voltage reference.
|
||||||
// TODO: delay 15us
|
#[cfg(time)]
|
||||||
//cortex_m::asm::delay(20_000_000);
|
embassy_time::block_for(embassy_time::Duration::from_micros(20));
|
||||||
delay.delay_us(15);
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 50_000);
|
||||||
|
|
||||||
VrefInt {}
|
VrefInt {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use embedded_hal_1::delay::DelayNs;
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel};
|
use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel};
|
||||||
use pac::adccommon::vals::Presc;
|
use pac::adccommon::vals::Presc;
|
||||||
|
@ -129,7 +128,7 @@ impl Prescaler {
|
||||||
|
|
||||||
impl<'d, T: Instance> Adc<'d, T> {
|
impl<'d, T: Instance> Adc<'d, T> {
|
||||||
/// Create a new ADC driver.
|
/// Create a new ADC driver.
|
||||||
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayNs) -> Self {
|
pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
|
||||||
embassy_hal_internal::into_ref!(adc);
|
embassy_hal_internal::into_ref!(adc);
|
||||||
T::enable_and_reset();
|
T::enable_and_reset();
|
||||||
|
|
||||||
|
@ -161,11 +160,14 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
adc,
|
adc,
|
||||||
sample_time: SampleTime::from_bits(0),
|
sample_time: SampleTime::from_bits(0),
|
||||||
};
|
};
|
||||||
s.power_up(delay);
|
s.power_up();
|
||||||
s.configure_differential_inputs();
|
s.configure_differential_inputs();
|
||||||
|
|
||||||
s.calibrate();
|
s.calibrate();
|
||||||
delay.delay_us(1);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(1));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 1000_000);
|
||||||
|
|
||||||
s.enable();
|
s.enable();
|
||||||
s.configure();
|
s.configure();
|
||||||
|
@ -173,13 +175,16 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
fn power_up(&mut self, delay: &mut impl DelayNs) {
|
fn power_up(&mut self) {
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
reg.set_deeppwd(false);
|
reg.set_deeppwd(false);
|
||||||
reg.set_advregen(true);
|
reg.set_advregen(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
delay.delay_us(10);
|
#[cfg(time)]
|
||||||
|
embassy_time::block_for(embassy_time::Duration::from_micros(10));
|
||||||
|
#[cfg(not(time))]
|
||||||
|
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 100_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_differential_inputs(&mut self) {
|
fn configure_differential_inputs(&mut self) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue