aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh3
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/build.rs14
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/opamp.rs133
-rw-r--r--examples/stm32f334/src/bin/opamp.rs59
6 files changed, 213 insertions, 2 deletions
diff --git a/ci.sh b/ci.sh
index 714056f15..d8bbb7858 100755
--- a/ci.sh
+++ b/ci.sh
@@ -201,6 +201,9 @@ cargo batch \
201 $BUILD_EXTRA 201 $BUILD_EXTRA
202 202
203 203
204rm out/tests/stm32wb55rg/wpan_mac
205rm out/tests/stm32wb55rg/wpan_ble
206
204 207
205if [[ -z "${TELEPROBE_TOKEN-}" ]]; then 208if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
206 echo No teleprobe token found, skipping running HIL tests 209 echo No teleprobe token found, skipping running HIL tests
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 87f9083b3..ab1cae891 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -59,7 +59,7 @@ sdio-host = "0.5.0"
59embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 59embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
60critical-section = "1.1" 60critical-section = "1.1"
61atomic-polyfill = "1.0.1" 61atomic-polyfill = "1.0.1"
62stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ee2862086886cd8ebaf5fd5e3bd6cfbe5baa840" } 62stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-06d13dfd245cc9bf86fd88c35b401bdb84c079c4" }
63vcell = "0.1.3" 63vcell = "0.1.3"
64bxcan = "0.7.0" 64bxcan = "0.7.0"
65nb = "1.0.0" 65nb = "1.0.0"
@@ -78,7 +78,7 @@ critical-section = { version = "1.1", features = ["std"] }
78[build-dependencies] 78[build-dependencies]
79proc-macro2 = "1.0.36" 79proc-macro2 = "1.0.36"
80quote = "1.0.15" 80quote = "1.0.15"
81stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ee2862086886cd8ebaf5fd5e3bd6cfbe5baa840", default-features = false, features = ["metadata"]} 81stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-06d13dfd245cc9bf86fd88c35b401bdb84c079c4", default-features = false, features = ["metadata"]}
82 82
83 83
84[features] 84[features]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index ed5fa84d6..f825dbeeb 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -810,6 +810,20 @@ fn main() {
810 } 810 }
811 } 811 }
812 812
813 if regs.kind == "opamp" {
814 if !pin.signal.starts_with("VP") {
815 continue;
816 }
817
818 let peri = format_ident!("{}", p.name);
819 let pin_name = format_ident!("{}", pin.pin);
820 let ch: u8 = pin.signal.strip_prefix("VP").unwrap().parse().unwrap();
821
822 g.extend(quote! {
823 impl_opamp_pin!( #peri, #pin_name, #ch);
824 })
825 }
826
813 // DAC is special 827 // DAC is special
814 if regs.kind == "dac" { 828 if regs.kind == "dac" {
815 let peri = format_ident!("{}", p.name); 829 let peri = format_ident!("{}", p.name);
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index bd77fae41..e883678b5 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -49,6 +49,8 @@ pub mod i2s;
49pub mod ipcc; 49pub mod ipcc;
50#[cfg(feature = "low-power")] 50#[cfg(feature = "low-power")]
51pub mod low_power; 51pub mod low_power;
52#[cfg(opamp)]
53pub mod opamp;
52#[cfg(quadspi)] 54#[cfg(quadspi)]
53pub mod qspi; 55pub mod qspi;
54#[cfg(rng)] 56#[cfg(rng)]
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs
new file mode 100644
index 000000000..7b388aefe
--- /dev/null
+++ b/embassy-stm32/src/opamp.rs
@@ -0,0 +1,133 @@
1#![macro_use]
2
3use embassy_hal_internal::{into_ref, PeripheralRef};
4
5use crate::Peripheral;
6
7#[cfg(opamp_f3)]
8pub struct OpAmpOutput<'d, 'p, T: Instance, P: NonInvertingPin<T>> {
9 _inner: &'d OpAmp<'d, T>,
10 _input: &'p mut P,
11}
12
13pub struct OpAmp<'d, T: Instance> {
14 _inner: PeripheralRef<'d, T>,
15}
16
17impl<'d, T: Instance> OpAmp<'d, T> {
18 pub fn new(opamp: impl Peripheral<P = T> + 'd) -> Self {
19 Self::new_inner(opamp)
20 }
21
22 fn new_inner(opamp: impl Peripheral<P = T> + 'd) -> Self {
23 into_ref!(opamp);
24
25 #[cfg(opamp_f3)]
26 T::regs().opampcsr().modify(|w| {
27 w.set_opampen(true);
28 });
29
30 #[cfg(opamp_g4)]
31 T::regs().opamp_csr().modify(|w| {
32 w.set_opaen(true);
33 });
34
35 Self { _inner: opamp }
36 }
37
38 #[cfg(opamp_f3)]
39 pub fn buffer_for<'a, 'b, P>(&'a mut self, pin: &'b mut P) -> OpAmpOutput<'a, 'b, T, P>
40 where
41 P: NonInvertingPin<T>,
42 {
43 #[cfg(opamp_f3)]
44 T::regs().opampcsr().modify(|w| {
45 w.set_vp_sel(pin.channel());
46 });
47
48 OpAmpOutput {
49 _inner: self,
50 _input: pin,
51 }
52 }
53}
54
55pub trait Instance: sealed::Instance + 'static {}
56
57pub(crate) mod sealed {
58 pub trait Instance {
59 fn regs() -> crate::pac::opamp::Opamp;
60 }
61
62 pub trait NonInvertingPin<T: Instance> {
63 fn channel(&self) -> u8;
64 }
65
66 pub trait InvertingPin<T: Instance> {
67 fn channel(&self) -> u8;
68 }
69}
70
71pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {}
72
73pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {}
74
75#[cfg(opamp_f3)]
76macro_rules! impl_opamp_output {
77 ($inst:ident, $adc:ident, $ch:expr) => {
78 impl<'d, 'p, P: NonInvertingPin<crate::peripherals::$inst>> crate::adc::sealed::AdcPin<crate::peripherals::$adc>
79 for OpAmpOutput<'d, 'p, crate::peripherals::$inst, P>
80 {
81 fn channel(&self) -> u8 {
82 $ch
83 }
84 }
85
86 impl<'d, 'p, P: NonInvertingPin<crate::peripherals::$inst>> crate::adc::AdcPin<crate::peripherals::$adc>
87 for OpAmpOutput<'d, 'p, crate::peripherals::$inst, P>
88 {
89 }
90 };
91}
92
93#[cfg(opamp_f3)]
94foreach_peripheral!(
95 (opamp, OPAMP1) => {
96 impl_opamp_output!(OPAMP1, ADC1, 3);
97 };
98 (opamp, OPAMP2) => {
99 impl_opamp_output!(OPAMP2, ADC2, 3);
100 };
101 (opamp, OPAMP3) => {
102 impl_opamp_output!(OPAMP3, ADC3, 1);
103 };
104 (opamp, OPAMP4) => {
105 impl_opamp_output!(OPAMP4, ADC4, 3);
106 };
107);
108
109foreach_peripheral! {
110 (opamp, $inst:ident) => {
111 impl sealed::Instance for crate::peripherals::$inst {
112 fn regs() -> crate::pac::opamp::Opamp {
113 crate::pac::$inst
114 }
115 }
116
117 impl Instance for crate::peripherals::$inst {
118
119 }
120 };
121}
122
123#[allow(unused_macros)]
124macro_rules! impl_opamp_pin {
125 ($inst:ident, $pin:ident, $ch:expr) => {
126 impl crate::opamp::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {}
127 impl crate::opamp::sealed::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {
128 fn channel(&self) -> u8 {
129 $ch
130 }
131 }
132 };
133}
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs
new file mode 100644
index 000000000..72263bab8
--- /dev/null
+++ b/examples/stm32f334/src/bin/opamp.rs
@@ -0,0 +1,59 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::info;
6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::opamp::OpAmp;
9use embassy_stm32::peripherals::ADC2;
10use embassy_stm32::rcc::AdcClockSource;
11use embassy_stm32::time::mhz;
12use embassy_stm32::{adc, bind_interrupts, Config};
13use embassy_time::{Delay, Duration, Timer};
14use {defmt_rtt as _, panic_probe as _};
15
16bind_interrupts!(struct Irqs {
17 ADC1_2 => adc::InterruptHandler<ADC2>;
18});
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) -> ! {
22 let mut config = Config::default();
23 config.rcc.sysclk = Some(mhz(64));
24 config.rcc.hclk = Some(mhz(64));
25 config.rcc.pclk1 = Some(mhz(32));
26 config.rcc.pclk2 = Some(mhz(64));
27 config.rcc.adc = Some(AdcClockSource::PllDiv1);
28
29 let mut p = embassy_stm32::init(config);
30
31 info!("create adc...");
32
33 let mut adc = Adc::new(p.ADC2, Irqs, &mut Delay);
34 let mut opamp = OpAmp::new(p.OPAMP2);
35
36 adc.set_sample_time(SampleTime::Cycles601_5);
37
38 info!("enable vrefint...");
39
40 let mut vrefint = adc.enable_vref(&mut Delay);
41 let mut temperature = adc.enable_temperature();
42 let mut buffer = opamp.buffer_for(&mut p.PA7);
43
44 loop {
45 let vref = adc.read(&mut vrefint).await;
46 info!("read vref: {} (should be {})", vref, vrefint.value());
47
48 let temp = adc.read(&mut temperature).await;
49 info!("read temperature: {}", temp);
50
51 let buffer = adc.read(&mut buffer).await;
52 info!("read buffer: {}", buffer);
53
54 let pin_mv = (buffer as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095;
55 info!("computed pin mv: {}", pin_mv);
56
57 Timer::after(Duration::from_millis(500)).await;
58 }
59}