This commit is contained in:
klownfish 2024-12-27 02:54:38 +01:00
parent 0836392219
commit a5a90156ce
3 changed files with 49 additions and 46 deletions

View File

@ -221,16 +221,16 @@ impl<'d, T: Instance> Adc4<'d, T> {
} }
fn power_up(&mut self) { fn power_up(&mut self) {
T::regs().isr().modify(|reg| { T::regs().isr().modify(|w| {
reg.set_ldordy(true); w.set_ldordy(true);
}); });
T::regs().cr().modify(|reg| { T::regs().cr().modify(|w| {
reg.set_advregen(true); w.set_advregen(true);
}); });
while !T::regs().isr().read().ldordy() { }; while !T::regs().isr().read().ldordy() { };
T::regs().isr().modify(|reg| { T::regs().isr().modify(|w| {
reg.set_ldordy(true); w.set_ldordy(true);
}); });
} }
@ -253,6 +253,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
w.set_cont(false); w.set_cont(false);
w.set_discen(false); w.set_discen(false);
w.set_exten(Adc4Exten::DISABLED); w.set_exten(Adc4Exten::DISABLED);
w.set_chselrmod(false);
}); });
// only use one channel at the moment // only use one channel at the moment
@ -265,8 +266,8 @@ impl<'d, T: Instance> Adc4<'d, T> {
/// Enable reading the voltage reference internal channel. /// Enable reading the voltage reference internal channel.
pub fn enable_vrefint(&self) -> VrefInt { pub fn enable_vrefint(&self) -> VrefInt {
T::regs().ccr().modify(|reg| { T::regs().ccr().modify(|w| {
reg.set_vrefen(true); w.set_vrefen(true);
}); });
VrefInt {} VrefInt {}
@ -274,8 +275,8 @@ impl<'d, T: Instance> Adc4<'d, T> {
/// Enable reading the temperature internal channel. /// Enable reading the temperature internal channel.
pub fn enable_temperature(&self) -> Temperature { pub fn enable_temperature(&self) -> Temperature {
T::regs().ccr().modify(|reg| { T::regs().ccr().modify(|w| {
reg.set_vsensesel(true); w.set_vsensesel(true);
}); });
Temperature {} Temperature {}
@ -283,8 +284,8 @@ impl<'d, T: Instance> Adc4<'d, T> {
/// Enable reading the vbat internal channel. /// Enable reading the vbat internal channel.
pub fn enable_vbat(&self) -> Vbat { pub fn enable_vbat(&self) -> Vbat {
T::regs().ccr().modify(|reg| { T::regs().ccr().modify(|w| {
reg.set_vbaten(true); w.set_vbaten(true);
}); });
Vbat {} Vbat {}
@ -320,7 +321,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
/// Set the ADC resolution. /// Set the ADC resolution.
pub fn set_resolution(&mut self, resolution: Resolution) { pub fn set_resolution(&mut self, resolution: Resolution) {
T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); T::regs().cfgr1().modify(|w| w.set_res(resolution.into()));
} }
/// Set hardware averaging. /// Set hardware averaging.
@ -337,25 +338,24 @@ impl<'d, T: Instance> Adc4<'d, T> {
Averaging::Samples256 => (true, Adc4OversamplingRatio::OVERSAMPLE256X, 8), Averaging::Samples256 => (true, Adc4OversamplingRatio::OVERSAMPLE256X, 8),
}; };
T::regs().cfgr2().modify(|reg| { T::regs().cfgr2().modify(|w| {
reg.set_ovsr(samples); w.set_ovsr(samples);
reg.set_ovss(right_shift); w.set_ovss(right_shift);
reg.set_ovse(enable) w.set_ovse(enable)
}) })
} }
/// Read an ADC channel. /// Read an ADC channel.
pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16{ pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16{
channel.setup(); channel.setup();
T::regs().cfgr1().modify(|reg| {
reg.set_chselrmod(false);
});
// Select channel
T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32)); T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32));
T::regs().chselrmod0().modify(|w| { T::regs().chselrmod0().modify(|w| {
w.set_chsel(channel.channel() as usize, true); w.set_chsel(channel.channel() as usize, true);
}); });
// Reset interrupts
T::regs().isr().modify(|reg| { T::regs().isr().modify(|reg| {
reg.set_eos(true); reg.set_eos(true);
reg.set_eoc(true); reg.set_eoc(true);
@ -373,8 +373,33 @@ impl<'d, T: Instance> Adc4<'d, T> {
T::regs().dr().read().0 as u16 T::regs().dr().read().0 as u16
} }
/// Channels can not be repeated and must be in ascending order! /// Read one or multiple ADC channels using DMA.
/// TODO: broken ///
/// `sequence` iterator and `readings` must have the same length.
/// The channels in `sequence` must be in ascending order.
///
/// Example
/// ```rust,ignore
/// use embassy_stm32::adc::adc4;
/// use embassy_stm32::adc::AdcChannel;
///
/// let mut adc4 = adc4::Adc4::new(p.ADC4);
/// let mut adc4_pin1 = p.PC1;
/// let mut adc4_pin2 = p.PC0;
/// let mut degraded41 = adc4_pin1.degrade_adc();
/// let mut degraded42 = adc4_pin2.degrade_adc();
/// let mut measurements = [0u16; 2];
/// // not that the channels must be in ascending order
/// adc4.read(
/// &mut p.GPDMA1_CH1,
/// [
/// &mut degraded42,
/// &mut degraded41,
/// ]
/// .into_iter(),
/// &mut measurements,
/// ).await.unwrap();
/// ```
pub async fn read( pub async fn read(
&mut self, &mut self,
rx_dma: &mut impl RxDma4<T>, rx_dma: &mut impl RxDma4<T>,
@ -402,7 +427,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
reg.set_chselrmod(false); reg.set_chselrmod(false);
}); });
// Verify and activate sequence
let mut prev_channel: i16 = -1; let mut prev_channel: i16 = -1;
T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32)); T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32));
for channel in sequence { for channel in sequence {
@ -433,11 +458,8 @@ impl<'d, T: Instance> Adc4<'d, T> {
reg.set_adstart(true); reg.set_adstart(true);
}); });
// Wait for conversion sequence to finish.
transfer.await; transfer.await;
blocking_delay_us(10);
// Ensure conversions are finished. // Ensure conversions are finished.
Self::cancel_conversions(); Self::cancel_conversions();

