aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-11 09:01:09 -0600
committerxoviat <[email protected]>2025-11-11 09:01:09 -0600
commit16f2aaca61df2e708e78a12051365034281c95a4 (patch)
tree34698e6cf291967da21f27ce8fe125e736dca686
parent3d1f09597335d3681699ba09a77da4b39ed984fd (diff)
adc: impl. differential channels
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/build.rs37
-rw-r--r--embassy-stm32/src/adc/g4.rs36
-rw-r--r--embassy-stm32/src/adc/mod.rs44
4 files changed, 86 insertions, 35 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 108321d0a..86c995ec2 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -197,11 +197,11 @@ aligned = "0.4.1"
197heapless = "0.9.1" 197heapless = "0.9.1"
198 198
199#stm32-metapac = { version = "18" } 199#stm32-metapac = { version = "18" }
200stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-22374e3344a2c9150b9b3d4da45c03f398fdc54e" } 200stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b77c8d968f53b18d6bdcd052e354b5070ec2bbc2" }
201 201
202[build-dependencies] 202[build-dependencies]
203#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} 203#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]}
204stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-22374e3344a2c9150b9b3d4da45c03f398fdc54e", default-features = false, features = ["metadata"] } 204stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b77c8d968f53b18d6bdcd052e354b5070ec2bbc2", default-features = false, features = ["metadata"] }
205 205
206proc-macro2 = "1.0.36" 206proc-macro2 = "1.0.36"
207quote = "1.0.15" 207quote = "1.0.15"
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 940e29417..017b0f196 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -1346,6 +1346,8 @@ fn main() {
1346 1346
1347 for p in METADATA.peripherals { 1347 for p in METADATA.peripherals {
1348 if let Some(regs) = &p.registers { 1348 if let Some(regs) = &p.registers {
1349 let mut adc_pairs: BTreeMap<u8, (Option<Ident>, Option<Ident>)> = BTreeMap::new();
1350
1349 for pin in p.pins { 1351 for pin in p.pins {
1350 let key = (regs.kind, pin.signal); 1352 let key = (regs.kind, pin.signal);
1351 if let Some(tr) = signals.get(&key) { 1353 if let Some(tr) = signals.get(&key) {
@@ -1467,25 +1469,29 @@ fn main() {
1467 }; 1469 };
1468 1470
1469 // H7 has differential voltage measurements 1471 // H7 has differential voltage measurements
1470 let ch: Option<u8> = if pin.signal.starts_with("INP") { 1472 let ch: Option<(u8, bool)> = if pin.signal.starts_with("INP") {
1471 Some(pin.signal.strip_prefix("INP").unwrap().parse().unwrap()) 1473 Some((pin.signal.strip_prefix("INP").unwrap().parse().unwrap(), false))
1472 } else if pin.signal.starts_with("INN") { 1474 } else if pin.signal.starts_with("INN") {
1473 // TODO handle in the future when embassy supports differential measurements 1475 Some((pin.signal.strip_prefix("INN").unwrap().parse().unwrap(), true))
1474 None
1475 } else if pin.signal.starts_with("IN") && pin.signal.ends_with('b') { 1476 } else if pin.signal.starts_with("IN") && pin.signal.ends_with('b') {
1476 // we number STM32L1 ADC bank 1 as 0..=31, bank 2 as 32..=63 1477 // we number STM32L1 ADC bank 1 as 0..=31, bank 2 as 32..=63
1477 let signal = pin.signal.strip_prefix("IN").unwrap().strip_suffix('b').unwrap(); 1478 let signal = pin.signal.strip_prefix("IN").unwrap().strip_suffix('b').unwrap();
1478 Some(32u8 + signal.parse::<u8>().unwrap()) 1479 Some((32u8 + signal.parse::<u8>().unwrap(), false))
1479 } else if pin.signal.starts_with("IN") { 1480 } else if pin.signal.starts_with("IN") {
1480 Some(pin.signal.strip_prefix("IN").unwrap().parse().unwrap()) 1481 Some((pin.signal.strip_prefix("IN").unwrap().parse().unwrap(), false))
1481 } else { 1482 } else {
1482 None 1483 None
1483 }; 1484 };
1484 if let Some(ch) = ch { 1485 if let Some((ch, false)) = ch {
1486 adc_pairs.entry(ch).or_insert((None, None)).0.replace(pin_name.clone());
1487
1485 g.extend(quote! { 1488 g.extend(quote! {
1486 impl_adc_pin!( #peri, #pin_name, #ch); 1489 impl_adc_pin!( #peri, #pin_name, #ch);
1487 }) 1490 })
1488 } 1491 }
1492 if let Some((ch, true)) = ch {
1493 adc_pairs.entry(ch).or_insert((None, None)).1.replace(pin_name.clone());
1494 }
1489 } 1495 }
1490 1496
1491 if regs.kind == "opamp" { 1497 if regs.kind == "opamp" {
@@ -1524,6 +1530,23 @@ fn main() {
1524 }) 1530 })
1525 } 1531 }
1526 } 1532 }
1533
1534 {
1535 let peri = format_ident!("{}", p.name);
1536
1537 for (ch, (pin, npin)) in adc_pairs {
1538 let (pin_name, npin_name) = match (pin, npin) {
1539 (Some(pin), Some(npin)) => (pin, npin),
1540 _ => {
1541 continue;
1542 }
1543 };
1544
1545 g.extend(quote! {
1546 impl_adc_pair!( #peri, #pin_name, #npin_name, #ch);
1547 })
1548 }
1549 }
1527 } 1550 }
1528 } 1551 }
1529 1552
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index 5d9c6ff74..c0fb7c733 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -140,37 +140,19 @@ impl<'d, T: Instance> Adc<'d, T> {
140 ); 140 );
141 } 141 }
142 142
143 let mut s = Self { adc };
144 s.power_up();
145 s.configure_differential_inputs();
146
147 s.calibrate();
148 blocking_delay_us(1);
149
150 Self::enable();
151 s.configure();
152
153 s
154 }
155
156 fn power_up(&mut self) {
157 T::regs().cr().modify(|reg| { 143 T::regs().cr().modify(|reg| {
158 reg.set_deeppwd(false); 144 reg.set_deeppwd(false);
159 reg.set_advregen(true); 145 reg.set_advregen(true);
160 }); 146 });
161 147
162 blocking_delay_us(20); 148 blocking_delay_us(20);
163 }
164 149
165 fn configure_differential_inputs(&mut self) {
166 T::regs().difsel().modify(|w| { 150 T::regs().difsel().modify(|w| {
167 for n in 0..18 { 151 for n in 0..18 {
168 w.set_difsel(n, Difsel::SINGLE_ENDED); 152 w.set_difsel(n, Difsel::SINGLE_ENDED);
169 } 153 }
170 }); 154 });
171 }
172 155
173 fn calibrate(&mut self) {
174 T::regs().cr().modify(|w| { 156 T::regs().cr().modify(|w| {
175 w.set_adcaldif(Adcaldif::SINGLE_ENDED); 157 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
176 }); 158 });
@@ -190,6 +172,16 @@ impl<'d, T: Instance> Adc<'d, T> {
190 while T::regs().cr().read().adcal() {} 172 while T::regs().cr().read().adcal() {}
191 173
192 blocking_delay_us(20); 174 blocking_delay_us(20);
175
176 Self::enable();
177
178 // single conversion mode, software trigger
179 T::regs().cfgr().modify(|w| {
180 w.set_cont(false);
181 w.set_exten(Exten::DISABLED);
182 });
183
184 Self { adc }
193 } 185 }
194 186
195 fn enable() { 187 fn enable() {
@@ -213,14 +205,6 @@ impl<'d, T: Instance> Adc<'d, T> {
213 } 205 }
214 } 206 }
215 207
216 fn configure(&mut self) {
217 // single conversion mode, software trigger
218 T::regs().cfgr().modify(|w| {
219 w.set_cont(false);
220 w.set_exten(Exten::DISABLED);
221 });
222 }
223
224 /// Enable reading the voltage reference internal channel. 208 /// Enable reading the voltage reference internal channel.
225 pub fn enable_vrefint(&self) -> super::VrefInt 209 pub fn enable_vrefint(&self) -> super::VrefInt
226 where 210 where
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 3bf893a35..a11e0c1b4 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -80,6 +80,11 @@ pub(crate) trait SealedAdcChannel<T> {
80 80
81 #[allow(unused)] 81 #[allow(unused)]
82 fn channel(&self) -> u8; 82 fn channel(&self) -> u8;
83
84 #[allow(unused)]
85 fn is_differential(&self) -> bool {
86 false
87 }
83} 88}
84 89
85/// Performs a busy-wait delay for a specified number of microseconds. 90/// Performs a busy-wait delay for a specified number of microseconds.
@@ -178,6 +183,7 @@ pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
178 183
179 AnyAdcChannel { 184 AnyAdcChannel {
180 channel: self.channel(), 185 channel: self.channel(),
186 is_differential: self.is_differential(),
181 _phantom: PhantomData, 187 _phantom: PhantomData,
182 } 188 }
183 } 189 }
@@ -189,6 +195,7 @@ pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
189/// storing them in an array. 195/// storing them in an array.
190pub struct AnyAdcChannel<T> { 196pub struct AnyAdcChannel<T> {
191 channel: u8, 197 channel: u8,
198 is_differential: bool,
192 _phantom: PhantomData<T>, 199 _phantom: PhantomData<T>,
193} 200}
194impl_peripheral!(AnyAdcChannel<T: Instance>); 201impl_peripheral!(AnyAdcChannel<T: Instance>);
@@ -197,6 +204,10 @@ impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<T> {
197 fn channel(&self) -> u8 { 204 fn channel(&self) -> u8 {
198 self.channel 205 self.channel
199 } 206 }
207
208 fn is_differential(&self) -> bool {
209 self.is_differential
210 }
200} 211}
201 212
202impl<T> AnyAdcChannel<T> { 213impl<T> AnyAdcChannel<T> {
@@ -315,6 +326,39 @@ macro_rules! impl_adc_pin {
315 }; 326 };
316} 327}
317 328
329#[allow(unused_macros)]
330macro_rules! impl_adc_pair {
331 ($inst:ident, $pin:ident, $npin:ident, $ch:expr) => {
332 impl crate::adc::AdcChannel<peripherals::$inst>
333 for (
334 crate::Peri<'_, crate::peripherals::$pin>,
335 crate::Peri<'_, crate::peripherals::$npin>,
336 )
337 {
338 }
339 impl crate::adc::SealedAdcChannel<peripherals::$inst>
340 for (
341 crate::Peri<'_, crate::peripherals::$pin>,
342 crate::Peri<'_, crate::peripherals::$npin>,
343 )
344 {
345 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
346 fn setup(&mut self) {
347 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(&mut self.0);
348 <crate::peripherals::$npin as crate::gpio::SealedPin>::set_as_analog(&mut self.1);
349 }
350
351 fn channel(&self) -> u8 {
352 $ch
353 }
354
355 fn is_differential(&self) -> bool {
356 true
357 }
358 }
359 };
360}
361
318/// Get the maximum reading value for this resolution. 362/// Get the maximum reading value for this resolution.
319/// 363///
320/// This is `2**n - 1`. 364/// This is `2**n - 1`.