From 1480305c16caa8d2e956774730366e7aec1eb6ab Mon Sep 17 00:00:00 2001 From: linuswck Date: Fri, 15 Mar 2024 14:45:19 +0800 Subject: [PATCH] max1968: Fix ADC+DMA does not start converting bug --- src/thermostat/max1968.rs | 91 +++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/src/thermostat/max1968.rs b/src/thermostat/max1968.rs index 18d2890..9cf02ef 100644 --- a/src/thermostat/max1968.rs +++ b/src/thermostat/max1968.rs @@ -1,15 +1,14 @@ use crate::thermostat::ad5680; use fugit::KilohertzU32; -use stm32_eth::stm32::{ADC2, DMA2}; - use stm32f4xx_hal::{ adc::{config::{self, AdcConfig}, Adc}, dma::{config::DmaConfig, PeripheralToMemory, Stream2, StreamsTuple, Transfer as DMA_Transfer}, gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Analog, Output, PushPull}, hal::{self, blocking::spi::Transfer, digital::v2::OutputPin}, - pac::{ADC1, SPI1, TIM4}, + pac::{ADC1, ADC2, DMA2, SPI1, TIM4, Peripherals, NVIC}, spi::{NoMiso, Spi, TransferModeNormal}, - timer::pwm::PwmChannel + timer::pwm::PwmChannel, + interrupt }; use uom::si::{ @@ -75,10 +74,14 @@ pub struct MAX1968PinSet { type DacSpi = Spi>, NoMiso, PB5>), TransferModeNormal>; type DacSync = PB4>; +static mut DMA_TRANSFER_COMPLETE: bool = true; + pub struct MAX1968 { pub phy: MAX1968Phy, pub pins_adc: Adc, pub dma_adc: DMA_Transfer, 1, Adc, PeripheralToMemory, &'static mut [u16; 16]>, + prev_vtec_volt: ElectricPotential, + prev_itec_volt: ElectricPotential, } pub enum PwmPinsEnum { @@ -155,50 +158,57 @@ impl MAX1968 { let dma_adc : DMA_Transfer, 1, Adc, PeripheralToMemory, &'static mut [u16; 16]>; unsafe { dma_adc = DMA_Transfer::init_peripheral_to_memory(dma.2, pins_adc2, &mut ADC2_FIRST_BUFFER, None, dma_config); + NVIC::unmask(interrupt::DMA2_STREAM2); } MAX1968 { phy: phy_ch0, pins_adc: pins_adc1, dma_adc: dma_adc, + prev_vtec_volt: ElectricPotential::new::(0.0), + prev_itec_volt: ElectricPotential::new::(0.0), } } pub fn dma_adc_start_conversion(&mut self){ - self.dma_adc.clear_interrupts(); - self.dma_adc.start(|adc| { - adc.clear_end_of_conversion_flag(); - adc.start_conversion(); - }); + if unsafe {DMA_TRANSFER_COMPLETE} { + unsafe { DMA_TRANSFER_COMPLETE = false; } + self.dma_adc.start(|adc| { + adc.clear_end_of_conversion_flag(); + adc.start_conversion(); + }); + } } pub fn get_tec_readings(&mut self) -> (ElectricPotential, ElectricPotential) { - self.dma_adc.clear_interrupts(); - let buffer: &[u16; 16]; - unsafe{ - (buffer, _) = self.dma_adc - .next_transfer(&mut ADC2_LOCAL_BUFFER) - .unwrap(); - } - - let sample_to_millivolts = self.dma_adc.peripheral().make_sample_to_millivolts(); - let mut itec: u16 = 0; - for data in buffer.into_iter().step_by(2){ - itec += *data; - } - itec = itec >> 3; + if unsafe { DMA_TRANSFER_COMPLETE } { + let buffer: &[u16; 16]; + unsafe { + (buffer, _) = self.dma_adc + .next_transfer(&mut ADC2_LOCAL_BUFFER) + .unwrap(); + } + + let sample_to_millivolts = self.dma_adc.peripheral().make_sample_to_millivolts(); + let mut itec: u16 = 0; + for data in buffer.into_iter().step_by(2) { + itec += *data; + } + itec = itec >> 3; - let mut vtec: u16 = 0; - for data in buffer.into_iter().skip(1).step_by(2){ - vtec += *data; - } - vtec = vtec >> 3; + let mut vtec: u16 = 0; + for data in buffer.into_iter().skip(1).step_by(2) { + vtec += *data; + } + vtec = vtec >> 3; - unsafe { - ADC2_LOCAL_BUFFER = *buffer; + unsafe { + ADC2_LOCAL_BUFFER = *buffer; + } + self.prev_vtec_volt = ElectricPotential::new::(sample_to_millivolts(vtec) as f32); + self.prev_itec_volt = ElectricPotential::new::(sample_to_millivolts(itec) as f32); } - - (ElectricPotential::new::(sample_to_millivolts(vtec) as f32), ElectricPotential::new::(sample_to_millivolts(itec) as f32)) + (self.prev_vtec_volt, self.prev_itec_volt) } // Return the calibrated VDDA Voltage @@ -292,3 +302,20 @@ impl MAX1968 { } } + +#[interrupt] +fn DMA2_STREAM2(){ + cortex_m::interrupt::free(|_| { + unsafe { + // Clear all DMA2_STREAM2 interrupt flags + Peripherals::steal().DMA2.lifcr.write(|w| w + .ctcif2().set_bit() + .cdmeif2().set_bit() + .chtif2().set_bit() + .cteif2().set_bit() + ); + DMA_TRANSFER_COMPLETE = true; + } + } + ) +}