View File

@ -238,7 +238,7 @@ pub struct Config {
#[cfg(any(stm32l4, stm32l5, stm32u5))] #[cfg(any(stm32l4, stm32l5, stm32u5))]
pub enable_independent_io_supply: bool, pub enable_independent_io_supply: bool,
/// On the U5 series all analog peripherals are powere by a separate supply. /// On the U5 series all analog peripherals are powered by a separate supply.
#[cfg(stm32u5)] #[cfg(stm32u5)]
pub enable_independent_analog_supply: bool, pub enable_independent_analog_supply: bool,

View File

@ -14,25 +14,6 @@ use panic_probe as _;
#[embassy_executor::main] #[embassy_executor::main]
async fn main(spawner: embassy_executor::Spawner) { async fn main(spawner: embassy_executor::Spawner) {
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = true;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI, // 16 MHz
prediv: PllPreDiv::DIV1, // 16 MHz
mul: PllMul::MUL10, // 160 MHz
divp: Some(PllDiv::DIV1), // don't care
divq: Some(PllDiv::DIV1), // don't care
divr: Some(PllDiv::DIV1), // 160 MHz
});
config.rcc.sys = Sysclk::PLL1_R;
config.rcc.voltage_range = VoltageScale::RANGE1;
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
config.rcc.mux.iclksel = mux::Iclksel::HSI48; // USB uses ICLK
}
let mut p = embassy_stm32::init(config); let mut p = embassy_stm32::init(config);