aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/adc/adc4.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/adc/adc4.rs')
-rw-r--r--embassy-stm32/src/adc/adc4.rs207
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
5use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel}; 5use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel};
6 6
7use super::blocking_delay_us; 7use super::blocking_delay_us;
8use crate::adc::ConversionMode; 8use crate::adc::{AdcRegs, ConversionMode, Instance};
9#[cfg(stm32u5)] 9#[cfg(stm32u5)]
10pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr; 10pub 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
93pub trait SealedInstance { 93impl 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
98pub 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
102foreach_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
223pub struct Adc4<'d, T: Instance> { 200pub 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
234impl<'d, T: Instance + super::AnyInstance> super::Adc<'d, T> { 211impl<'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| {