diff options
Diffstat (limited to 'embassy-stm32/src/adc/adc4.rs')
| -rw-r--r-- | embassy-stm32/src/adc/adc4.rs | 207 |
1 files changed, 92 insertions, 115 deletions
diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs index 453513309..43509873f 100644 --- a/embassy-stm32/src/adc/adc4.rs +++ b/embassy-stm32/src/adc/adc4.rs | |||
| @@ -5,7 +5,7 @@ use pac::adc::vals::{Adc4Dmacfg as Dmacfg, Adc4Exten as Exten, Adc4OversamplingR | |||
| 5 | use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel}; | 5 | use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel}; |
| 6 | 6 | ||
| 7 | use super::blocking_delay_us; | 7 | use super::blocking_delay_us; |
| 8 | use crate::adc::ConversionMode; | 8 | use crate::adc::{AdcRegs, ConversionMode, Instance}; |
| 9 | #[cfg(stm32u5)] | 9 | #[cfg(stm32u5)] |
| 10 | pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr; | 10 | pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr; |
| 11 | #[cfg(stm32wba)] | 11 | #[cfg(stm32wba)] |
| @@ -90,135 +90,112 @@ fn from_ker_ck(frequency: Hertz) -> Presc { | |||
| 90 | } | 90 | } |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | pub trait SealedInstance { | 93 | impl AdcRegs for crate::pac::adc::Adc4 { |
| 94 | #[allow(unused)] | 94 | fn data(&self) -> *mut u16 { |
| 95 | fn regs() -> crate::pac::adc::Adc4; | 95 | crate::pac::adc::Adc4::dr(*self).as_ptr() as *mut u16 |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { | 98 | fn enable(&self) { |
| 99 | type Interrupt: crate::interrupt::typelevel::Interrupt; | 99 | if !self.cr().read().aden() || !self.isr().read().adrdy() { |
| 100 | } | 100 | self.isr().write(|w| w.set_adrdy(true)); |
| 101 | self.cr().modify(|w| w.set_aden(true)); | ||
| 102 | while !self.isr().read().adrdy() {} | ||
| 103 | } | ||
| 104 | } | ||
| 101 | 105 | ||
| 102 | foreach_adc!( | 106 | fn start(&self) { |
| 103 | (ADC4, $common_inst:ident, $clock:ident) => { | 107 | // Start conversion |
| 104 | use crate::peripherals::ADC4; | 108 | self.cr().modify(|reg| { |
| 109 | reg.set_adstart(true); | ||
| 110 | }); | ||
| 111 | } | ||
| 105 | 112 | ||
| 106 | impl super::BasicAnyInstance for ADC4 { | 113 | fn stop(&self) { |
| 107 | type SampleTime = SampleTime; | 114 | let cr = self.cr().read(); |
| 115 | if cr.adstart() { | ||
| 116 | self.cr().modify(|w| w.set_adstp(true)); | ||
| 117 | while self.cr().read().adstart() {} | ||
| 108 | } | 118 | } |
| 109 | 119 | ||
| 110 | impl super::SealedAnyInstance for ADC4 { | 120 | if cr.aden() || cr.adstart() { |
| 111 | fn dr() -> *mut u16 { | 121 | self.cr().modify(|w| w.set_addis(true)); |
| 112 | ADC4::regs().dr().as_ptr() as *mut u16 | 122 | while self.cr().read().aden() {} |
| 113 | } | 123 | } |
| 114 | 124 | ||
| 115 | fn enable() { | 125 | // Reset configuration. |
| 116 | if !ADC4::regs().cr().read().aden() || !ADC4::regs().isr().read().adrdy() { | 126 | self.cfgr1().modify(|reg| { |
| 117 | ADC4::regs().isr().write(|w| w.set_adrdy(true)); | 127 | reg.set_dmaen(false); |
| 118 | ADC4::regs().cr().modify(|w| w.set_aden(true)); | 128 | }); |
| 119 | while !ADC4::regs().isr().read().adrdy() {} | 129 | } |
| 120 | } | ||
| 121 | } | ||
| 122 | 130 | ||
| 123 | fn start() { | 131 | fn configure_dma(&self, conversion_mode: ConversionMode) { |
| 124 | // Start conversion | 132 | match conversion_mode { |
| 125 | ADC4::regs().cr().modify(|reg| { | 133 | ConversionMode::Singular => { |
| 126 | reg.set_adstart(true); | 134 | self.isr().modify(|reg| { |
| 135 | reg.set_ovr(true); | ||
| 136 | reg.set_eos(true); | ||
| 137 | reg.set_eoc(true); | ||
| 127 | }); | 138 | }); |
| 128 | } | ||
| 129 | 139 | ||
| 130 | fn stop() { | 140 | self.cfgr1().modify(|reg| { |
| 131 | let cr = ADC4::regs().cr().read(); | 141 | reg.set_dmaen(true); |
| 132 | if cr.adstart() { | 142 | reg.set_dmacfg(Dmacfg::ONE_SHOT); |
| 133 | ADC4::regs().cr().modify(|w| w.set_adstp(true)); | 143 | #[cfg(stm32u5)] |
| 134 | while ADC4::regs().cr().read().adstart() {} | 144 | reg.set_chselrmod(false); |
| 135 | } | 145 | #[cfg(stm32wba)] |
| 136 | 146 | reg.set_chselrmod(Chselrmod::ENABLE_INPUT) | |
| 137 | if cr.aden() || cr.adstart() { | ||
| 138 | ADC4::regs().cr().modify(|w| w.set_addis(true)); | ||
| 139 | while ADC4::regs().cr().read().aden() {} | ||
| 140 | } | ||
| 141 | |||
| 142 | // Reset configuration. | ||
| 143 | ADC4::regs().cfgr1().modify(|reg| { | ||
| 144 | reg.set_dmaen(false); | ||
| 145 | }); | 147 | }); |
| 146 | } | 148 | } |
| 149 | #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))] | ||
| 150 | _ => unreachable!(), | ||
| 151 | } | ||
| 152 | } | ||
| 147 | 153 | ||
| 148 | fn configure_dma(conversion_mode: ConversionMode) { | 154 | fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { |
| 149 | match conversion_mode { | 155 | let mut prev_channel: i16 = -1; |
| 150 | ConversionMode::Singular => { | 156 | #[cfg(stm32wba)] |
| 151 | ADC4::regs().isr().modify(|reg| { | 157 | self.chselr().write_value(Chselr(0_u32)); |
| 152 | reg.set_ovr(true); | 158 | #[cfg(stm32u5)] |
| 153 | reg.set_eos(true); | 159 | self.chselrmod0().write_value(Chselr(0_u32)); |
| 154 | reg.set_eoc(true); | 160 | for (_i, ((channel, _), sample_time)) in sequence.enumerate() { |
| 155 | }); | 161 | self.smpr().modify(|w| { |
| 156 | 162 | w.set_smp(_i, sample_time); | |
| 157 | ADC4::regs().cfgr1().modify(|reg| { | 163 | }); |
| 158 | reg.set_dmaen(true); | 164 | |
| 159 | reg.set_dmacfg(Dmacfg::ONE_SHOT); | 165 | let channel_num = channel; |
| 160 | #[cfg(stm32u5)] | 166 | if channel_num as i16 <= prev_channel { |
| 161 | reg.set_chselrmod(false); | 167 | return; |
| 162 | #[cfg(stm32wba)] | 168 | }; |
| 163 | reg.set_chselrmod(Chselrmod::ENABLE_INPUT) | 169 | prev_channel = channel_num as i16; |
| 164 | }); | ||
| 165 | } | ||
| 166 | #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))] | ||
| 167 | _ => unreachable!(), | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { | ||
| 172 | let mut prev_channel: i16 = -1; | ||
| 173 | #[cfg(stm32wba)] | ||
| 174 | ADC4::regs().chselr().write_value(Chselr(0_u32)); | ||
| 175 | #[cfg(stm32u5)] | ||
| 176 | ADC4::regs().chselrmod0().write_value(Chselr(0_u32)); | ||
| 177 | for (_i, ((channel, _), sample_time)) in sequence.enumerate() { | ||
| 178 | ADC4::regs().smpr().modify(|w| { | ||
| 179 | w.set_smp(_i, sample_time); | ||
| 180 | }); | ||
| 181 | |||
| 182 | let channel_num = channel; | ||
| 183 | if channel_num as i16 <= prev_channel { | ||
| 184 | return; | ||
| 185 | }; | ||
| 186 | prev_channel = channel_num as i16; | ||
| 187 | |||
| 188 | #[cfg(stm32wba)] | ||
| 189 | ADC4::regs().chselr().modify(|w| { | ||
| 190 | w.set_chsel0(channel as usize, true); | ||
| 191 | }); | ||
| 192 | #[cfg(stm32u5)] | ||
| 193 | ADC4::regs().chselrmod0().modify(|w| { | ||
| 194 | w.set_chsel(channel as usize, true); | ||
| 195 | }); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | 170 | ||
| 199 | fn convert() -> u16 { | 171 | #[cfg(stm32wba)] |
| 200 | // Reset interrupts | 172 | self.chselr().modify(|w| { |
| 201 | ADC4::regs().isr().modify(|reg| { | 173 | w.set_chsel0(channel as usize, true); |
| 202 | reg.set_eos(true); | 174 | }); |
| 203 | reg.set_eoc(true); | 175 | #[cfg(stm32u5)] |
| 204 | }); | 176 | self.chselrmod0().modify(|w| { |
| 177 | w.set_chsel(channel as usize, true); | ||
| 178 | }); | ||
| 179 | } | ||
| 180 | } | ||
| 205 | 181 | ||
| 206 | // Start conversion | 182 | fn convert(&self) { |
| 207 | ADC4::regs().cr().modify(|reg| { | 183 | // Reset interrupts |
| 208 | reg.set_adstart(true); | 184 | self.isr().modify(|reg| { |
| 209 | }); | 185 | reg.set_eos(true); |
| 186 | reg.set_eoc(true); | ||
| 187 | }); | ||
| 210 | 188 | ||
| 211 | while !ADC4::regs().isr().read().eos() { | 189 | // Start conversion |
| 212 | // spin | 190 | self.cr().modify(|reg| { |
| 213 | } | 191 | reg.set_adstart(true); |
| 192 | }); | ||
| 214 | 193 | ||
| 215 | ADC4::regs().dr().read().0 as u16 | 194 | while !self.isr().read().eos() { |
| 216 | } | 195 | // spin |
| 217 | } | 196 | } |
| 218 | 197 | } | |
| 219 | impl super::AnyInstance for ADC4 {} | 198 | } |
| 220 | }; | ||
| 221 | ); | ||
| 222 | 199 | ||
| 223 | pub struct Adc4<'d, T: Instance> { | 200 | pub struct Adc4<'d, T: Instance> { |
| 224 | #[allow(unused)] | 201 | #[allow(unused)] |
| @@ -231,7 +208,7 @@ pub enum Adc4Error { | |||
| 231 | DMAError, | 208 | DMAError, |
| 232 | } | 209 | } |
| 233 | 210 | ||
| 234 | impl<'d, T: Instance + super::AnyInstance> super::Adc<'d, T> { | 211 | impl<'d, T: Instance<Regs = crate::pac::adc::Adc4>> super::Adc<'d, T> { |
| 235 | /// Create a new ADC driver. | 212 | /// Create a new ADC driver. |
| 236 | pub fn new_adc4(adc: Peri<'d, T>) -> Self { | 213 | pub fn new_adc4(adc: Peri<'d, T>) -> Self { |
| 237 | rcc::enable_and_reset::<T>(); | 214 | rcc::enable_and_reset::<T>(); |
| @@ -267,7 +244,7 @@ impl<'d, T: Instance + super::AnyInstance> super::Adc<'d, T> { | |||
| 267 | 244 | ||
| 268 | blocking_delay_us(1); | 245 | blocking_delay_us(1); |
| 269 | 246 | ||
| 270 | T::enable(); | 247 | T::regs().enable(); |
| 271 | 248 | ||
| 272 | // single conversion mode, software trigger | 249 | // single conversion mode, software trigger |
| 273 | T::regs().cfgr1().modify(|w| { | 250 | T::regs().cfgr1().modify(|w| { |
