diff options
Diffstat (limited to 'embassy-stm32/src/adc/c0.rs')
| -rw-r--r-- | embassy-stm32/src/adc/c0.rs | 64 |
1 files changed, 31 insertions, 33 deletions
diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs index 3e109e429..2f0f326af 100644 --- a/embassy-stm32/src/adc/c0.rs +++ b/embassy-stm32/src/adc/c0.rs | |||
| @@ -4,7 +4,7 @@ use pac::adccommon::vals::Presc; | |||
| 4 | use stm32_metapac::adc::vals::{SampleTime, Scandir}; | 4 | use stm32_metapac::adc::vals::{SampleTime, Scandir}; |
| 5 | 5 | ||
| 6 | use super::{Adc, Instance, Resolution, blocking_delay_us}; | 6 | use super::{Adc, Instance, Resolution, blocking_delay_us}; |
| 7 | use crate::adc::{AnyInstance, ConversionMode}; | 7 | use crate::adc::{AdcRegs, ConversionMode}; |
| 8 | use crate::time::Hertz; | 8 | use crate::time::Hertz; |
| 9 | use crate::{Peri, pac, rcc}; | 9 | use crate::{Peri, pac, rcc}; |
| 10 | 10 | ||
| @@ -43,52 +43,52 @@ fn from_ker_ck(frequency: Hertz) -> Presc { | |||
| 43 | } | 43 | } |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | impl<T: Instance> super::SealedAnyInstance for T { | 46 | impl AdcRegs for crate::pac::adc::Adc { |
| 47 | fn dr() -> *mut u16 { | 47 | fn data(&self) -> *mut u16 { |
| 48 | T::regs().dr().as_ptr() as *mut u16 | 48 | crate::pac::adc::Adc::dr(*self).as_ptr() as *mut u16 |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | fn enable() { | 51 | fn enable(&self) { |
| 52 | T::regs().isr().modify(|w| w.set_adrdy(true)); | 52 | self.isr().modify(|w| w.set_adrdy(true)); |
| 53 | T::regs().cr().modify(|w| w.set_aden(true)); | 53 | self.cr().modify(|w| w.set_aden(true)); |
| 54 | // ADRDY is "ADC ready". Wait until it will be True. | 54 | // ADRDY is "ADC ready". Wait until it will be True. |
| 55 | while !T::regs().isr().read().adrdy() {} | 55 | while !self.isr().read().adrdy() {} |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | fn start() { | 58 | fn start(&self) { |
| 59 | // Start conversion | 59 | // Start conversion |
| 60 | T::regs().cr().modify(|reg| { | 60 | self.cr().modify(|reg| { |
| 61 | reg.set_adstart(true); | 61 | reg.set_adstart(true); |
| 62 | }); | 62 | }); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | fn stop() { | 65 | fn stop(&self) { |
| 66 | if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { | 66 | if self.cr().read().adstart() && !self.cr().read().addis() { |
| 67 | T::regs().cr().modify(|reg| { | 67 | self.cr().modify(|reg| { |
| 68 | reg.set_adstp(Adstp::STOP); | 68 | reg.set_adstp(Adstp::STOP); |
| 69 | }); | 69 | }); |
| 70 | while T::regs().cr().read().adstart() {} | 70 | while self.cr().read().adstart() {} |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | // Reset configuration. | 73 | // Reset configuration. |
| 74 | T::regs().cfgr1().modify(|reg| { | 74 | self.cfgr1().modify(|reg| { |
| 75 | reg.set_cont(false); | 75 | reg.set_cont(false); |
| 76 | reg.set_dmacfg(Dmacfg::from_bits(0)); | 76 | reg.set_dmacfg(Dmacfg::from_bits(0)); |
| 77 | reg.set_dmaen(false); | 77 | reg.set_dmaen(false); |
| 78 | }); | 78 | }); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | fn configure_dma(conversion_mode: super::ConversionMode) { | 81 | fn configure_dma(&self, conversion_mode: super::ConversionMode) { |
| 82 | match conversion_mode { | 82 | match conversion_mode { |
| 83 | ConversionMode::Singular => { | 83 | ConversionMode::Singular => { |
| 84 | // Enable overrun control, so no new DMA requests will be generated until | 84 | // Enable overrun control, so no new DMA requests will be generated until |
| 85 | // previous DR values is read. | 85 | // previous DR values is read. |
| 86 | T::regs().isr().modify(|reg| { | 86 | self.isr().modify(|reg| { |
| 87 | reg.set_ovr(true); | 87 | reg.set_ovr(true); |
| 88 | }); | 88 | }); |
| 89 | 89 | ||
| 90 | // Set continuous mode with oneshot dma. | 90 | // Set continuous mode with oneshot dma. |
| 91 | T::regs().cfgr1().modify(|reg| { | 91 | self.cfgr1().modify(|reg| { |
| 92 | reg.set_discen(false); | 92 | reg.set_discen(false); |
| 93 | reg.set_cont(true); | 93 | reg.set_cont(true); |
| 94 | reg.set_dmacfg(Dmacfg::DMA_ONE_SHOT); | 94 | reg.set_dmacfg(Dmacfg::DMA_ONE_SHOT); |
| @@ -99,7 +99,7 @@ impl<T: Instance> super::SealedAnyInstance for T { | |||
| 99 | } | 99 | } |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>) { | 102 | fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>) { |
| 103 | let mut needs_hw = sequence.len() == 1 || sequence.len() > CHSELR_SQ_SIZE; | 103 | let mut needs_hw = sequence.len() == 1 || sequence.len() > CHSELR_SQ_SIZE; |
| 104 | let mut is_ordered_up = true; | 104 | let mut is_ordered_up = true; |
| 105 | let mut is_ordered_down = true; | 105 | let mut is_ordered_down = true; |
| @@ -109,7 +109,7 @@ impl<T: Instance> super::SealedAnyInstance for T { | |||
| 109 | let mut last_channel: u8 = 0; | 109 | let mut last_channel: u8 = 0; |
| 110 | let mut sample_time: Self::SampleTime = SampleTime::CYCLES2_5; | 110 | let mut sample_time: Self::SampleTime = SampleTime::CYCLES2_5; |
| 111 | 111 | ||
| 112 | T::regs().chselr_sq().write(|w| { | 112 | self.chselr_sq().write(|w| { |
| 113 | for (i, ((channel, _), _sample_time)) in sequence.enumerate() { | 113 | for (i, ((channel, _), _sample_time)) in sequence.enumerate() { |
| 114 | assert!( | 114 | assert!( |
| 115 | sample_time == _sample_time || i == 0, | 115 | sample_time == _sample_time || i == 0, |
| @@ -146,42 +146,40 @@ impl<T: Instance> super::SealedAnyInstance for T { | |||
| 146 | ); | 146 | ); |
| 147 | 147 | ||
| 148 | // Set required channels for multi-convert. | 148 | // Set required channels for multi-convert. |
| 149 | unsafe { (T::regs().chselr().as_ptr() as *mut u32).write_volatile(hw_channel_selection) } | 149 | unsafe { (self.chselr().as_ptr() as *mut u32).write_volatile(hw_channel_selection) } |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | T::regs().smpr().modify(|w| { | 152 | self.smpr().modify(|w| { |
| 153 | w.smpsel(0); | 153 | w.smpsel(0); |
| 154 | w.set_smp1(sample_time); | 154 | w.set_smp1(sample_time); |
| 155 | }); | 155 | }); |
| 156 | 156 | ||
| 157 | T::regs().cfgr1().modify(|reg| { | 157 | self.cfgr1().modify(|reg| { |
| 158 | reg.set_chselrmod(!needs_hw); | 158 | reg.set_chselrmod(!needs_hw); |
| 159 | reg.set_align(Align::RIGHT); | 159 | reg.set_align(Align::RIGHT); |
| 160 | reg.set_scandir(if is_ordered_up { Scandir::UP } else { Scandir::BACK }); | 160 | reg.set_scandir(if is_ordered_up { Scandir::UP } else { Scandir::BACK }); |
| 161 | }); | 161 | }); |
| 162 | 162 | ||
| 163 | // Trigger and wait for the channel selection procedure to complete. | 163 | // Trigger and wait for the channel selection procedure to complete. |
| 164 | T::regs().isr().modify(|w| w.set_ccrdy(false)); | 164 | self.isr().modify(|w| w.set_ccrdy(false)); |
| 165 | while !T::regs().isr().read().ccrdy() {} | 165 | while !self.isr().read().ccrdy() {} |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | fn convert() -> u16 { | 168 | fn convert(&self) { |
| 169 | // Set single conversion mode. | 169 | // Set single conversion mode. |
| 170 | T::regs().cfgr1().modify(|w| w.set_cont(false)); | 170 | self.cfgr1().modify(|w| w.set_cont(false)); |
| 171 | 171 | ||
| 172 | // Start conversion | 172 | // Start conversion |
| 173 | T::regs().cr().modify(|reg| { | 173 | self.cr().modify(|reg| { |
| 174 | reg.set_adstart(true); | 174 | reg.set_adstart(true); |
| 175 | }); | 175 | }); |
| 176 | 176 | ||
| 177 | // Waiting for End Of Conversion (EOC). | 177 | // Waiting for End Of Conversion (EOC). |
| 178 | while !T::regs().isr().read().eoc() {} | 178 | while !self.isr().read().eoc() {} |
| 179 | |||
| 180 | T::regs().dr().read().data() as u16 | ||
| 181 | } | 179 | } |
| 182 | } | 180 | } |
| 183 | 181 | ||
| 184 | impl<'d, T: AnyInstance> Adc<'d, T> { | 182 | impl<'d, T: Instance<Regs = crate::pac::adc::Adc>> Adc<'d, T> { |
| 185 | /// Create a new ADC driver. | 183 | /// Create a new ADC driver. |
| 186 | pub fn new(adc: Peri<'d, T>, resolution: Resolution) -> Self { | 184 | pub fn new(adc: Peri<'d, T>, resolution: Resolution) -> Self { |
| 187 | rcc::enable_and_reset::<T>(); | 185 | rcc::enable_and_reset::<T>(); |
| @@ -225,7 +223,7 @@ impl<'d, T: AnyInstance> Adc<'d, T> { | |||
| 225 | 223 | ||
| 226 | T::regs().cfgr1().modify(|w| w.set_autoff(autoff_value)); | 224 | T::regs().cfgr1().modify(|w| w.set_autoff(autoff_value)); |
| 227 | 225 | ||
| 228 | T::enable(); | 226 | T::regs().enable(); |
| 229 | 227 | ||
| 230 | // single conversion mode, software trigger | 228 | // single conversion mode, software trigger |
| 231 | T::regs().cfgr1().modify(|w| { | 229 | T::regs().cfgr1().modify(|w| { |
