aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-12-11 09:08:50 -0600
committerGitHub <[email protected]>2025-12-11 09:08:50 -0600
commit1aadce76847a7686bf66e3a6532e18e05042f78a (patch)
treeca42d80e784a6746065bd4e0c676db3ef0f10b93 /embassy-stm32
parent52a9b08f0ca13d23bfb039c884a9101997c10567 (diff)
parentf650afc33b2d6b39116f27c6545c5f2d9e3c7d06 (diff)
Merge branch 'main' into main
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/CHANGELOG.md6
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/adc/adc4.rs207
-rw-r--r--embassy-stm32/src/adc/c0.rs64
-rw-r--r--embassy-stm32/src/adc/g4.rs121
-rw-r--r--embassy-stm32/src/adc/injected.rs16
-rw-r--r--embassy-stm32/src/adc/mod.rs254
-rw-r--r--embassy-stm32/src/adc/ringbuffered.rs48
-rw-r--r--embassy-stm32/src/adc/v2.rs60
-rw-r--r--embassy-stm32/src/adc/v3.rs91
-rw-r--r--embassy-stm32/src/adc/v4.rs76
-rw-r--r--embassy-stm32/src/dma/gpdma/mod.rs6
-rw-r--r--embassy-stm32/src/dma/mod.rs44
-rw-r--r--embassy-stm32/src/dma/util.rs58
-rw-r--r--embassy-stm32/src/dma/word.rs4
-rw-r--r--embassy-stm32/src/exti.rs2
-rw-r--r--embassy-stm32/src/fmt.rs10
-rw-r--r--embassy-stm32/src/gpio.rs6
-rw-r--r--embassy-stm32/src/i2c/mod.rs2
-rw-r--r--embassy-stm32/src/i2c/v1.rs7
-rw-r--r--embassy-stm32/src/i2c/v2.rs10
-rw-r--r--embassy-stm32/src/low_power.rs61
-rw-r--r--embassy-stm32/src/qspi/mod.rs4
-rw-r--r--embassy-stm32/src/rcc/mod.rs22
-rw-r--r--embassy-stm32/src/rcc/n6.rs20
-rw-r--r--embassy-stm32/src/sai/mod.rs10
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs1352
-rw-r--r--embassy-stm32/src/sdmmc/sd.rs693
-rw-r--r--embassy-stm32/src/sdmmc/sdio.rs177
-rw-r--r--embassy-stm32/src/spi/mod.rs109
-rw-r--r--embassy-stm32/src/time.rs2
-rw-r--r--embassy-stm32/src/time_driver.rs6
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs90
-rw-r--r--embassy-stm32/src/timer/input_capture.rs2
-rw-r--r--embassy-stm32/src/timer/low_level.rs235
-rw-r--r--embassy-stm32/src/timer/mod.rs34
-rw-r--r--embassy-stm32/src/timer/one_pulse.rs12
-rw-r--r--embassy-stm32/src/timer/pwm_input.rs14
-rw-r--r--embassy-stm32/src/timer/ringbuffered.rs29
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs82
-rw-r--r--embassy-stm32/src/usart/mod.rs8
41 files changed, 2296 insertions, 1762 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index 6c36bc108..38f22b1c3 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7 7
8## Unreleased - ReleaseDate 8## Unreleased - ReleaseDate
9 9
10- fix: stm32: GPDMA driver reset ignored during channel configuration
11- fix: stm32: SPI driver SSOE and SSM manegment, add `nss_output_disable` to SPI Config
12- change: stm32: use typelevel timer type to allow dma for 32 bit timers
10- fix: fix incorrect handling of split interrupts in timer driver 13- fix: fix incorrect handling of split interrupts in timer driver
11- feat: allow granular stop for regular usart 14- feat: allow granular stop for regular usart
12- feat: Add continuous waveform method to SimplePWM 15- feat: Add continuous waveform method to SimplePWM
@@ -85,8 +88,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
85- fix: build script ensures EXTI2_TSC is listed as the IRQ of EXTI2 even if the PAC doesn't 88- fix: build script ensures EXTI2_TSC is listed as the IRQ of EXTI2 even if the PAC doesn't
86- feat: stm32/lcd: added implementation 89- feat: stm32/lcd: added implementation
87- change: add error messages to can timing calculations ([#4961](https://github.com/embassy-rs/embassy/pull/4961)) 90- change: add error messages to can timing calculations ([#4961](https://github.com/embassy-rs/embassy/pull/4961))
91- feat: stm32/spi bidirectional mode
88- fix: stm32/i2c v2: add stop flag on stop received 92- fix: stm32/i2c v2: add stop flag on stop received
89- stm32: Add blocking_listen for blocking I2C driver 93- stm32: Add blocking_listen for blocking I2C driver
94- fix: stm32l47*/stm32l48* adc analog pin setup
95- fix: keep stm32/sai: make NODIV independent of MCKDIV
90 96
91## 0.4.0 - 2025-08-26 97## 0.4.0 - 2025-08-26
92 98
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index e10409112..7989fc5d7 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -200,11 +200,11 @@ aligned = "0.4.1"
200heapless = "0.9.1" 200heapless = "0.9.1"
201 201
202#stm32-metapac = { version = "18" } 202#stm32-metapac = { version = "18" }
203stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f61ed017ef12ec84ff04c49e3147694bda3b29cb" } 203stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-497fb3042b49b765d8974aac87b8ab4fa3566d74" }
204 204
205[build-dependencies] 205[build-dependencies]
206#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} 206#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]}
207stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f61ed017ef12ec84ff04c49e3147694bda3b29cb", default-features = false, features = ["metadata"] } 207stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-497fb3042b49b765d8974aac87b8ab4fa3566d74", default-features = false, features = ["metadata"] }
208 208
209proc-macro2 = "1.0.36" 209proc-macro2 = "1.0.36"
210quote = "1.0.15" 210quote = "1.0.15"
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| {
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;
4use stm32_metapac::adc::vals::{SampleTime, Scandir}; 4use stm32_metapac::adc::vals::{SampleTime, Scandir};
5 5
6use super::{Adc, Instance, Resolution, blocking_delay_us}; 6use super::{Adc, Instance, Resolution, blocking_delay_us};
7use crate::adc::{AnyInstance, ConversionMode}; 7use crate::adc::{AdcRegs, ConversionMode};
8use crate::time::Hertz; 8use crate::time::Hertz;
9use crate::{Peri, pac, rcc}; 9use crate::{Peri, pac, rcc};
10 10
@@ -43,52 +43,52 @@ fn from_ker_ck(frequency: Hertz) -> Presc {
43 } 43 }
44} 44}
45 45
46impl<T: Instance> super::SealedAnyInstance for T { 46impl 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
184impl<'d, T: AnyInstance> Adc<'d, T> { 182impl<'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| {
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index 1767a3bb3..e93ed945f 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -12,7 +12,8 @@ use super::{
12 Adc, AnyAdcChannel, ConversionMode, Instance, RegularConversionMode, Resolution, RxDma, SampleTime, 12 Adc, AnyAdcChannel, ConversionMode, Instance, RegularConversionMode, Resolution, RxDma, SampleTime,
13 blocking_delay_us, 13 blocking_delay_us,
14}; 14};
15use crate::adc::{AnyInstance, SealedAdcChannel}; 15use crate::adc::{AdcRegs, BasicAdcRegs, SealedAdcChannel};
16use crate::pac::adc::regs::{Smpr, Smpr2, Sqr1, Sqr2, Sqr3, Sqr4};
16use crate::time::Hertz; 17use crate::time::Hertz;
17use crate::{Peri, pac, rcc}; 18use crate::{Peri, pac, rcc};
18 19
@@ -68,79 +69,77 @@ pub struct ConversionTrigger {
68 pub edge: Exten, 69 pub edge: Exten,
69} 70}
70 71
71impl<T: Instance> super::SealedAnyInstance for T { 72impl super::AdcRegs for crate::pac::adc::Adc {
72 fn dr() -> *mut u16 { 73 fn data(&self) -> *mut u16 {
73 T::regs().dr().as_ptr() as *mut u16 74 crate::pac::adc::Adc::dr(*self).as_ptr() as *mut u16
74 } 75 }
75 76
76 fn enable() { 77 fn enable(&self) {
77 // Make sure bits are off 78 // Make sure bits are off
78 while T::regs().cr().read().addis() { 79 while self.cr().read().addis() {
79 // spin 80 // spin
80 } 81 }
81 82
82 if !T::regs().cr().read().aden() { 83 if !self.cr().read().aden() {
83 // Enable ADC 84 // Enable ADC
84 T::regs().isr().modify(|reg| { 85 self.isr().modify(|reg| {
85 reg.set_adrdy(true); 86 reg.set_adrdy(true);
86 }); 87 });
87 T::regs().cr().modify(|reg| { 88 self.cr().modify(|reg| {
88 reg.set_aden(true); 89 reg.set_aden(true);
89 }); 90 });
90 91
91 while !T::regs().isr().read().adrdy() { 92 while !self.isr().read().adrdy() {
92 // spin 93 // spin
93 } 94 }
94 } 95 }
95 } 96 }
96 97
97 fn start() { 98 fn start(&self) {
98 T::regs().cr().modify(|reg| { 99 self.cr().modify(|reg| {
99 reg.set_adstart(true); 100 reg.set_adstart(true);
100 }); 101 });
101 } 102 }
102 103
103 fn stop() { 104 fn stop(&self) {
104 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 105 if self.cr().read().adstart() && !self.cr().read().addis() {
105 T::regs().cr().modify(|reg| { 106 self.cr().modify(|reg| {
106 reg.set_adstp(Adstp::STOP); 107 reg.set_adstp(Adstp::STOP);
107 }); 108 });
108 // The software must poll ADSTART until the bit is reset before assuming the 109 // The software must poll ADSTART until the bit is reset before assuming the
109 // ADC is completely stopped 110 // ADC is completely stopped
110 while T::regs().cr().read().adstart() {} 111 while self.cr().read().adstart() {}
111 } 112 }
112 113
113 // Disable dma control and continuous conversion, if enabled 114 // Disable dma control and continuous conversion, if enabled
114 T::regs().cfgr().modify(|reg| { 115 self.cfgr().modify(|reg| {
115 reg.set_cont(false); 116 reg.set_cont(false);
116 reg.set_dmaen(Dmaen::DISABLE); 117 reg.set_dmaen(Dmaen::DISABLE);
117 }); 118 });
118 } 119 }
119 120
120 fn convert() -> u16 { 121 fn convert(&self) {
121 T::regs().isr().modify(|reg| { 122 self.isr().modify(|reg| {
122 reg.set_eos(true); 123 reg.set_eos(true);
123 reg.set_eoc(true); 124 reg.set_eoc(true);
124 }); 125 });
125 126
126 // Start conversion 127 // Start conversion
127 T::regs().cr().modify(|reg| { 128 self.cr().modify(|reg| {
128 reg.set_adstart(true); 129 reg.set_adstart(true);
129 }); 130 });
130 131
131 while !T::regs().isr().read().eos() { 132 while !self.isr().read().eos() {
132 // spin 133 // spin
133 } 134 }
134
135 T::regs().dr().read().0 as u16
136 } 135 }
137 136
138 fn configure_dma(conversion_mode: ConversionMode) { 137 fn configure_dma(&self, conversion_mode: ConversionMode) {
139 T::regs().isr().modify(|reg| { 138 self.isr().modify(|reg| {
140 reg.set_ovr(true); 139 reg.set_ovr(true);
141 }); 140 });
142 141
143 T::regs().cfgr().modify(|reg| { 142 self.cfgr().modify(|reg| {
144 reg.set_discen(false); // Convert all channels for each trigger 143 reg.set_discen(false); // Convert all channels for each trigger
145 reg.set_dmacfg(match conversion_mode { 144 reg.set_dmacfg(match conversion_mode {
146 ConversionMode::Singular => Dmacfg::ONE_SHOT, 145 ConversionMode::Singular => Dmacfg::ONE_SHOT,
@@ -152,43 +151,41 @@ impl<T: Instance> super::SealedAnyInstance for T {
152 if let ConversionMode::Repeated(mode) = conversion_mode { 151 if let ConversionMode::Repeated(mode) = conversion_mode {
153 match mode { 152 match mode {
154 RegularConversionMode::Continuous => { 153 RegularConversionMode::Continuous => {
155 T::regs().cfgr().modify(|reg| { 154 self.cfgr().modify(|reg| {
156 reg.set_cont(true); 155 reg.set_cont(true);
157 }); 156 });
158 } 157 }
159 RegularConversionMode::Triggered(trigger) => { 158 RegularConversionMode::Triggered(trigger) => {
160 T::regs().cfgr().modify(|r| { 159 self.cfgr().modify(|r| {
161 r.set_cont(false); // New trigger is neede for each sample to be read 160 r.set_cont(false); // New trigger is neede for each sample to be read
162 }); 161 });
163 162
164 T::regs().cfgr().modify(|r| { 163 self.cfgr().modify(|r| {
165 r.set_extsel(trigger.channel); 164 r.set_extsel(trigger.channel);
166 r.set_exten(trigger.edge); 165 r.set_exten(trigger.edge);
167 }); 166 });
168 167
169 // Regular conversions uses DMA so no need to generate interrupt 168 // Regular conversions uses DMA so no need to generate interrupt
170 T::regs().ier().modify(|r| r.set_eosie(false)); 169 self.ier().modify(|r| r.set_eosie(false));
171 } 170 }
172 } 171 }
173 } 172 }
174 } 173 }
175 174
176 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 175 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
177 T::regs().cr().modify(|w| w.set_aden(false)); 176 self.cr().modify(|w| w.set_aden(false));
178
179 // Set sequence length
180 T::regs().sqr1().modify(|w| {
181 w.set_l(sequence.len() as u8 - 1);
182 });
183 177
184 #[cfg(stm32g4)] 178 #[cfg(stm32g4)]
185 let mut difsel = DifselReg::default(); 179 let mut difsel = DifselReg::default();
186 let mut smpr = T::regs().smpr().read(); 180 let mut smpr = Smpr::default();
187 let mut smpr2 = T::regs().smpr2().read(); 181 let mut smpr2 = Smpr2::default();
188 let mut sqr1 = T::regs().sqr1().read(); 182 let mut sqr1 = Sqr1::default();
189 let mut sqr2 = T::regs().sqr2().read(); 183 let mut sqr2 = Sqr2::default();
190 let mut sqr3 = T::regs().sqr3().read(); 184 let mut sqr3 = Sqr3::default();
191 let mut sqr4 = T::regs().sqr4().read(); 185 let mut sqr4 = Sqr4::default();
186
187 // Set sequence length
188 sqr1.set_l(sequence.len() as u8 - 1);
192 189
193 // Configure channels and ranks 190 // Configure channels and ranks
194 for (_i, ((ch, is_differential), sample_time)) in sequence.enumerate() { 191 for (_i, ((ch, is_differential), sample_time)) in sequence.enumerate() {
@@ -230,18 +227,18 @@ impl<T: Instance> super::SealedAnyInstance for T {
230 } 227 }
231 } 228 }
232 229
233 T::regs().smpr().write_value(smpr); 230 self.smpr().write_value(smpr);
234 T::regs().smpr2().write_value(smpr2); 231 self.smpr2().write_value(smpr2);
235 T::regs().sqr1().write_value(sqr1); 232 self.sqr1().write_value(sqr1);
236 T::regs().sqr2().write_value(sqr2); 233 self.sqr2().write_value(sqr2);
237 T::regs().sqr3().write_value(sqr3); 234 self.sqr3().write_value(sqr3);
238 T::regs().sqr4().write_value(sqr4); 235 self.sqr4().write_value(sqr4);
239 #[cfg(stm32g4)] 236 #[cfg(stm32g4)]
240 T::regs().difsel().write_value(difsel); 237 self.difsel().write_value(difsel);
241 } 238 }
242} 239}
243 240
244impl<'d, T: Instance + AnyInstance> Adc<'d, T> { 241impl<'d, T: Instance<Regs = crate::pac::adc::Adc>> Adc<'d, T> {
245 /// Create a new ADC driver. 242 /// Create a new ADC driver.
246 pub fn new(adc: Peri<'d, T>, config: AdcConfig) -> Self { 243 pub fn new(adc: Peri<'d, T>, config: AdcConfig) -> Self {
247 rcc::enable_and_reset::<T>(); 244 rcc::enable_and_reset::<T>();
@@ -293,7 +290,7 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> {
293 290
294 blocking_delay_us(20); 291 blocking_delay_us(20);
295 292
296 T::enable(); 293 T::regs().enable();
297 294
298 // single conversion mode, software trigger 295 // single conversion mode, software trigger
299 T::regs().cfgr().modify(|w| { 296 T::regs().cfgr().modify(|w| {
@@ -409,10 +406,10 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> {
409 /// `InjectedAdc<T, N>` to enforce bounds at compile time. 406 /// `InjectedAdc<T, N>` to enforce bounds at compile time.
410 pub fn setup_injected_conversions<'a, const N: usize>( 407 pub fn setup_injected_conversions<'a, const N: usize>(
411 self, 408 self,
412 sequence: [(AnyAdcChannel<T>, SampleTime); N], 409 sequence: [(AnyAdcChannel<'a, T>, SampleTime); N],
413 trigger: ConversionTrigger, 410 trigger: ConversionTrigger,
414 interrupt: bool, 411 interrupt: bool,
415 ) -> InjectedAdc<T, N> { 412 ) -> InjectedAdc<'a, T, N> {
416 assert!(N != 0, "Read sequence cannot be empty"); 413 assert!(N != 0, "Read sequence cannot be empty");
417 assert!( 414 assert!(
418 N <= NR_INJECTED_RANKS, 415 N <= NR_INJECTED_RANKS,
@@ -420,12 +417,12 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> {
420 NR_INJECTED_RANKS 417 NR_INJECTED_RANKS
421 ); 418 );
422 419
423 T::enable(); 420 T::regs().enable();
424 421
425 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); 422 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1));
426 423
427 for (n, (channel, sample_time)) in sequence.into_iter().enumerate() { 424 for (n, (channel, sample_time)) in sequence.iter().enumerate() {
428 let sample_time = sample_time.into(); 425 let sample_time = sample_time.clone().into();
429 if channel.channel() <= 9 { 426 if channel.channel() <= 9 {
430 T::regs() 427 T::regs()
431 .smpr() 428 .smpr()
@@ -487,16 +484,16 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> {
487 /// This function is `unsafe` because it clones the ADC peripheral handle unchecked. Both the 484 /// This function is `unsafe` because it clones the ADC peripheral handle unchecked. Both the
488 /// `RingBufferedAdc` and `InjectedAdc` take ownership of the handle and drop it independently. 485 /// `RingBufferedAdc` and `InjectedAdc` take ownership of the handle and drop it independently.
489 /// Ensure no other code concurrently accesses the same ADC instance in a conflicting way. 486 /// Ensure no other code concurrently accesses the same ADC instance in a conflicting way.
490 pub fn into_ring_buffered_and_injected<'a, const N: usize>( 487 pub fn into_ring_buffered_and_injected<'a, 'b, const N: usize>(
491 self, 488 self,
492 dma: Peri<'a, impl RxDma<T>>, 489 dma: Peri<'a, impl RxDma<T>>,
493 dma_buf: &'a mut [u16], 490 dma_buf: &'a mut [u16],
494 regular_sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, T::SampleTime)>, 491 regular_sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<'b, T>, <T::Regs as BasicAdcRegs>::SampleTime)>,
495 regular_conversion_mode: RegularConversionMode, 492 regular_conversion_mode: RegularConversionMode,
496 injected_sequence: [(AnyAdcChannel<T>, SampleTime); N], 493 injected_sequence: [(AnyAdcChannel<'b, T>, SampleTime); N],
497 injected_trigger: ConversionTrigger, 494 injected_trigger: ConversionTrigger,
498 injected_interrupt: bool, 495 injected_interrupt: bool,
499 ) -> (super::RingBufferedAdc<'a, T>, InjectedAdc<T, N>) { 496 ) -> (super::RingBufferedAdc<'a, T>, InjectedAdc<'b, T, N>) {
500 unsafe { 497 unsafe {
501 ( 498 (
502 Self { 499 Self {
@@ -531,7 +528,7 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> {
531 } 528 }
532} 529}
533 530
534impl<T: Instance, const N: usize> InjectedAdc<T, N> { 531impl<'a, T: Instance<Regs = crate::pac::adc::Adc>, const N: usize> InjectedAdc<'a, T, N> {
535 /// Read sampled data from all injected ADC injected ranks 532 /// Read sampled data from all injected ADC injected ranks
536 /// Clear the JEOS flag to allow a new injected sequence 533 /// Clear the JEOS flag to allow a new injected sequence
537 pub(super) fn read_injected_data() -> [u16; N] { 534 pub(super) fn read_injected_data() -> [u16; N] {
diff --git a/embassy-stm32/src/adc/injected.rs b/embassy-stm32/src/adc/injected.rs
index ccaa5d1b2..029722b84 100644
--- a/embassy-stm32/src/adc/injected.rs
+++ b/embassy-stm32/src/adc/injected.rs
@@ -4,19 +4,19 @@ use core::sync::atomic::{Ordering, compiler_fence};
4#[allow(unused_imports)] 4#[allow(unused_imports)]
5use embassy_hal_internal::Peri; 5use embassy_hal_internal::Peri;
6 6
7use super::{AnyAdcChannel, SampleTime}; 7use super::{AdcRegs, AnyAdcChannel, SampleTime};
8use crate::adc::Adc;
8#[allow(unused_imports)] 9#[allow(unused_imports)]
9use crate::adc::Instance; 10use crate::adc::Instance;
10use crate::adc::{Adc, AnyInstance};
11 11
12/// Injected ADC sequence with owned channels. 12/// Injected ADC sequence with owned channels.
13pub struct InjectedAdc<T: Instance, const N: usize> { 13pub struct InjectedAdc<'a, T: Instance<Regs = crate::pac::adc::Adc>, const N: usize> {
14 _channels: [(AnyAdcChannel<T>, SampleTime); N], 14 _channels: [(AnyAdcChannel<'a, T>, SampleTime); N],
15 _phantom: PhantomData<T>, 15 _phantom: PhantomData<T>,
16} 16}
17 17
18impl<T: Instance, const N: usize> InjectedAdc<T, N> { 18impl<'a, T: Instance<Regs = crate::pac::adc::Adc>, const N: usize> InjectedAdc<'a, T, N> {
19 pub(crate) fn new(channels: [(AnyAdcChannel<T>, SampleTime); N]) -> Self { 19 pub(crate) fn new(channels: [(AnyAdcChannel<'a, T>, SampleTime); N]) -> Self {
20 Self { 20 Self {
21 _channels: channels, 21 _channels: channels,
22 _phantom: PhantomData, 22 _phantom: PhantomData,
@@ -36,9 +36,9 @@ impl<T: Instance, const N: usize> InjectedAdc<T, N> {
36 } 36 }
37} 37}
38 38
39impl<T: Instance + AnyInstance, const N: usize> Drop for InjectedAdc<T, N> { 39impl<'a, T: Instance<Regs = crate::pac::adc::Adc>, const N: usize> Drop for InjectedAdc<'a, T, N> {
40 fn drop(&mut self) { 40 fn drop(&mut self) {
41 T::stop(); 41 T::regs().stop();
42 compiler_fence(Ordering::SeqCst); 42 compiler_fence(Ordering::SeqCst);
43 } 43 }
44} 44}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 6d53d9b91..a6af1175a 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -25,12 +25,18 @@ use core::marker::PhantomData;
25#[allow(unused)] 25#[allow(unused)]
26#[cfg(not(any(adc_f3v3, adc_wba)))] 26#[cfg(not(any(adc_f3v3, adc_wba)))]
27pub use _version::*; 27pub use _version::*;
28use embassy_hal_internal::{PeripheralType, impl_peripheral}; 28#[allow(unused)]
29use embassy_hal_internal::PeripheralType;
29#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] 30#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
30use embassy_sync::waitqueue::AtomicWaker; 31use embassy_sync::waitqueue::AtomicWaker;
31#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))] 32#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
32pub use ringbuffered::RingBufferedAdc; 33pub use ringbuffered::RingBufferedAdc;
33 34
35#[cfg(adc_u5)]
36use crate::pac::adc::vals::Adc4SampleTime;
37#[cfg(adc_wba)]
38use crate::pac::adc::vals::SampleTime as Adc4SampleTime;
39
34#[cfg(any(adc_u5, adc_wba))] 40#[cfg(any(adc_u5, adc_wba))]
35#[path = "adc4.rs"] 41#[path = "adc4.rs"]
36pub mod adc4; 42pub mod adc4;
@@ -43,10 +49,10 @@ pub use crate::pac::adc::vals::Res as Resolution;
43pub use crate::pac::adc::vals::SampleTime; 49pub use crate::pac::adc::vals::SampleTime;
44use crate::peripherals; 50use crate::peripherals;
45 51
46dma_trait!(RxDma, AnyInstance); 52dma_trait!(RxDma, Instance);
47 53
48/// Analog to Digital driver. 54/// Analog to Digital driver.
49pub struct Adc<'d, T: AnyInstance> { 55pub struct Adc<'d, T: Instance> {
50 #[allow(unused)] 56 #[allow(unused)]
51 adc: crate::Peri<'d, T>, 57 adc: crate::Peri<'d, T>,
52} 58}
@@ -65,79 +71,72 @@ impl State {
65 } 71 }
66} 72}
67 73
68trait SealedInstance { 74#[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
69 #[cfg(not(adc_wba))] 75trait_set::trait_set! {
70 #[allow(unused)] 76 pub trait DefaultInstance = Instance;
71 fn regs() -> crate::pac::adc::Adc;
72 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0)))]
73 #[allow(unused)]
74 fn common_regs() -> crate::pac::adccommon::AdcCommon;
75 #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
76 fn state() -> &'static State;
77} 77}
78 78
79pub(crate) trait SealedAdcChannel<T> { 79#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_g4, adc_c0))]
80 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 80trait_set::trait_set! {
81 fn setup(&mut self) {} 81 pub trait DefaultInstance = Instance<Regs = crate::pac::adc::Adc>;
82
83 #[allow(unused)]
84 fn channel(&self) -> u8;
85
86 #[allow(unused)]
87 fn is_differential(&self) -> bool {
88 false
89 }
90} 82}
91 83
92// Temporary patch for ADCs that have not implemented the standard iface yet 84#[cfg(adc_wba)]
93#[cfg(any(adc_v1, adc_l0, adc_f1, adc_f3v1, adc_f3v2, adc_f3v3, adc_v1))]
94trait_set::trait_set! { 85trait_set::trait_set! {
95 pub trait AnyInstance = Instance; 86 pub trait DefaultInstance = Instance<Regs = crate::pac::adc::Adc4>;
96} 87}
97 88
98#[cfg(any( 89pub trait BasicAdcRegs {
99 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
100))]
101pub trait BasicAnyInstance {
102 type SampleTime; 90 type SampleTime;
103} 91}
104 92
105#[cfg(any( 93#[cfg(any(
106 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0 94 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
107))] 95))]
108pub(self) trait SealedAnyInstance: BasicAnyInstance { 96trait AdcRegs: BasicAdcRegs {
109 fn enable(); 97 fn enable(&self);
110 fn start(); 98 fn start(&self);
111 fn stop(); 99 fn stop(&self);
112 fn convert() -> u16; 100 fn convert(&self);
113 fn configure_dma(conversion_mode: ConversionMode); 101 fn configure_dma(&self, conversion_mode: ConversionMode);
114 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>); 102 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>);
115 #[allow(dead_code)] 103 fn data(&self) -> *mut u16;
116 fn dr() -> *mut u16;
117} 104}
118 105
119// On chips without ADC4, AnyInstance is an Instance
120#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_g4, adc_c0))]
121#[allow(private_bounds)] 106#[allow(private_bounds)]
122pub trait AnyInstance: SealedAnyInstance + Instance {} 107pub trait BasicInstance {
123 108 #[cfg(any(
124// On chips with ADC4, AnyInstance is an Instance or adc4::Instance 109 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
125#[cfg(any(adc_v4, adc_u5, adc_wba))] 110 ))]
126#[allow(private_bounds)] 111 type Regs: AdcRegs;
127pub trait AnyInstance: SealedAnyInstance + crate::PeripheralType + crate::rcc::RccPeripheral {} 112}
128 113
129// Implement AnyInstance automatically for SealedAnyInstance 114trait SealedInstance: BasicInstance {
130#[cfg(any( 115 #[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
131 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0 116 fn regs() -> crate::pac::adc::Adc;
132))] 117 #[cfg(any(
133impl<T: SealedAnyInstance + Instance> BasicAnyInstance for T { 118 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
134 type SampleTime = SampleTime; 119 ))]
120 fn regs() -> Self::Regs;
121 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0)))]
122 #[allow(unused)]
123 fn common_regs() -> crate::pac::adccommon::AdcCommon;
124 #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
125 fn state() -> &'static State;
135} 126}
136 127
137#[cfg(any( 128pub(crate) trait SealedAdcChannel<T> {
138 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0 129 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
139))] 130 fn setup(&mut self) {}
140impl<T: SealedAnyInstance + Instance> AnyInstance for T {} 131
132 #[allow(unused)]
133 fn channel(&self) -> u8;
134
135 #[allow(unused)]
136 fn is_differential(&self) -> bool {
137 false
138 }
139}
141 140
142#[cfg(any(adc_c0, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))] 141#[cfg(any(adc_c0, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))]
143/// Number of samples used for averaging. 142/// Number of samples used for averaging.
@@ -183,28 +182,33 @@ pub enum RegularConversionMode {
183 Triggered(ConversionTrigger), 182 Triggered(ConversionTrigger),
184} 183}
185 184
186impl<'d, T: AnyInstance> Adc<'d, T> { 185impl<'d, T: Instance> Adc<'d, T> {
187 #[cfg(any( 186 #[cfg(any(
188 adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u5, adc_v4, adc_wba, adc_c0 187 adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u5, adc_v3, adc_v4, adc_wba, adc_c0
189 ))] 188 ))]
190 /// Read an ADC pin. 189 /// Read an ADC pin.
191 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: T::SampleTime) -> u16 { 190 pub fn blocking_read(
192 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 191 &mut self,
192 channel: &mut impl AdcChannel<T>,
193 sample_time: <T::Regs as BasicAdcRegs>::SampleTime,
194 ) -> u16 {
195 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
193 channel.setup(); 196 channel.setup();
194 197
195 // Ensure no conversions are ongoing 198 // Ensure no conversions are ongoing
196 T::stop(); 199 T::regs().stop();
197 #[cfg(any(adc_v2, adc_v3, adc_g0, adc_h7rs, adc_u0, adc_u5, adc_wba, adc_c0))] 200 #[cfg(any(adc_v2, adc_v3, adc_g0, adc_h7rs, adc_u0, adc_u5, adc_wba, adc_c0))]
198 T::enable(); 201 T::regs().enable();
199 T::configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter()); 202 T::regs().configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter());
200 203
201 // On chips with differential channels, enable after configure_sequence to allow setting differential channels 204 // On chips with differential channels, enable after configure_sequence to allow setting differential channels
202 // 205 //
203 // TODO: If hardware allows, enable after configure_sequence on all chips 206 // TODO: If hardware allows, enable after configure_sequence on all chips
204 #[cfg(any(adc_g4, adc_h5))] 207 #[cfg(any(adc_g4, adc_h5))]
205 T::enable(); 208 T::regs().enable();
209 T::regs().convert();
206 210
207 T::convert() 211 unsafe { *T::regs().data() }
208 } 212 }
209 213
210 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))] 214 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
@@ -241,10 +245,10 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
241 /// in order or require the sequence to have the same sample time for all channnels, depending 245 /// in order or require the sequence to have the same sample time for all channnels, depending
242 /// on the number and properties of the channels in the sequence. This method will panic if 246 /// on the number and properties of the channels in the sequence. This method will panic if
243 /// the hardware cannot deliver the requested configuration. 247 /// the hardware cannot deliver the requested configuration.
244 pub async fn read( 248 pub async fn read<'a, 'b: 'a>(
245 &mut self, 249 &mut self,
246 rx_dma: embassy_hal_internal::Peri<'_, impl RxDma<T>>, 250 rx_dma: embassy_hal_internal::Peri<'_, impl RxDma<T>>,
247 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, T::SampleTime)>, 251 sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<'b, T>, <T::Regs as BasicAdcRegs>::SampleTime)>,
248 readings: &mut [u16], 252 readings: &mut [u16],
249 ) { 253 ) {
250 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); 254 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
@@ -258,11 +262,11 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
258 ); 262 );
259 263
260 // Ensure no conversions are ongoing 264 // Ensure no conversions are ongoing
261 T::stop(); 265 T::regs().stop();
262 #[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))] 266 #[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
263 T::enable(); 267 T::regs().enable();
264 268
265 T::configure_sequence( 269 T::regs().configure_sequence(
266 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)), 270 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
267 ); 271 );
268 272
@@ -270,20 +274,20 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
270 // 274 //
271 // TODO: If hardware allows, enable after configure_sequence on all chips 275 // TODO: If hardware allows, enable after configure_sequence on all chips
272 #[cfg(any(adc_g4, adc_h5))] 276 #[cfg(any(adc_g4, adc_h5))]
273 T::enable(); 277 T::regs().enable();
274 T::configure_dma(ConversionMode::Singular); 278 T::regs().configure_dma(ConversionMode::Singular);
275 279
276 let request = rx_dma.request(); 280 let request = rx_dma.request();
277 let transfer = 281 let transfer =
278 unsafe { crate::dma::Transfer::new_read(rx_dma, request, T::dr(), readings, Default::default()) }; 282 unsafe { crate::dma::Transfer::new_read(rx_dma, request, T::regs().data(), readings, Default::default()) };
279 283
280 T::start(); 284 T::regs().start();
281 285
282 // Wait for conversion sequence to finish. 286 // Wait for conversion sequence to finish.
283 transfer.await; 287 transfer.await;
284 288
285 // Ensure conversions are finished. 289 // Ensure conversions are finished.
286 T::stop(); 290 T::regs().stop();
287 } 291 }
288 292
289 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))] 293 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
@@ -313,11 +317,11 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
313 /// in order or require the sequence to have the same sample time for all channnels, depending 317 /// in order or require the sequence to have the same sample time for all channnels, depending
314 /// on the number and properties of the channels in the sequence. This method will panic if 318 /// on the number and properties of the channels in the sequence. This method will panic if
315 /// the hardware cannot deliver the requested configuration. 319 /// the hardware cannot deliver the requested configuration.
316 pub fn into_ring_buffered<'a>( 320 pub fn into_ring_buffered<'a, 'b>(
317 self, 321 self,
318 dma: embassy_hal_internal::Peri<'a, impl RxDma<T>>, 322 dma: embassy_hal_internal::Peri<'a, impl RxDma<T>>,
319 dma_buf: &'a mut [u16], 323 dma_buf: &'a mut [u16],
320 sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, T::SampleTime)>, 324 sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<'b, T>, <T::Regs as BasicAdcRegs>::SampleTime)>,
321 mode: RegularConversionMode, 325 mode: RegularConversionMode,
322 ) -> RingBufferedAdc<'a, T> { 326 ) -> RingBufferedAdc<'a, T> {
323 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); 327 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
@@ -327,11 +331,11 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
327 "Asynchronous read sequence cannot be more than 16 in length" 331 "Asynchronous read sequence cannot be more than 16 in length"
328 ); 332 );
329 // Ensure no conversions are ongoing 333 // Ensure no conversions are ongoing
330 T::stop(); 334 T::regs().stop();
331 #[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))] 335 #[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
332 T::enable(); 336 T::regs().enable();
333 337
334 T::configure_sequence( 338 T::regs().configure_sequence(
335 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)), 339 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
336 ); 340 );
337 341
@@ -339,8 +343,8 @@ impl<'d, T: AnyInstance> Adc<'d, T> {
339 // 343 //
340 // TODO: If hardware allows, enable after configure_sequence on all chips 344 // TODO: If hardware allows, enable after configure_sequence on all chips
341 #[cfg(any(adc_g4, adc_h5))] 345 #[cfg(any(adc_g4, adc_h5))]
342 T::enable(); 346 T::regs().enable();
343 T::configure_dma(ConversionMode::Repeated(mode)); 347 T::regs().configure_dma(ConversionMode::Repeated(mode));
344 348
345 core::mem::forget(self); 349 core::mem::forget(self);
346 350
@@ -417,8 +421,11 @@ pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeri
417#[allow(private_bounds)] 421#[allow(private_bounds)]
418pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized { 422pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
419 #[allow(unused_mut)] 423 #[allow(unused_mut)]
420 fn degrade_adc(mut self) -> AnyAdcChannel<T> { 424 fn degrade_adc<'a>(mut self) -> AnyAdcChannel<'a, T>
421 #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 425 where
426 Self: 'a,
427 {
428 #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
422 self.setup(); 429 self.setup();
423 430
424 AnyAdcChannel { 431 AnyAdcChannel {
@@ -433,14 +440,13 @@ pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
433/// 440///
434/// This is useful in scenarios where you need the ADC channels to have the same type, such as 441/// This is useful in scenarios where you need the ADC channels to have the same type, such as
435/// storing them in an array. 442/// storing them in an array.
436pub struct AnyAdcChannel<T> { 443pub struct AnyAdcChannel<'a, T> {
437 channel: u8, 444 channel: u8,
438 is_differential: bool, 445 is_differential: bool,
439 _phantom: PhantomData<T>, 446 _phantom: PhantomData<&'a mut T>,
440} 447}
441impl_peripheral!(AnyAdcChannel<T: AnyInstance>); 448impl<T: Instance> AdcChannel<T> for AnyAdcChannel<'_, T> {}
442impl<T: AnyInstance> AdcChannel<T> for AnyAdcChannel<T> {} 449impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<'_, T> {
443impl<T: AnyInstance> SealedAdcChannel<T> for AnyAdcChannel<T> {
444 fn channel(&self) -> u8 { 450 fn channel(&self) -> u8 {
445 self.channel 451 self.channel
446 } 452 }
@@ -450,22 +456,41 @@ impl<T: AnyInstance> SealedAdcChannel<T> for AnyAdcChannel<T> {
450 } 456 }
451} 457}
452 458
453impl<T> AnyAdcChannel<T> { 459impl<T> AnyAdcChannel<'_, T> {
454 #[allow(unused)] 460 #[allow(unused)]
455 pub fn get_hw_channel(&self) -> u8 { 461 pub fn get_hw_channel(&self) -> u8 {
456 self.channel 462 self.channel
457 } 463 }
458} 464}
465
466#[cfg(not(adc_wba))]
467impl BasicAdcRegs for crate::pac::adc::Adc {
468 type SampleTime = SampleTime;
469}
470
471#[cfg(any(adc_wba, adc_u5))]
472impl BasicAdcRegs for crate::pac::adc::Adc4 {
473 type SampleTime = Adc4SampleTime;
474}
475
459#[cfg(adc_wba)] 476#[cfg(adc_wba)]
460foreach_adc!( 477foreach_adc!(
461 (ADC4, $common_inst:ident, $clock:ident) => { 478 (ADC4, $common_inst:ident, $clock:ident) => {
462 impl crate::adc::adc4::SealedInstance for peripherals::ADC4 { 479 impl crate::adc::BasicInstance for peripherals::ADC4 {
463 fn regs() -> crate::pac::adc::Adc4 { 480 type Regs = crate::pac::adc::Adc4;
481 }
482
483 impl crate::adc::SealedInstance for peripherals::ADC4 {
484 fn regs() -> Self::Regs {
464 crate::pac::ADC4 485 crate::pac::ADC4
465 } 486 }
487
488 fn common_regs() -> crate::pac::adccommon::AdcCommon {
489 return crate::pac::$common_inst
490 }
466 } 491 }
467 492
468 impl crate::adc::adc4::Instance for peripherals::ADC4 { 493 impl crate::adc::Instance for peripherals::ADC4 {
469 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL; 494 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
470 } 495 }
471 }; 496 };
@@ -490,20 +515,32 @@ foreach_adc!(
490#[cfg(adc_u5)] 515#[cfg(adc_u5)]
491foreach_adc!( 516foreach_adc!(
492 (ADC4, $common_inst:ident, $clock:ident) => { 517 (ADC4, $common_inst:ident, $clock:ident) => {
493 impl crate::adc::adc4::SealedInstance for peripherals::ADC4 { 518 impl crate::adc::BasicInstance for peripherals::ADC4 {
494 fn regs() -> crate::pac::adc::Adc4 { 519 type Regs = crate::pac::adc::Adc4;
520 }
521
522 impl crate::adc::SealedInstance for peripherals::ADC4 {
523 fn regs() -> Self::Regs {
495 crate::pac::ADC4 524 crate::pac::ADC4
496 } 525 }
526
527 fn common_regs() -> crate::pac::adccommon::AdcCommon {
528 return crate::pac::$common_inst
529 }
497 } 530 }
498 531
499 impl crate::adc::adc4::Instance for peripherals::ADC4 { 532 impl crate::adc::Instance for peripherals::ADC4 {
500 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL; 533 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
501 } 534 }
502 }; 535 };
503 536
504 ($inst:ident, $common_inst:ident, $clock:ident) => { 537 ($inst:ident, $common_inst:ident, $clock:ident) => {
538 impl crate::adc::BasicInstance for peripherals::$inst {
539 type Regs = crate::pac::adc::Adc;
540 }
541
505 impl crate::adc::SealedInstance for peripherals::$inst { 542 impl crate::adc::SealedInstance for peripherals::$inst {
506 fn regs() -> crate::pac::adc::Adc { 543 fn regs() -> Self::Regs {
507 crate::pac::$inst 544 crate::pac::$inst
508 } 545 }
509 546
@@ -521,14 +558,23 @@ foreach_adc!(
521#[cfg(not(any(adc_u5, adc_wba)))] 558#[cfg(not(any(adc_u5, adc_wba)))]
522foreach_adc!( 559foreach_adc!(
523 ($inst:ident, $common_inst:ident, $clock:ident) => { 560 ($inst:ident, $common_inst:ident, $clock:ident) => {
561 impl crate::adc::BasicInstance for peripherals::$inst {
562 #[cfg(any(
563 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
564 ))]
565 type Regs = crate::pac::adc::Adc;
566 }
567
524 impl crate::adc::SealedInstance for peripherals::$inst { 568 impl crate::adc::SealedInstance for peripherals::$inst {
525 #[cfg(not(adc_wba))] 569 #[cfg(any(
526 fn regs() -> crate::pac::adc::Adc { 570 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
571 ))]
572 fn regs() -> Self::Regs {
527 crate::pac::$inst 573 crate::pac::$inst
528 } 574 }
529 575
530 #[cfg(adc_wba)] 576 #[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
531 fn regs() -> crate::pac::adc::Adc4 { 577 fn regs() -> crate::pac::adc::Adc {
532 crate::pac::$inst 578 crate::pac::$inst
533 } 579 }
534 580
@@ -554,7 +600,7 @@ macro_rules! impl_adc_pin {
554 ($inst:ident, $pin:ident, $ch:expr) => { 600 ($inst:ident, $pin:ident, $ch:expr) => {
555 impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {} 601 impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {}
556 impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> { 602 impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {
557 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 603 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
558 fn setup(&mut self) { 604 fn setup(&mut self) {
559 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self); 605 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self);
560 } 606 }
@@ -582,7 +628,7 @@ macro_rules! impl_adc_pair {
582 crate::Peri<'_, crate::peripherals::$npin>, 628 crate::Peri<'_, crate::peripherals::$npin>,
583 ) 629 )
584 { 630 {
585 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 631 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
586 fn setup(&mut self) { 632 fn setup(&mut self) {
587 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(&mut self.0); 633 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(&mut self.0);
588 <crate::peripherals::$npin as crate::gpio::SealedPin>::set_as_analog(&mut self.1); 634 <crate::peripherals::$npin as crate::gpio::SealedPin>::set_as_analog(&mut self.1);
diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs
index 5437866d3..242a1a89c 100644
--- a/embassy-stm32/src/adc/ringbuffered.rs
+++ b/embassy-stm32/src/adc/ringbuffered.rs
@@ -4,7 +4,7 @@ use core::sync::atomic::{Ordering, compiler_fence};
4#[allow(unused_imports)] 4#[allow(unused_imports)]
5use embassy_hal_internal::Peri; 5use embassy_hal_internal::Peri;
6 6
7use crate::adc::AnyInstance; 7use super::AdcRegs;
8#[allow(unused_imports)] 8#[allow(unused_imports)]
9use crate::adc::{Instance, RxDma}; 9use crate::adc::{Instance, RxDma};
10#[allow(unused_imports)] 10#[allow(unused_imports)]
@@ -19,7 +19,7 @@ pub struct RingBufferedAdc<'d, T: Instance> {
19 ring_buf: ReadableRingBuffer<'d, u16>, 19 ring_buf: ReadableRingBuffer<'d, u16>,
20} 20}
21 21
22impl<'d, T: Instance + AnyInstance> RingBufferedAdc<'d, T> { 22impl<'d, T: Instance> RingBufferedAdc<'d, T> {
23 pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self { 23 pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self {
24 //dma side setup 24 //dma side setup
25 let opts = TransferOptions { 25 let opts = TransferOptions {
@@ -31,8 +31,7 @@ impl<'d, T: Instance + AnyInstance> RingBufferedAdc<'d, T> {
31 // Safety: we forget the struct before this function returns. 31 // Safety: we forget the struct before this function returns.
32 let request = dma.request(); 32 let request = dma.request();
33 33
34 let ring_buf = 34 let ring_buf = unsafe { ReadableRingBuffer::new(dma, request, T::regs().data(), dma_buf, opts) };
35 unsafe { ReadableRingBuffer::new(dma, request, T::regs().dr().as_ptr() as *mut u16, dma_buf, opts) };
36 35
37 Self { 36 Self {
38 _phantom: PhantomData, 37 _phantom: PhantomData,
@@ -45,7 +44,7 @@ impl<'d, T: Instance + AnyInstance> RingBufferedAdc<'d, T> {
45 compiler_fence(Ordering::SeqCst); 44 compiler_fence(Ordering::SeqCst);
46 self.ring_buf.start(); 45 self.ring_buf.start();
47 46
48 T::start(); 47 T::regs().start();
49 } 48 }
50 49
51 pub fn stop(&mut self) { 50 pub fn stop(&mut self) {
@@ -117,15 +116,15 @@ impl<'d, T: Instance + AnyInstance> RingBufferedAdc<'d, T> {
117 self.start(); 116 self.start();
118 } 117 }
119 118
120 #[cfg(adc_v2)] 119 // #[cfg(adc_v2)]
121 { 120 // {
122 // Clear overrun flag if set. 121 // // Clear overrun flag if set.
123 if T::regs().sr().read().ovr() { 122 // if T::regs().sr().read().ovr() {
124 self.stop(); 123 // self.stop();
125 124 //
126 return Err(OverrunError); 125 // return Err(OverrunError);
127 } 126 // }
128 } 127 // }
129 128
130 self.ring_buf.read_exact(measurements).await.map_err(|_| OverrunError) 129 self.ring_buf.read_exact(measurements).await.map_err(|_| OverrunError)
131 } 130 }
@@ -143,15 +142,16 @@ impl<'d, T: Instance + AnyInstance> RingBufferedAdc<'d, T> {
143 self.start(); 142 self.start();
144 } 143 }
145 144
146 #[cfg(adc_v2)] 145 // #[cfg(adc_v2)]
147 { 146 // {
148 // Clear overrun flag if set. 147 // // Clear overrun flag if set.
149 if T::regs().sr().read().ovr() { 148 // if T::regs().sr().read().ovr() {
150 self.stop(); 149 // self.stop();
150 //
151 // return Err(OverrunError);
152 // }
153 // }
151 154
152 return Err(OverrunError);
153 }
154 }
155 loop { 155 loop {
156 match self.ring_buf.read(buf) { 156 match self.ring_buf.read(buf) {
157 Ok((0, _)) => {} 157 Ok((0, _)) => {}
@@ -168,9 +168,9 @@ impl<'d, T: Instance + AnyInstance> RingBufferedAdc<'d, T> {
168 } 168 }
169} 169}
170 170
171impl<T: Instance + AnyInstance> Drop for RingBufferedAdc<'_, T> { 171impl<T: Instance> Drop for RingBufferedAdc<'_, T> {
172 fn drop(&mut self) { 172 fn drop(&mut self) {
173 T::stop(); 173 T::regs().stop();
174 174
175 compiler_fence(Ordering::SeqCst); 175 compiler_fence(Ordering::SeqCst);
176 176
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 3c4431ae0..b026383d5 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -1,7 +1,7 @@
1use core::sync::atomic::{Ordering, compiler_fence}; 1use core::sync::atomic::{Ordering, compiler_fence};
2 2
3use super::{ConversionMode, Temperature, Vbat, VrefInt, blocking_delay_us}; 3use super::{ConversionMode, Temperature, Vbat, VrefInt, blocking_delay_us};
4use crate::adc::{Adc, Instance, Resolution, SampleTime}; 4use crate::adc::{Adc, AdcRegs, Instance, Resolution, SampleTime};
5use crate::pac::adc::vals; 5use crate::pac::adc::vals;
6pub use crate::pac::adccommon::vals::Adcpre; 6pub use crate::pac::adccommon::vals::Adcpre;
7use crate::time::Hertz; 7use crate::time::Hertz;
@@ -71,31 +71,31 @@ fn from_pclk2(freq: Hertz) -> Adcpre {
71/// ADC configuration 71/// ADC configuration
72#[derive(Default)] 72#[derive(Default)]
73pub struct AdcConfig { 73pub struct AdcConfig {
74 resolution: Option<Resolution>, 74 pub resolution: Option<Resolution>,
75} 75}
76 76
77impl<T: Instance> super::SealedAnyInstance for T { 77impl super::AdcRegs for crate::pac::adc::Adc {
78 fn dr() -> *mut u16 { 78 fn data(&self) -> *mut u16 {
79 T::regs().dr().as_ptr() as *mut u16 79 crate::pac::adc::Adc::dr(*self).as_ptr() as *mut u16
80 } 80 }
81 81
82 fn enable() { 82 fn enable(&self) {
83 T::regs().cr2().modify(|reg| { 83 self.cr2().modify(|reg| {
84 reg.set_adon(true); 84 reg.set_adon(true);
85 }); 85 });
86 86
87 blocking_delay_us(3); 87 blocking_delay_us(3);
88 } 88 }
89 89
90 fn start() { 90 fn start(&self) {
91 // Begin ADC conversions 91 // Begin ADC conversions
92 T::regs().cr2().modify(|reg| { 92 self.cr2().modify(|reg| {
93 reg.set_swstart(true); 93 reg.set_swstart(true);
94 }); 94 });
95 } 95 }
96 96
97 fn stop() { 97 fn stop(&self) {
98 let r = T::regs(); 98 let r = self;
99 99
100 // Stop ADC 100 // Stop ADC
101 r.cr2().modify(|reg| { 101 r.cr2().modify(|reg| {
@@ -114,36 +114,34 @@ impl<T: Instance> super::SealedAnyInstance for T {
114 w.set_ovrie(false); 114 w.set_ovrie(false);
115 }); 115 });
116 116
117 clear_interrupt_flags(r); 117 clear_interrupt_flags(*r);
118 118
119 compiler_fence(Ordering::SeqCst); 119 compiler_fence(Ordering::SeqCst);
120 } 120 }
121 121
122 fn convert() -> u16 { 122 fn convert(&self) {
123 // clear end of conversion flag 123 // clear end of conversion flag
124 T::regs().sr().modify(|reg| { 124 self.sr().modify(|reg| {
125 reg.set_eoc(false); 125 reg.set_eoc(false);
126 }); 126 });
127 127
128 // Start conversion 128 // Start conversion
129 T::regs().cr2().modify(|reg| { 129 self.cr2().modify(|reg| {
130 reg.set_swstart(true); 130 reg.set_swstart(true);
131 }); 131 });
132 132
133 while T::regs().sr().read().strt() == false { 133 while self.sr().read().strt() == false {
134 // spin //wait for actual start 134 // spin //wait for actual start
135 } 135 }
136 while T::regs().sr().read().eoc() == false { 136 while self.sr().read().eoc() == false {
137 // spin //wait for finish 137 // spin //wait for finish
138 } 138 }
139
140 T::regs().dr().read().0 as u16
141 } 139 }
142 140
143 fn configure_dma(conversion_mode: ConversionMode) { 141 fn configure_dma(&self, conversion_mode: ConversionMode) {
144 match conversion_mode { 142 match conversion_mode {
145 ConversionMode::Repeated(_) => { 143 ConversionMode::Repeated(_) => {
146 let r = T::regs(); 144 let r = self;
147 145
148 // Clear all interrupts 146 // Clear all interrupts
149 r.sr().modify(|regs| { 147 r.sr().modify(|regs| {
@@ -177,25 +175,25 @@ impl<T: Instance> super::SealedAnyInstance for T {
177 } 175 }
178 } 176 }
179 177
180 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 178 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
181 T::regs().cr2().modify(|reg| { 179 self.cr2().modify(|reg| {
182 reg.set_adon(true); 180 reg.set_adon(true);
183 }); 181 });
184 182
185 // Check the sequence is long enough 183 // Check the sequence is long enough
186 T::regs().sqr1().modify(|r| { 184 self.sqr1().modify(|r| {
187 r.set_l((sequence.len() - 1).try_into().unwrap()); 185 r.set_l((sequence.len() - 1).try_into().unwrap());
188 }); 186 });
189 187
190 for (i, ((ch, _), sample_time)) in sequence.enumerate() { 188 for (i, ((ch, _), sample_time)) in sequence.enumerate() {
191 // Set the channel in the right sequence field. 189 // Set the channel in the right sequence field.
192 T::regs().sqr3().modify(|w| w.set_sq(i, ch)); 190 self.sqr3().modify(|w| w.set_sq(i, ch));
193 191
194 let sample_time = sample_time.into(); 192 let sample_time = sample_time.into();
195 if ch <= 9 { 193 if ch <= 9 {
196 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); 194 self.smpr2().modify(|reg| reg.set_smp(ch as _, sample_time));
197 } else { 195 } else {
198 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); 196 self.smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
199 } 197 }
200 } 198 }
201 } 199 }
@@ -203,7 +201,7 @@ impl<T: Instance> super::SealedAnyInstance for T {
203 201
204impl<'d, T> Adc<'d, T> 202impl<'d, T> Adc<'d, T>
205where 203where
206 T: Instance + super::AnyInstance, 204 T: Instance<Regs = crate::pac::adc::Adc>,
207{ 205{
208 pub fn new(adc: Peri<'d, T>) -> Self { 206 pub fn new(adc: Peri<'d, T>) -> Self {
209 Self::new_with_config(adc, Default::default()) 207 Self::new_with_config(adc, Default::default())
@@ -214,7 +212,7 @@ where
214 212
215 let presc = from_pclk2(T::frequency()); 213 let presc = from_pclk2(T::frequency());
216 T::common_regs().ccr().modify(|w| w.set_adcpre(presc)); 214 T::common_regs().ccr().modify(|w| w.set_adcpre(presc));
217 T::enable(); 215 T::regs().enable();
218 216
219 if let Some(resolution) = config.resolution { 217 if let Some(resolution) = config.resolution {
220 T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); 218 T::regs().cr1().modify(|reg| reg.set_res(resolution.into()));
@@ -259,9 +257,7 @@ where
259 257
260impl<'d, T: Instance> Drop for Adc<'d, T> { 258impl<'d, T: Instance> Drop for Adc<'d, T> {
261 fn drop(&mut self) { 259 fn drop(&mut self) {
262 T::regs().cr2().modify(|reg| { 260 T::regs().stop();
263 reg.set_adon(false);
264 });
265 261
266 rcc::disable::<T>(); 262 rcc::disable::<T>();
267 } 263 }
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index b270588c4..9cc44aa9a 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -146,63 +146,63 @@ pub struct AdcConfig {
146 pub averaging: Option<Averaging>, 146 pub averaging: Option<Averaging>,
147} 147}
148 148
149impl<T: Instance> super::SealedAnyInstance for T { 149impl super::AdcRegs for crate::pac::adc::Adc {
150 fn dr() -> *mut u16 { 150 fn data(&self) -> *mut u16 {
151 T::regs().dr().as_ptr() as *mut u16 151 crate::pac::adc::Adc::dr(*self).as_ptr() as *mut u16
152 } 152 }
153 153
154 // Enable ADC only when it is not already running. 154 // Enable ADC only when it is not already running.
155 fn enable() { 155 fn enable(&self) {
156 // Make sure bits are off 156 // Make sure bits are off
157 while T::regs().cr().read().addis() { 157 while self.cr().read().addis() {
158 // spin 158 // spin
159 } 159 }
160 160
161 if !T::regs().cr().read().aden() { 161 if !self.cr().read().aden() {
162 // Enable ADC 162 // Enable ADC
163 T::regs().isr().modify(|reg| { 163 self.isr().modify(|reg| {
164 reg.set_adrdy(true); 164 reg.set_adrdy(true);
165 }); 165 });
166 T::regs().cr().modify(|reg| { 166 self.cr().modify(|reg| {
167 reg.set_aden(true); 167 reg.set_aden(true);
168 }); 168 });
169 169
170 while !T::regs().isr().read().adrdy() { 170 while !self.isr().read().adrdy() {
171 // spin 171 // spin
172 } 172 }
173 } 173 }
174 } 174 }
175 175
176 fn start() { 176 fn start(&self) {
177 T::regs().cr().modify(|reg| { 177 self.cr().modify(|reg| {
178 reg.set_adstart(true); 178 reg.set_adstart(true);
179 }); 179 });
180 } 180 }
181 181
182 fn stop() { 182 fn stop(&self) {
183 // Ensure conversions are finished. 183 // Ensure conversions are finished.
184 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 184 if self.cr().read().adstart() && !self.cr().read().addis() {
185 T::regs().cr().modify(|reg| { 185 self.cr().modify(|reg| {
186 reg.set_adstp(true); 186 reg.set_adstp(true);
187 }); 187 });
188 while T::regs().cr().read().adstart() {} 188 while self.cr().read().adstart() {}
189 } 189 }
190 190
191 // Reset configuration. 191 // Reset configuration.
192 #[cfg(not(any(adc_g0, adc_u0)))] 192 #[cfg(not(any(adc_g0, adc_u0)))]
193 T::regs().cfgr().modify(|reg| { 193 self.cfgr().modify(|reg| {
194 reg.set_cont(false); 194 reg.set_cont(false);
195 reg.set_dmaen(false); 195 reg.set_dmaen(false);
196 }); 196 });
197 #[cfg(any(adc_g0, adc_u0))] 197 #[cfg(any(adc_g0, adc_u0))]
198 T::regs().cfgr1().modify(|reg| { 198 self.cfgr1().modify(|reg| {
199 reg.set_cont(false); 199 reg.set_cont(false);
200 reg.set_dmaen(false); 200 reg.set_dmaen(false);
201 }); 201 });
202 } 202 }
203 203
204 /// Perform a single conversion. 204 /// Perform a single conversion.
205 fn convert() -> u16 { 205 fn convert(&self) {
206 // Some models are affected by an erratum: 206 // Some models are affected by an erratum:
207 // If we perform conversions slower than 1 kHz, the first read ADC value can be 207 // If we perform conversions slower than 1 kHz, the first read ADC value can be
208 // corrupted, so we discard it and measure again. 208 // corrupted, so we discard it and measure again.
@@ -216,36 +216,34 @@ impl<T: Instance> super::SealedAnyInstance for T {
216 let len = 1; 216 let len = 1;
217 217
218 for _ in 0..len { 218 for _ in 0..len {
219 T::regs().isr().modify(|reg| { 219 self.isr().modify(|reg| {
220 reg.set_eos(true); 220 reg.set_eos(true);
221 reg.set_eoc(true); 221 reg.set_eoc(true);
222 }); 222 });
223 223
224 // Start conversion 224 // Start conversion
225 T::regs().cr().modify(|reg| { 225 self.cr().modify(|reg| {
226 reg.set_adstart(true); 226 reg.set_adstart(true);
227 }); 227 });
228 228
229 while !T::regs().isr().read().eos() { 229 while !self.isr().read().eos() {
230 // spin 230 // spin
231 } 231 }
232 } 232 }
233
234 T::regs().dr().read().0 as u16
235 } 233 }
236 234
237 fn configure_dma(conversion_mode: ConversionMode) { 235 fn configure_dma(&self, conversion_mode: ConversionMode) {
238 // Set continuous mode with oneshot dma. 236 // Set continuous mode with oneshot dma.
239 // Clear overrun flag before starting transfer. 237 // Clear overrun flag before starting transfer.
240 T::regs().isr().modify(|reg| { 238 self.isr().modify(|reg| {
241 reg.set_ovr(true); 239 reg.set_ovr(true);
242 }); 240 });
243 241
244 #[cfg(not(any(adc_g0, adc_u0)))] 242 #[cfg(not(any(adc_g0, adc_u0)))]
245 let regs = T::regs().cfgr(); 243 let regs = self.cfgr();
246 244
247 #[cfg(any(adc_g0, adc_u0))] 245 #[cfg(any(adc_g0, adc_u0))]
248 let regs = T::regs().cfgr1(); 246 let regs = self.cfgr1();
249 247
250 regs.modify(|reg| { 248 regs.modify(|reg| {
251 reg.set_discen(false); 249 reg.set_discen(false);
@@ -259,13 +257,13 @@ impl<T: Instance> super::SealedAnyInstance for T {
259 }); 257 });
260 } 258 }
261 259
262 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 260 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
263 #[cfg(adc_h5)] 261 #[cfg(adc_h5)]
264 T::regs().cr().modify(|w| w.set_aden(false)); 262 self.cr().modify(|w| w.set_aden(false));
265 263
266 // Set sequence length 264 // Set sequence length
267 #[cfg(not(any(adc_g0, adc_u0)))] 265 #[cfg(not(any(adc_g0, adc_u0)))]
268 T::regs().sqr1().modify(|w| { 266 self.sqr1().modify(|w| {
269 w.set_l(sequence.len() as u8 - 1); 267 w.set_l(sequence.len() as u8 - 1);
270 }); 268 });
271 269
@@ -273,8 +271,8 @@ impl<T: Instance> super::SealedAnyInstance for T {
273 { 271 {
274 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new(); 272 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new();
275 273
276 T::regs().chselr().write(|chselr| { 274 self.chselr().write(|chselr| {
277 T::regs().smpr().write(|smpr| { 275 self.smpr().write(|smpr| {
278 for ((channel, _), sample_time) in sequence { 276 for ((channel, _), sample_time) in sequence {
279 chselr.set_chsel(channel.into(), true); 277 chselr.set_chsel(channel.into(), true);
280 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) { 278 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) {
@@ -306,22 +304,22 @@ impl<T: Instance> super::SealedAnyInstance for T {
306 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected." 304 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
307 #[cfg(any(adc_h5, adc_h7rs))] 305 #[cfg(any(adc_h5, adc_h7rs))]
308 if channel == 0 { 306 if channel == 0 {
309 T::regs().or().modify(|reg| reg.set_op0(true)); 307 self.or().modify(|reg| reg.set_op0(true));
310 } 308 }
311 309
312 // Configure channel 310 // Configure channel
313 cfg_if! { 311 cfg_if! {
314 if #[cfg(adc_u0)] { 312 if #[cfg(adc_u0)] {
315 // On G0 and U6 all channels use the same sampling time. 313 // On G0 and U6 all channels use the same sampling time.
316 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); 314 self.smpr().modify(|reg| reg.set_smp1(sample_time.into()));
317 } else if #[cfg(any(adc_h5, adc_h7rs))] { 315 } else if #[cfg(any(adc_h5, adc_h7rs))] {
318 match channel { 316 match channel {
319 0..=9 => T::regs().smpr1().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())), 317 0..=9 => self.smpr1().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())),
320 _ => T::regs().smpr2().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())), 318 _ => self.smpr2().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())),
321 } 319 }
322 } else { 320 } else {
323 let sample_time = sample_time.into(); 321 let sample_time = sample_time.into();
324 T::regs() 322 self
325 .smpr(channel as usize / 10) 323 .smpr(channel as usize / 10)
326 .modify(|reg| reg.set_smp(channel as usize % 10, sample_time)); 324 .modify(|reg| reg.set_smp(channel as usize % 10, sample_time));
327 } 325 }
@@ -331,9 +329,8 @@ impl<T: Instance> super::SealedAnyInstance for T {
331 { 329 {
332 use crate::pac::adc::vals::Pcsel; 330 use crate::pac::adc::vals::Pcsel;
333 331
334 T::regs().cfgr2().modify(|w| w.set_lshift(0)); 332 self.cfgr2().modify(|w| w.set_lshift(0));
335 T::regs() 333 self.pcsel()
336 .pcsel()
337 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED)); 334 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED));
338 } 335 }
339 336
@@ -341,22 +338,22 @@ impl<T: Instance> super::SealedAnyInstance for T {
341 #[cfg(not(any(adc_g0, adc_u0)))] 338 #[cfg(not(any(adc_g0, adc_u0)))]
342 match _i { 339 match _i {
343 0..=3 => { 340 0..=3 => {
344 T::regs().sqr1().modify(|w| { 341 self.sqr1().modify(|w| {
345 w.set_sq(_i, channel); 342 w.set_sq(_i, channel);
346 }); 343 });
347 } 344 }
348 4..=8 => { 345 4..=8 => {
349 T::regs().sqr2().modify(|w| { 346 self.sqr2().modify(|w| {
350 w.set_sq(_i - 4, channel); 347 w.set_sq(_i - 4, channel);
351 }); 348 });
352 } 349 }
353 9..=13 => { 350 9..=13 => {
354 T::regs().sqr3().modify(|w| { 351 self.sqr3().modify(|w| {
355 w.set_sq(_i - 9, channel); 352 w.set_sq(_i - 9, channel);
356 }); 353 });
357 } 354 }
358 14..=15 => { 355 14..=15 => {
359 T::regs().sqr4().modify(|w| { 356 self.sqr4().modify(|w| {
360 w.set_sq(_i - 14, channel); 357 w.set_sq(_i - 14, channel);
361 }); 358 });
362 } 359 }
@@ -375,20 +372,20 @@ impl<T: Instance> super::SealedAnyInstance for T {
375 } 372 }
376 373
377 #[cfg(adc_h5)] 374 #[cfg(adc_h5)]
378 T::regs().difsel().write(|w| w.set_difsel(difsel)); 375 self.difsel().write(|w| w.set_difsel(difsel));
379 376
380 // On G0 and U0 enabled channels are sampled from 0 to last channel. 377 // On G0 and U0 enabled channels are sampled from 0 to last channel.
381 // It is possible to add up to 8 sequences if CHSELRMOD = 1. 378 // It is possible to add up to 8 sequences if CHSELRMOD = 1.
382 // However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used. 379 // However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used.
383 #[cfg(adc_u0)] 380 #[cfg(adc_u0)]
384 T::regs().chselr().modify(|reg| { 381 self.chselr().modify(|reg| {
385 reg.set_chsel(channel_mask); 382 reg.set_chsel(channel_mask);
386 }); 383 });
387 } 384 }
388 } 385 }
389} 386}
390 387
391impl<'d, T: Instance> Adc<'d, T> { 388impl<'d, T: Instance<Regs = crate::pac::adc::Adc>> Adc<'d, T> {
392 /// Enable the voltage regulator 389 /// Enable the voltage regulator
393 fn init_regulator() { 390 fn init_regulator() {
394 rcc::enable_and_reset::<T>(); 391 rcc::enable_and_reset::<T>();
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index a3d9e6176..09fc2ab22 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -5,7 +5,7 @@ use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel};
5use pac::adccommon::vals::Presc; 5use pac::adccommon::vals::Presc;
6 6
7use super::{Adc, Averaging, Instance, Resolution, SampleTime, Temperature, Vbat, VrefInt, blocking_delay_us}; 7use super::{Adc, Averaging, Instance, Resolution, SampleTime, Temperature, Vbat, VrefInt, blocking_delay_us};
8use crate::adc::ConversionMode; 8use crate::adc::{AdcRegs, ConversionMode};
9use crate::time::Hertz; 9use crate::time::Hertz;
10use crate::{Peri, pac, rcc}; 10use crate::{Peri, pac, rcc};
11 11
@@ -80,65 +80,63 @@ pub struct AdcConfig {
80 pub averaging: Option<Averaging>, 80 pub averaging: Option<Averaging>,
81} 81}
82 82
83impl<T: Instance> super::SealedAnyInstance for T { 83impl AdcRegs for crate::pac::adc::Adc {
84 fn dr() -> *mut u16 { 84 fn data(&self) -> *mut u16 {
85 T::regs().dr().as_ptr() as *mut u16 85 crate::pac::adc::Adc::dr(*self).as_ptr() as *mut u16
86 } 86 }
87 87
88 fn enable() { 88 fn enable(&self) {
89 T::regs().isr().write(|w| w.set_adrdy(true)); 89 self.isr().write(|w| w.set_adrdy(true));
90 T::regs().cr().modify(|w| w.set_aden(true)); 90 self.cr().modify(|w| w.set_aden(true));
91 while !T::regs().isr().read().adrdy() {} 91 while !self.isr().read().adrdy() {}
92 T::regs().isr().write(|w| w.set_adrdy(true)); 92 self.isr().write(|w| w.set_adrdy(true));
93 } 93 }
94 94
95 fn start() { 95 fn start(&self) {
96 // Start conversion 96 // Start conversion
97 T::regs().cr().modify(|reg| { 97 self.cr().modify(|reg| {
98 reg.set_adstart(true); 98 reg.set_adstart(true);
99 }); 99 });
100 } 100 }
101 101
102 fn stop() { 102 fn stop(&self) {
103 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 103 if self.cr().read().adstart() && !self.cr().read().addis() {
104 T::regs().cr().modify(|reg| { 104 self.cr().modify(|reg| {
105 reg.set_adstp(Adstp::STOP); 105 reg.set_adstp(Adstp::STOP);
106 }); 106 });
107 while T::regs().cr().read().adstart() {} 107 while self.cr().read().adstart() {}
108 } 108 }
109 109
110 // Reset configuration. 110 // Reset configuration.
111 T::regs().cfgr().modify(|reg| { 111 self.cfgr().modify(|reg| {
112 reg.set_cont(false); 112 reg.set_cont(false);
113 reg.set_dmngt(Dmngt::from_bits(0)); 113 reg.set_dmngt(Dmngt::from_bits(0));
114 }); 114 });
115 } 115 }
116 116
117 fn convert() -> u16 { 117 fn convert(&self) {
118 T::regs().isr().modify(|reg| { 118 self.isr().modify(|reg| {
119 reg.set_eos(true); 119 reg.set_eos(true);
120 reg.set_eoc(true); 120 reg.set_eoc(true);
121 }); 121 });
122 122
123 // Start conversion 123 // Start conversion
124 T::regs().cr().modify(|reg| { 124 self.cr().modify(|reg| {
125 reg.set_adstart(true); 125 reg.set_adstart(true);
126 }); 126 });
127 127
128 while !T::regs().isr().read().eos() { 128 while !self.isr().read().eos() {
129 // spin 129 // spin
130 } 130 }
131
132 T::regs().dr().read().0 as u16
133 } 131 }
134 132
135 fn configure_dma(conversion_mode: ConversionMode) { 133 fn configure_dma(&self, conversion_mode: ConversionMode) {
136 match conversion_mode { 134 match conversion_mode {
137 ConversionMode::Singular => { 135 ConversionMode::Singular => {
138 T::regs().isr().modify(|reg| { 136 self.isr().modify(|reg| {
139 reg.set_ovr(true); 137 reg.set_ovr(true);
140 }); 138 });
141 T::regs().cfgr().modify(|reg| { 139 self.cfgr().modify(|reg| {
142 reg.set_cont(true); 140 reg.set_cont(true);
143 reg.set_dmngt(Dmngt::DMA_ONE_SHOT); 141 reg.set_dmngt(Dmngt::DMA_ONE_SHOT);
144 }); 142 });
@@ -148,9 +146,9 @@ impl<T: Instance> super::SealedAnyInstance for T {
148 } 146 }
149 } 147 }
150 148
151 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 149 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
152 // Set sequence length 150 // Set sequence length
153 T::regs().sqr1().modify(|w| { 151 self.sqr1().modify(|w| {
154 w.set_l(sequence.len() as u8 - 1); 152 w.set_l(sequence.len() as u8 - 1);
155 }); 153 });
156 154
@@ -158,39 +156,35 @@ impl<T: Instance> super::SealedAnyInstance for T {
158 for (i, ((channel, _), sample_time)) in sequence.enumerate() { 156 for (i, ((channel, _), sample_time)) in sequence.enumerate() {
159 let sample_time = sample_time.into(); 157 let sample_time = sample_time.into();
160 if channel <= 9 { 158 if channel <= 9 {
161 T::regs().smpr(0).modify(|reg| reg.set_smp(channel as _, sample_time)); 159 self.smpr(0).modify(|reg| reg.set_smp(channel as _, sample_time));
162 } else { 160 } else {
163 T::regs() 161 self.smpr(1).modify(|reg| reg.set_smp((channel - 10) as _, sample_time));
164 .smpr(1)
165 .modify(|reg| reg.set_smp((channel - 10) as _, sample_time));
166 } 162 }
167 163
168 #[cfg(any(stm32h7, stm32u5))] 164 #[cfg(any(stm32h7, stm32u5))]
169 { 165 {
170 T::regs().cfgr2().modify(|w| w.set_lshift(0)); 166 self.cfgr2().modify(|w| w.set_lshift(0));
171 T::regs() 167 self.pcsel().modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
172 .pcsel()
173 .modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
174 } 168 }
175 169
176 match i { 170 match i {
177 0..=3 => { 171 0..=3 => {
178 T::regs().sqr1().modify(|w| { 172 self.sqr1().modify(|w| {
179 w.set_sq(i, channel); 173 w.set_sq(i, channel);
180 }); 174 });
181 } 175 }
182 4..=8 => { 176 4..=8 => {
183 T::regs().sqr2().modify(|w| { 177 self.sqr2().modify(|w| {
184 w.set_sq(i - 4, channel); 178 w.set_sq(i - 4, channel);
185 }); 179 });
186 } 180 }
187 9..=13 => { 181 9..=13 => {
188 T::regs().sqr3().modify(|w| { 182 self.sqr3().modify(|w| {
189 w.set_sq(i - 9, channel); 183 w.set_sq(i - 9, channel);
190 }); 184 });
191 } 185 }
192 14..=15 => { 186 14..=15 => {
193 T::regs().sqr4().modify(|w| { 187 self.sqr4().modify(|w| {
194 w.set_sq(i - 14, channel); 188 w.set_sq(i - 14, channel);
195 }); 189 });
196 } 190 }
@@ -200,7 +194,7 @@ impl<T: Instance> super::SealedAnyInstance for T {
200 } 194 }
201} 195}
202 196
203impl<'d, T: Instance + super::AnyInstance> Adc<'d, T> { 197impl<'d, T: Instance<Regs = crate::pac::adc::Adc>> Adc<'d, T> {
204 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self { 198 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
205 let s = Self::new(adc); 199 let s = Self::new(adc);
206 200
@@ -292,7 +286,7 @@ impl<'d, T: Instance + super::AnyInstance> Adc<'d, T> {
292 286
293 blocking_delay_us(1); 287 blocking_delay_us(1);
294 288
295 T::enable(); 289 T::regs().enable();
296 290
297 // single conversion mode, software trigger 291 // single conversion mode, software trigger
298 T::regs().cfgr().modify(|w| { 292 T::regs().cfgr().modify(|w| {
diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs
index bfd0570f8..afb18ec1a 100644
--- a/embassy-stm32/src/dma/gpdma/mod.rs
+++ b/embassy-stm32/src/dma/gpdma/mod.rs
@@ -137,7 +137,6 @@ pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: c
137 137
138impl AnyChannel { 138impl AnyChannel {
139 /// Safety: Must be called with a matching set of parameters for a valid dma channel 139 /// Safety: Must be called with a matching set of parameters for a valid dma channel
140 #[cfg(not(stm32n6))]
141 pub(crate) unsafe fn on_irq(&self) { 140 pub(crate) unsafe fn on_irq(&self) {
142 let info = self.info(); 141 let info = self.info();
143 #[cfg(feature = "_dual-core")] 142 #[cfg(feature = "_dual-core")]
@@ -238,6 +237,11 @@ impl AnyChannel {
238 // "Preceding reads and writes cannot be moved past subsequent writes." 237 // "Preceding reads and writes cannot be moved past subsequent writes."
239 fence(Ordering::SeqCst); 238 fence(Ordering::SeqCst);
240 239
240 if ch.cr().read().en() {
241 ch.cr().modify(|w| w.set_susp(true));
242 while !ch.sr().read().suspf() {}
243 }
244
241 ch.cr().write(|w| w.set_reset(true)); 245 ch.cr().write(|w| w.set_reset(true));
242 ch.fcr().write(|w| { 246 ch.fcr().write(|w| {
243 // Clear all irqs 247 // Clear all irqs
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index efb324fa6..05d9c2e51 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -25,7 +25,7 @@ pub(crate) use util::*;
25pub(crate) mod ringbuffer; 25pub(crate) mod ringbuffer;
26pub mod word; 26pub mod word;
27 27
28use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral}; 28use embassy_hal_internal::{PeripheralType, impl_peripheral};
29 29
30use crate::interrupt; 30use crate::interrupt;
31use crate::rcc::StoppablePeripheral; 31use crate::rcc::StoppablePeripheral;
@@ -47,21 +47,10 @@ pub type Request = u8;
47#[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))] 47#[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))]
48pub type Request = (); 48pub type Request = ();
49 49
50impl<'a> StoppablePeripheral for Peri<'a, AnyChannel> { 50pub(crate) trait SealedChannel: StoppablePeripheral {
51 #[cfg(feature = "low-power")]
52 fn stop_mode(&self) -> crate::rcc::StopMode {
53 self.stop_mode
54 }
55}
56
57pub(crate) trait SealedChannel {
58 #[cfg(not(stm32n6))]
59 fn id(&self) -> u8; 51 fn id(&self) -> u8;
60 #[cfg(feature = "low-power")]
61 fn stop_mode(&self) -> crate::rcc::StopMode;
62} 52}
63 53
64#[cfg(not(stm32n6))]
65pub(crate) trait ChannelInterrupt { 54pub(crate) trait ChannelInterrupt {
66 #[cfg_attr(not(feature = "rt"), allow(unused))] 55 #[cfg_attr(not(feature = "rt"), allow(unused))]
67 unsafe fn on_irq(); 56 unsafe fn on_irq();
@@ -71,19 +60,21 @@ pub(crate) trait ChannelInterrupt {
71#[allow(private_bounds)] 60#[allow(private_bounds)]
72pub trait Channel: SealedChannel + PeripheralType + Into<AnyChannel> + 'static {} 61pub trait Channel: SealedChannel + PeripheralType + Into<AnyChannel> + 'static {}
73 62
74#[cfg(not(stm32n6))]
75macro_rules! dma_channel_impl { 63macro_rules! dma_channel_impl {
76 ($channel_peri:ident, $index:expr, $stop_mode:ident) => { 64 ($channel_peri:ident, $index:expr, $stop_mode:ident) => {
77 impl crate::dma::SealedChannel for crate::peripherals::$channel_peri { 65 impl crate::rcc::StoppablePeripheral for crate::peripherals::$channel_peri {
78 fn id(&self) -> u8 {
79 $index
80 }
81
82 #[cfg(feature = "low-power")] 66 #[cfg(feature = "low-power")]
83 fn stop_mode(&self) -> crate::rcc::StopMode { 67 fn stop_mode(&self) -> crate::rcc::StopMode {
84 crate::rcc::StopMode::$stop_mode 68 crate::rcc::StopMode::$stop_mode
85 } 69 }
86 } 70 }
71
72 impl crate::dma::SealedChannel for crate::peripherals::$channel_peri {
73 fn id(&self) -> u8 {
74 $index
75 }
76 }
77
87 impl crate::dma::ChannelInterrupt for crate::peripherals::$channel_peri { 78 impl crate::dma::ChannelInterrupt for crate::peripherals::$channel_peri {
88 unsafe fn on_irq() { 79 unsafe fn on_irq() {
89 crate::dma::AnyChannel { 80 crate::dma::AnyChannel {
@@ -102,7 +93,7 @@ macro_rules! dma_channel_impl {
102 Self { 93 Self {
103 id: crate::dma::SealedChannel::id(&val), 94 id: crate::dma::SealedChannel::id(&val),
104 #[cfg(feature = "low-power")] 95 #[cfg(feature = "low-power")]
105 stop_mode: crate::dma::SealedChannel::stop_mode(&val), 96 stop_mode: crate::rcc::StoppablePeripheral::stop_mode(&val),
106 } 97 }
107 } 98 }
108 } 99 }
@@ -123,17 +114,18 @@ impl AnyChannel {
123 } 114 }
124} 115}
125 116
126impl SealedChannel for AnyChannel { 117impl StoppablePeripheral for AnyChannel {
127 #[cfg(not(stm32n6))]
128 fn id(&self) -> u8 {
129 self.id
130 }
131
132 #[cfg(feature = "low-power")] 118 #[cfg(feature = "low-power")]
133 fn stop_mode(&self) -> crate::rcc::StopMode { 119 fn stop_mode(&self) -> crate::rcc::StopMode {
134 self.stop_mode 120 self.stop_mode
135 } 121 }
136} 122}
123
124impl SealedChannel for AnyChannel {
125 fn id(&self) -> u8 {
126 self.id
127 }
128}
137impl Channel for AnyChannel {} 129impl Channel for AnyChannel {}
138 130
139const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len(); 131const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len();
diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs
index 3245887c1..304268963 100644
--- a/embassy-stm32/src/dma/util.rs
+++ b/embassy-stm32/src/dma/util.rs
@@ -20,6 +20,16 @@ impl<'d> ChannelAndRequest<'d> {
20 Transfer::new_read(self.channel.reborrow(), self.request, peri_addr, buf, options) 20 Transfer::new_read(self.channel.reborrow(), self.request, peri_addr, buf, options)
21 } 21 }
22 22
23 #[allow(dead_code)]
24 pub unsafe fn read_unchecked<'a, W: Word>(
25 &'a self,
26 peri_addr: *mut W,
27 buf: &'a mut [W],
28 options: TransferOptions,
29 ) -> Transfer<'a> {
30 Transfer::new_read(self.channel.clone_unchecked(), self.request, peri_addr, buf, options)
31 }
32
23 pub unsafe fn read_raw<'a, MW: Word, PW: Word>( 33 pub unsafe fn read_raw<'a, MW: Word, PW: Word>(
24 &'a mut self, 34 &'a mut self,
25 peri_addr: *mut PW, 35 peri_addr: *mut PW,
@@ -29,6 +39,16 @@ impl<'d> ChannelAndRequest<'d> {
29 Transfer::new_read_raw(self.channel.reborrow(), self.request, peri_addr, buf, options) 39 Transfer::new_read_raw(self.channel.reborrow(), self.request, peri_addr, buf, options)
30 } 40 }
31 41
42 #[allow(dead_code)]
43 pub unsafe fn read_raw_unchecked<'a, MW: Word, PW: Word>(
44 &'a self,
45 peri_addr: *mut PW,
46 buf: *mut [MW],
47 options: TransferOptions,
48 ) -> Transfer<'a> {
49 Transfer::new_read_raw(self.channel.clone_unchecked(), self.request, peri_addr, buf, options)
50 }
51
32 pub unsafe fn write<'a, W: Word>( 52 pub unsafe fn write<'a, W: Word>(
33 &'a mut self, 53 &'a mut self,
34 buf: &'a [W], 54 buf: &'a [W],
@@ -38,6 +58,16 @@ impl<'d> ChannelAndRequest<'d> {
38 Transfer::new_write(self.channel.reborrow(), self.request, buf, peri_addr, options) 58 Transfer::new_write(self.channel.reborrow(), self.request, buf, peri_addr, options)
39 } 59 }
40 60
61 #[allow(dead_code)]
62 pub unsafe fn write_unchecked<'a, W: Word>(
63 &'a self,
64 buf: &'a [W],
65 peri_addr: *mut W,
66 options: TransferOptions,
67 ) -> Transfer<'a> {
68 Transfer::new_write(self.channel.clone_unchecked(), self.request, buf, peri_addr, options)
69 }
70
41 pub unsafe fn write_raw<'a, MW: Word, PW: Word>( 71 pub unsafe fn write_raw<'a, MW: Word, PW: Word>(
42 &'a mut self, 72 &'a mut self,
43 buf: *const [MW], 73 buf: *const [MW],
@@ -48,6 +78,16 @@ impl<'d> ChannelAndRequest<'d> {
48 } 78 }
49 79
50 #[allow(dead_code)] 80 #[allow(dead_code)]
81 pub unsafe fn write_raw_unchecked<'a, MW: Word, PW: Word>(
82 &'a self,
83 buf: *const [MW],
84 peri_addr: *mut PW,
85 options: TransferOptions,
86 ) -> Transfer<'a> {
87 Transfer::new_write_raw(self.channel.clone_unchecked(), self.request, buf, peri_addr, options)
88 }
89
90 #[allow(dead_code)]
51 pub unsafe fn write_repeated<'a, W: Word>( 91 pub unsafe fn write_repeated<'a, W: Word>(
52 &'a mut self, 92 &'a mut self,
53 repeated: &'a W, 93 repeated: &'a W,
@@ -64,4 +104,22 @@ impl<'d> ChannelAndRequest<'d> {
64 options, 104 options,
65 ) 105 )
66 } 106 }
107
108 #[allow(dead_code)]
109 pub unsafe fn write_repeated_unchecked<'a, W: Word>(
110 &'a self,
111 repeated: &'a W,
112 count: usize,
113 peri_addr: *mut W,
114 options: TransferOptions,
115 ) -> Transfer<'a> {
116 Transfer::new_write_repeated(
117 self.channel.clone_unchecked(),
118 self.request,
119 repeated,
120 count,
121 peri_addr,
122 options,
123 )
124 }
67} 125}
diff --git a/embassy-stm32/src/dma/word.rs b/embassy-stm32/src/dma/word.rs
index fb1bde860..5c3bb8f7f 100644
--- a/embassy-stm32/src/dma/word.rs
+++ b/embassy-stm32/src/dma/word.rs
@@ -31,6 +31,10 @@ pub trait Word: SealedWord + Default + Copy + 'static {
31 fn size() -> WordSize; 31 fn size() -> WordSize;
32 /// Amount of bits of this word size. 32 /// Amount of bits of this word size.
33 fn bits() -> usize; 33 fn bits() -> usize;
34 /// Maximum value of this type.
35 fn max() -> usize {
36 (1 << Self::bits()) - 1
37 }
34} 38}
35 39
36macro_rules! impl_word { 40macro_rules! impl_word {
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 7b7896d46..458174b5d 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -74,7 +74,7 @@ unsafe fn on_irq() {
74 } 74 }
75 75
76 #[cfg(feature = "low-power")] 76 #[cfg(feature = "low-power")]
77 crate::low_power::Executor::on_wakeup_irq(); 77 crate::low_power::Executor::on_wakeup_irq_or_event();
78} 78}
79 79
80struct BitIter(u32); 80struct BitIter(u32);
diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs
index b6ae24ee8..b731796f0 100644
--- a/embassy-stm32/src/fmt.rs
+++ b/embassy-stm32/src/fmt.rs
@@ -207,6 +207,16 @@ macro_rules! error {
207} 207}
208 208
209#[cfg(feature = "defmt")] 209#[cfg(feature = "defmt")]
210trait_set::trait_set! {
211 pub trait Debuggable = Debug + defmt::Format;
212}
213
214#[cfg(not(feature = "defmt"))]
215trait_set::trait_set! {
216 pub trait Debuggable = Debug;
217}
218
219#[cfg(feature = "defmt")]
210#[collapse_debuginfo(yes)] 220#[collapse_debuginfo(yes)]
211macro_rules! unwrap { 221macro_rules! unwrap {
212 ($($x:tt)*) => { 222 ($($x:tt)*) => {
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index e7d4e9ad3..5de8bad2c 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -684,7 +684,11 @@ fn set_as_analog(pin_port: PinNumber) {
684 }); 684 });
685 685
686 #[cfg(gpio_v2)] 686 #[cfg(gpio_v2)]
687 r.moder().modify(|w| w.set_moder(n, vals::Moder::ANALOG)); 687 {
688 #[cfg(any(stm32l47x, stm32l48x))]
689 r.ascr().modify(|w| w.set_asc(n, true));
690 r.moder().modify(|w| w.set_moder(n, vals::Moder::ANALOG));
691 }
688} 692}
689 693
690#[inline(never)] 694#[inline(never)]
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index ee60c3f44..0bf430ffc 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -226,7 +226,7 @@ impl<'d, M: Mode> I2c<'d, M, Master> {
226 } 226 }
227 227
228 fn enable_and_init(&mut self, config: Config) { 228 fn enable_and_init(&mut self, config: Config) {
229 self.info.rcc.enable_and_reset(); 229 self.info.rcc.enable_and_reset_without_stop();
230 self.init(config); 230 self.init(config);
231 } 231 }
232} 232}
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 128a58db7..81a6d74c1 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -529,6 +529,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
529 529
530 /// Write. 530 /// Write.
531 pub async fn write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> { 531 pub async fn write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> {
532 let _scoped_block_stop = self.info.rcc.block_stop();
532 self.write_frame(address, write_buffer, FrameOptions::FirstAndLastFrame) 533 self.write_frame(address, write_buffer, FrameOptions::FirstAndLastFrame)
533 .await?; 534 .await?;
534 535
@@ -537,6 +538,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
537 538
538 /// Read. 539 /// Read.
539 pub async fn read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> { 540 pub async fn read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> {
541 let _scoped_block_stop = self.info.rcc.block_stop();
540 self.read_frame(address, read_buffer, FrameOptions::FirstAndLastFrame) 542 self.read_frame(address, read_buffer, FrameOptions::FirstAndLastFrame)
541 .await?; 543 .await?;
542 544
@@ -701,6 +703,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
701 703
702 /// Write, restart, read. 704 /// Write, restart, read.
703 pub async fn write_read(&mut self, address: u8, write_buffer: &[u8], read_buffer: &mut [u8]) -> Result<(), Error> { 705 pub async fn write_read(&mut self, address: u8, write_buffer: &[u8], read_buffer: &mut [u8]) -> Result<(), Error> {
706 let _scoped_block_stop = self.info.rcc.block_stop();
704 // Check empty read buffer before starting transaction. Otherwise, we would not generate the 707 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
705 // stop condition below. 708 // stop condition below.
706 if read_buffer.is_empty() { 709 if read_buffer.is_empty() {
@@ -719,6 +722,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
719 /// 722 ///
720 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 723 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
721 pub async fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 724 pub async fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
725 let _scoped_block_stop = self.info.rcc.block_stop();
722 for (op, frame) in operation_frames(operations)? { 726 for (op, frame) in operation_frames(operations)? {
723 match op { 727 match op {
724 Operation::Read(read_buffer) => self.read_frame(address, read_buffer, frame).await?, 728 Operation::Read(read_buffer) => self.read_frame(address, read_buffer, frame).await?,
@@ -1357,6 +1361,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1357 /// (Read/Write) and the matched address. This method will suspend until 1361 /// (Read/Write) and the matched address. This method will suspend until
1358 /// an address match occurs. 1362 /// an address match occurs.
1359 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> { 1363 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> {
1364 let _scoped_block_stop = self.info.rcc.block_stop();
1360 trace!("I2C slave: starting async listen for address match"); 1365 trace!("I2C slave: starting async listen for address match");
1361 let state = self.state; 1366 let state = self.state;
1362 let info = self.info; 1367 let info = self.info;
@@ -1421,6 +1426,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1421 /// 1426 ///
1422 /// Returns the number of bytes stored in the buffer (not total received). 1427 /// Returns the number of bytes stored in the buffer (not total received).
1423 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 1428 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
1429 let _scoped_block_stop = self.info.rcc.block_stop();
1424 trace!("I2C slave: starting respond_to_write, buffer_len={}", buffer.len()); 1430 trace!("I2C slave: starting respond_to_write, buffer_len={}", buffer.len());
1425 1431
1426 if buffer.is_empty() { 1432 if buffer.is_empty() {
@@ -1454,6 +1460,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1454 /// 1460 ///
1455 /// Returns the total number of bytes transmitted (data + padding). 1461 /// Returns the total number of bytes transmitted (data + padding).
1456 pub async fn respond_to_read(&mut self, data: &[u8]) -> Result<usize, Error> { 1462 pub async fn respond_to_read(&mut self, data: &[u8]) -> Result<usize, Error> {
1463 let _scoped_block_stop = self.info.rcc.block_stop();
1457 trace!("I2C slave: starting respond_to_read, data_len={}", data.len()); 1464 trace!("I2C slave: starting respond_to_read, data_len={}", data.len());
1458 1465
1459 if data.is_empty() { 1466 if data.is_empty() {
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 933cca9cb..fe7782a7c 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -73,7 +73,7 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
73 // restore the clocks to their last configured state as 73 // restore the clocks to their last configured state as
74 // much is lost in STOP modes 74 // much is lost in STOP modes
75 #[cfg(all(feature = "low-power", stm32wlex))] 75 #[cfg(all(feature = "low-power", stm32wlex))]
76 crate::low_power::Executor::on_wakeup_irq(); 76 crate::low_power::Executor::on_wakeup_irq_or_event();
77 77
78 let regs = T::info().regs; 78 let regs = T::info().regs;
79 let isr = regs.isr().read(); 79 let isr = regs.isr().read();
@@ -1075,6 +1075,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
1075 1075
1076 /// Write. 1076 /// Write.
1077 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 1077 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
1078 let _scoped_block_stop = self.info.rcc.block_stop();
1078 let timeout = self.timeout(); 1079 let timeout = self.timeout();
1079 if write.is_empty() { 1080 if write.is_empty() {
1080 self.write_internal(address.into(), write, true, timeout) 1081 self.write_internal(address.into(), write, true, timeout)
@@ -1089,6 +1090,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
1089 /// 1090 ///
1090 /// The buffers are concatenated in a single write transaction. 1091 /// The buffers are concatenated in a single write transaction.
1091 pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { 1092 pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> {
1093 let _scoped_block_stop = self.info.rcc.block_stop();
1092 let timeout = self.timeout(); 1094 let timeout = self.timeout();
1093 1095
1094 if write.is_empty() { 1096 if write.is_empty() {
@@ -1120,6 +1122,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
1120 1122
1121 /// Read. 1123 /// Read.
1122 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 1124 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
1125 let _scoped_block_stop = self.info.rcc.block_stop();
1123 let timeout = self.timeout(); 1126 let timeout = self.timeout();
1124 1127
1125 if buffer.is_empty() { 1128 if buffer.is_empty() {
@@ -1132,6 +1135,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
1132 1135
1133 /// Write, restart, read. 1136 /// Write, restart, read.
1134 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 1137 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
1138 let _scoped_block_stop = self.info.rcc.block_stop();
1135 let timeout = self.timeout(); 1139 let timeout = self.timeout();
1136 1140
1137 if write.is_empty() { 1141 if write.is_empty() {
@@ -1157,6 +1161,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
1157 /// 1161 ///
1158 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 1162 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
1159 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 1163 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
1164 let _scoped_block_stop = self.info.rcc.block_stop();
1160 if operations.is_empty() { 1165 if operations.is_empty() {
1161 return Err(Error::ZeroLengthTransfer); 1166 return Err(Error::ZeroLengthTransfer);
1162 } 1167 }
@@ -1741,6 +1746,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1741 /// 1746 ///
1742 /// The listen method is an asynchronous method but it does not require DMA to be asynchronous. 1747 /// The listen method is an asynchronous method but it does not require DMA to be asynchronous.
1743 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> { 1748 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> {
1749 let _scoped_block_stop = self.info.rcc.block_stop();
1744 let state = self.state; 1750 let state = self.state;
1745 self.info.regs.cr1().modify(|reg| { 1751 self.info.regs.cr1().modify(|reg| {
1746 reg.set_addrie(true); 1752 reg.set_addrie(true);
@@ -1766,12 +1772,14 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1766 /// 1772 ///
1767 /// Returns the total number of bytes received. 1773 /// Returns the total number of bytes received.
1768 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 1774 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
1775 let _scoped_block_stop = self.info.rcc.block_stop();
1769 let timeout = self.timeout(); 1776 let timeout = self.timeout();
1770 timeout.with(self.read_dma_internal_slave(buffer, timeout)).await 1777 timeout.with(self.read_dma_internal_slave(buffer, timeout)).await
1771 } 1778 }
1772 1779
1773 /// Respond to a read request from an I2C master. 1780 /// Respond to a read request from an I2C master.
1774 pub async fn respond_to_read(&mut self, write: &[u8]) -> Result<SendStatus, Error> { 1781 pub async fn respond_to_read(&mut self, write: &[u8]) -> Result<SendStatus, Error> {
1782 let _scoped_block_stop = self.info.rcc.block_stop();
1775 let timeout = self.timeout(); 1783 let timeout = self.timeout();
1776 timeout.with(self.write_dma_internal_slave(write, timeout)).await 1784 timeout.with(self.write_dma_internal_slave(write, timeout)).await
1777 } 1785 }
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index cdf3323fb..2388abe3c 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -88,7 +88,7 @@ foreach_interrupt! {
88 #[interrupt] 88 #[interrupt]
89 #[allow(non_snake_case)] 89 #[allow(non_snake_case)]
90 unsafe fn $irq() { 90 unsafe fn $irq() {
91 Executor::on_wakeup_irq(); 91 Executor::on_wakeup_irq_or_event();
92 } 92 }
93 }; 93 };
94} 94}
@@ -99,7 +99,7 @@ foreach_interrupt! {
99 #[interrupt] 99 #[interrupt]
100 #[allow(non_snake_case)] 100 #[allow(non_snake_case)]
101 unsafe fn $irq() { 101 unsafe fn $irq() {
102 Executor::on_wakeup_irq(); 102 Executor::on_wakeup_irq_or_event();
103 } 103 }
104 }; 104 };
105} 105}
@@ -164,22 +164,30 @@ impl Executor {
164 } 164 }
165 } 165 }
166 166
167 pub(crate) unsafe fn on_wakeup_irq() { 167 pub(crate) unsafe fn on_wakeup_irq_or_event() {
168 if !get_driver().is_stopped() {
169 return;
170 }
171
168 critical_section::with(|cs| { 172 critical_section::with(|cs| {
169 #[cfg(stm32wlex)] 173 #[cfg(stm32wlex)]
170 { 174 {
171 use crate::pac::rcc::vals::Sw; 175 let es = crate::pac::PWR.extscr().read();
172 use crate::pac::{PWR, RCC}; 176 match (es.c1stopf(), es.c1stop2f()) {
173 use crate::rcc::init as init_rcc; 177 (true, false) => debug!("low power: wake from STOP1"),
174 178 (false, true) => debug!("low power: wake from STOP2"),
175 let extscr = PWR.extscr().read(); 179 (true, true) => debug!("low power: wake from STOP1 and STOP2 ???"),
176 if extscr.c1stop2f() || extscr.c1stopf() { 180 (false, false) => trace!("low power: stop mode not entered"),
181 };
182 crate::pac::PWR.extscr().modify(|w| {
183 w.set_c1cssf(false);
184 });
185
186 if es.c1stop2f() || es.c1stopf() {
177 // when we wake from any stop mode we need to re-initialize the rcc 187 // when we wake from any stop mode we need to re-initialize the rcc
178 while RCC.cfgr().read().sws() != Sw::MSI {} 188 crate::rcc::init(RCC_CONFIG.unwrap());
179
180 init_rcc(RCC_CONFIG.unwrap());
181 189
182 if extscr.c1stop2f() { 190 if es.c1stop2f() {
183 // when we wake from STOP2, we need to re-initialize the time driver 191 // when we wake from STOP2, we need to re-initialize the time driver
184 get_driver().init_timer(cs); 192 get_driver().init_timer(cs);
185 // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer) 193 // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer)
@@ -190,7 +198,8 @@ impl Executor {
190 } 198 }
191 } 199 }
192 get_driver().resume_time(cs); 200 get_driver().resume_time(cs);
193 trace!("low power: resume"); 201
202 trace!("low power: resume time");
194 }); 203 });
195 } 204 }
196 205
@@ -201,10 +210,8 @@ impl Executor {
201 fn stop_mode(_cs: CriticalSection) -> Option<StopMode> { 210 fn stop_mode(_cs: CriticalSection) -> Option<StopMode> {
202 // We cannot enter standby because we will lose program state. 211 // We cannot enter standby because we will lose program state.
203 if unsafe { REFCOUNT_STOP2 == 0 && REFCOUNT_STOP1 == 0 } { 212 if unsafe { REFCOUNT_STOP2 == 0 && REFCOUNT_STOP1 == 0 } {
204 trace!("low power: stop 2");
205 Some(StopMode::Stop2) 213 Some(StopMode::Stop2)
206 } else if unsafe { REFCOUNT_STOP1 == 0 } { 214 } else if unsafe { REFCOUNT_STOP1 == 0 } {
207 trace!("low power: stop 1");
208 Some(StopMode::Stop1) 215 Some(StopMode::Stop1)
209 } else { 216 } else {
210 trace!("low power: not ready to stop (refcount_stop1: {})", unsafe { 217 trace!("low power: not ready to stop (refcount_stop1: {})", unsafe {
@@ -305,9 +312,11 @@ impl Executor {
305 get_driver().pause_time(cs).ok()?; 312 get_driver().pause_time(cs).ok()?;
306 self.configure_stop(cs, stop_mode).ok()?; 313 self.configure_stop(cs, stop_mode).ok()?;
307 314
308 Some(()) 315 Some(stop_mode)
309 }) 316 })
310 .map(|_| { 317 .map(|stop_mode| {
318 trace!("low power: enter stop: {}", stop_mode);
319
311 #[cfg(not(feature = "low-power-debug-with-sleep"))] 320 #[cfg(not(feature = "low-power-debug-with-sleep"))]
312 Self::get_scb().set_sleepdeep(); 321 Self::get_scb().set_sleepdeep();
313 }); 322 });
@@ -338,20 +347,10 @@ impl Executor {
338 unsafe { 347 unsafe {
339 self.inner.poll(); 348 self.inner.poll();
340 self.configure_pwr(); 349 self.configure_pwr();
350 #[cfg(feature = "defmt")]
351 defmt::flush();
341 asm!("wfe"); 352 asm!("wfe");
342 #[cfg(stm32wlex)] 353 Self::on_wakeup_irq_or_event();
343 {
344 let es = crate::pac::PWR.extscr().read();
345 match (es.c1stopf(), es.c1stop2f()) {
346 (true, false) => debug!("low power: wake from STOP1"),
347 (false, true) => debug!("low power: wake from STOP2"),
348 (true, true) => debug!("low power: wake from STOP1 and STOP2 ???"),
349 (false, false) => trace!("low power: stop mode not entered"),
350 };
351 crate::pac::PWR.extscr().modify(|w| {
352 w.set_c1cssf(false);
353 });
354 }
355 }; 354 };
356 } 355 }
357 } 356 }
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index bb4f4f1d0..1f47f4845 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -111,7 +111,7 @@ impl<'d, T: Instance, M: PeriMode> Qspi<'d, T, M> {
111 config: Config, 111 config: Config,
112 fsel: FlashSelection, 112 fsel: FlashSelection,
113 ) -> Self { 113 ) -> Self {
114 rcc::enable_and_reset::<T>(); 114 rcc::enable_and_reset_without_stop::<T>();
115 115
116 while T::REGS.sr().read().busy() {} 116 while T::REGS.sr().read().busy() {}
117 117
@@ -403,6 +403,7 @@ impl<'d, T: Instance> Qspi<'d, T, Async> {
403 403
404 /// Async read data, using DMA. 404 /// Async read data, using DMA.
405 pub async fn read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) { 405 pub async fn read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) {
406 let _scoped_block_stop = T::RCC_INFO.block_stop();
406 let transfer = self.start_read_transfer(transaction, buf); 407 let transfer = self.start_read_transfer(transaction, buf);
407 transfer.await; 408 transfer.await;
408 } 409 }
@@ -443,6 +444,7 @@ impl<'d, T: Instance> Qspi<'d, T, Async> {
443 444
444 /// Async write data, using DMA. 445 /// Async write data, using DMA.
445 pub async fn write_dma(&mut self, buf: &[u8], transaction: TransferConfig) { 446 pub async fn write_dma(&mut self, buf: &[u8], transaction: TransferConfig) {
447 let _scoped_block_stop = T::RCC_INFO.block_stop();
446 let transfer = self.start_write_transfer(transaction, buf); 448 let transfer = self.start_write_transfer(transaction, buf);
447 transfer.await; 449 transfer.await;
448 } 450 }
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 1dd634cfe..2a9a1595a 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -12,6 +12,7 @@ pub use bd::*;
12#[cfg(any(mco, mco1, mco2))] 12#[cfg(any(mco, mco1, mco2))]
13mod mco; 13mod mco;
14use critical_section::CriticalSection; 14use critical_section::CriticalSection;
15use embassy_hal_internal::{Peri, PeripheralType};
15#[cfg(any(mco, mco1, mco2))] 16#[cfg(any(mco, mco1, mco2))]
16pub use mco::*; 17pub use mco::*;
17 18
@@ -172,7 +173,7 @@ pub(crate) struct RccInfo {
172/// E.g. if `StopMode::Stop1` is selected, the peripheral prevents the chip from entering Stop1 mode. 173/// E.g. if `StopMode::Stop1` is selected, the peripheral prevents the chip from entering Stop1 mode.
173#[cfg(feature = "low-power")] 174#[cfg(feature = "low-power")]
174#[allow(dead_code)] 175#[allow(dead_code)]
175#[derive(Debug, Clone, Copy, PartialEq, Default)] 176#[derive(Debug, Clone, Copy, PartialEq, Default, defmt::Format)]
176pub enum StopMode { 177pub enum StopMode {
177 #[default] 178 #[default]
178 /// Peripheral prevents chip from entering Stop1 or executor will enter Stop1 179 /// Peripheral prevents chip from entering Stop1 or executor will enter Stop1
@@ -381,12 +382,19 @@ pub(crate) trait StoppablePeripheral {
381} 382}
382 383
383#[cfg(feature = "low-power")] 384#[cfg(feature = "low-power")]
384impl<'a> StoppablePeripheral for StopMode { 385impl StoppablePeripheral for StopMode {
385 fn stop_mode(&self) -> StopMode { 386 fn stop_mode(&self) -> StopMode {
386 *self 387 *self
387 } 388 }
388} 389}
389 390
391impl<'a, T: StoppablePeripheral + PeripheralType> StoppablePeripheral for Peri<'a, T> {
392 #[cfg(feature = "low-power")]
393 fn stop_mode(&self) -> StopMode {
394 T::stop_mode(&self)
395 }
396}
397
390pub(crate) struct BusyPeripheral<T: StoppablePeripheral> { 398pub(crate) struct BusyPeripheral<T: StoppablePeripheral> {
391 peripheral: T, 399 peripheral: T,
392} 400}
@@ -490,6 +498,16 @@ pub fn enable_and_reset<T: RccPeripheral>() {
490 T::RCC_INFO.enable_and_reset(); 498 T::RCC_INFO.enable_and_reset();
491} 499}
492 500
501/// Enables and resets peripheral `T` without incrementing the stop refcount.
502///
503/// # Safety
504///
505/// Peripheral must not be in use.
506// TODO: should this be `unsafe`?
507pub fn enable_and_reset_without_stop<T: RccPeripheral>() {
508 T::RCC_INFO.enable_and_reset_without_stop();
509}
510
493/// Disables peripheral `T`. 511/// Disables peripheral `T`.
494/// 512///
495/// # Safety 513/// # Safety
diff --git a/embassy-stm32/src/rcc/n6.rs b/embassy-stm32/src/rcc/n6.rs
index 866851bbd..178ec57d4 100644
--- a/embassy-stm32/src/rcc/n6.rs
+++ b/embassy-stm32/src/rcc/n6.rs
@@ -1003,6 +1003,24 @@ pub(crate) unsafe fn init(config: Config) {
1003 p.SCB.cpacr.modify(|w| w | (3 << 20) | (3 << 22)); 1003 p.SCB.cpacr.modify(|w| w | (3 << 20) | (3 << 22));
1004 } 1004 }
1005 1005
1006 // TODO: ugly workaround for DMA accesses until RIF is properly implemented
1007 debug!("deactivating RIF");
1008 const RISAF3_BASE_NS: *mut u32 = stm32_metapac::RNG.wrapping_byte_offset(0x8000) as _; // AHB3PERIPH_BASE_NS + 0x8000UL
1009 const RISAF3_REG0_CFGR: *mut u32 = RISAF3_BASE_NS.wrapping_byte_offset(0x40);
1010 const RISAF3_REG0_ENDR: *mut u32 = RISAF3_BASE_NS.wrapping_byte_offset(0x48);
1011 const RISAF3_REG0_CIDCFGR: *mut u32 = RISAF3_BASE_NS.wrapping_byte_offset(0x4C);
1012 const RISAF3_REG1_CFGR: *mut u32 = RISAF3_BASE_NS.wrapping_byte_offset(0x80);
1013 const RISAF3_REG1_ENDR: *mut u32 = RISAF3_BASE_NS.wrapping_byte_offset(0x88);
1014 const RISAF3_REG1_CIDCFGR: *mut u32 = RISAF3_BASE_NS.wrapping_byte_offset(0x8C);
1015 unsafe {
1016 *RISAF3_REG0_CIDCFGR = 0x000F000F; /* RW for everyone */
1017 *RISAF3_REG0_ENDR = 0xFFFFFFFF; /* all-encompassing */
1018 *RISAF3_REG0_CFGR = 0x00000101; /* enabled, secure, unprivileged for everyone */
1019 *RISAF3_REG1_CIDCFGR = 0x00FF00FF; /* RW for everyone */
1020 *RISAF3_REG1_ENDR = 0xFFFFFFFF; /* all-encompassing */
1021 *RISAF3_REG1_CFGR = 0x00000001; /* enabled, non-secure, unprivileged*/
1022 }
1023
1006 debug!("setting power supply config"); 1024 debug!("setting power supply config");
1007 1025
1008 power_supply_config(config.supply_config); 1026 power_supply_config(config.supply_config);
@@ -1039,7 +1057,9 @@ pub(crate) unsafe fn init(config: Config) {
1039 i2s_ckin: None, 1057 i2s_ckin: None,
1040 ic8: None, 1058 ic8: None,
1041 ic9: None, 1059 ic9: None,
1060 ic10: None,
1042 ic14: None, 1061 ic14: None,
1062 ic15: None,
1043 ic17: None, 1063 ic17: None,
1044 ic20: None, 1064 ic20: None,
1045 ); 1065 );
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
index ce4bc43c3..579c34c13 100644
--- a/embassy-stm32/src/sai/mod.rs
+++ b/embassy-stm32/src/sai/mod.rs
@@ -394,7 +394,8 @@ pub struct Config {
394 pub frame_length: u16, 394 pub frame_length: u16,
395 pub clock_strobe: ClockStrobe, 395 pub clock_strobe: ClockStrobe,
396 pub output_drive: OutputDrive, 396 pub output_drive: OutputDrive,
397 pub master_clock_divider: Option<MasterClockDivider>, 397 pub master_clock_divider: MasterClockDivider,
398 pub nodiv: bool,
398 pub is_high_impedance_on_inactive_slot: bool, 399 pub is_high_impedance_on_inactive_slot: bool,
399 pub fifo_threshold: FifoThreshold, 400 pub fifo_threshold: FifoThreshold,
400 pub companding: Companding, 401 pub companding: Companding,
@@ -423,7 +424,8 @@ impl Default for Config {
423 frame_sync_active_level_length: word::U7(16), 424 frame_sync_active_level_length: word::U7(16),
424 frame_sync_definition: FrameSyncDefinition::ChannelIdentification, 425 frame_sync_definition: FrameSyncDefinition::ChannelIdentification,
425 frame_length: 32, 426 frame_length: 32,
426 master_clock_divider: None, 427 master_clock_divider: MasterClockDivider::DIV1,
428 nodiv: false,
427 clock_strobe: ClockStrobe::Rising, 429 clock_strobe: ClockStrobe::Rising,
428 output_drive: OutputDrive::Immediately, 430 output_drive: OutputDrive::Immediately,
429 is_high_impedance_on_inactive_slot: false, 431 is_high_impedance_on_inactive_slot: false,
@@ -677,8 +679,8 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> {
677 w.set_syncen(config.sync_input.syncen()); 679 w.set_syncen(config.sync_input.syncen());
678 w.set_mono(config.stereo_mono.mono()); 680 w.set_mono(config.stereo_mono.mono());
679 w.set_outdriv(config.output_drive.outdriv()); 681 w.set_outdriv(config.output_drive.outdriv());
680 w.set_mckdiv(config.master_clock_divider.unwrap_or(MasterClockDivider::DIV1)); 682 w.set_mckdiv(config.master_clock_divider);
681 w.set_nodiv(config.master_clock_divider.is_none()); 683 w.set_nodiv(config.nodiv);
682 w.set_dmaen(true); 684 w.set_dmaen(true);
683 }); 685 });
684 686
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index e05131040..12086cd3a 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -4,16 +4,15 @@
4use core::default::Default; 4use core::default::Default;
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::ops::{Deref, DerefMut}; 7use core::slice;
8use core::task::Poll; 8use core::task::Poll;
9 9
10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{Peri, PeripheralType}; 10use embassy_hal_internal::{Peri, PeripheralType};
12use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::common_cmd::{self, Resp, ResponseLen}; 12use sdio_host::Cmd;
14use sdio_host::emmc::{EMMC, ExtCSD}; 13use sdio_host::common_cmd::{self, R1, R2, R3, Resp, ResponseLen, Rz};
15use sdio_host::sd::{BusWidth, CIC, CID, CSD, CardCapacity, CardStatus, CurrentState, OCR, RCA, SCR, SD, SDStatus}; 14use sdio_host::sd::{BusWidth, CardStatus};
16use sdio_host::{Cmd, emmc_cmd, sd_cmd}; 15use sdio_host::sd_cmd::{R6, R7};
17 16
18#[cfg(sdmmc_v1)] 17#[cfg(sdmmc_v1)]
19use crate::dma::ChannelAndRequest; 18use crate::dma::ChannelAndRequest;
@@ -22,37 +21,27 @@ use crate::gpio::Pull;
22use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; 21use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
23use crate::interrupt::typelevel::Interrupt; 22use crate::interrupt::typelevel::Interrupt;
24use crate::pac::sdmmc::Sdmmc as RegBlock; 23use crate::pac::sdmmc::Sdmmc as RegBlock;
25use crate::rcc::{self, RccPeripheral}; 24use crate::rcc::{self, RccInfo, RccPeripheral, SealedRccPeripheral};
25use crate::sdmmc::sd::Addressable;
26use crate::time::Hertz; 26use crate::time::Hertz;
27use crate::{interrupt, peripherals}; 27use crate::{interrupt, peripherals};
28 28
29/// Module for SD and EMMC cards
30pub mod sd;
31
32/// Module for SDIO interface
33pub mod sdio;
34
29/// Interrupt handler. 35/// Interrupt handler.
30pub struct InterruptHandler<T: Instance> { 36pub struct InterruptHandler<T: Instance> {
31 _phantom: PhantomData<T>, 37 _phantom: PhantomData<T>,
32} 38}
33 39
34impl<T: Instance> InterruptHandler<T> {
35 fn enable_interrupts() {
36 let regs = T::regs();
37 regs.maskr().write(|w| {
38 w.set_dcrcfailie(true);
39 w.set_dtimeoutie(true);
40 w.set_dataendie(true);
41 w.set_dbckendie(true);
42
43 #[cfg(sdmmc_v1)]
44 w.set_stbiterre(true);
45 #[cfg(sdmmc_v2)]
46 w.set_dabortie(true);
47 });
48 }
49}
50
51impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { 40impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
52 unsafe fn on_interrupt() { 41 unsafe fn on_interrupt() {
53 T::state().wake(); 42 T::state().waker.wake();
54 let status = T::regs().star().read(); 43 let status = T::info().regs.star().read();
55 T::regs().maskr().modify(|w| { 44 T::info().regs.maskr().modify(|w| {
56 if status.dcrcfail() { 45 if status.dcrcfail() {
57 w.set_dcrcfailie(false) 46 w.set_dcrcfailie(false)
58 } 47 }
@@ -77,6 +66,57 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
77 } 66 }
78} 67}
79 68
69struct U128(pub u128);
70
71trait TypedResp: Resp {
72 type Word: From<U128>;
73}
74
75impl From<U128> for () {
76 fn from(value: U128) -> Self {
77 match value.0 {
78 0 => (),
79 _ => unreachable!(),
80 }
81 }
82}
83
84impl From<U128> for u32 {
85 fn from(value: U128) -> Self {
86 unwrap!(value.0.try_into())
87 }
88}
89
90impl From<U128> for u128 {
91 fn from(value: U128) -> Self {
92 value.0
93 }
94}
95
96impl TypedResp for Rz {
97 type Word = ();
98}
99
100impl TypedResp for R1 {
101 type Word = u32;
102}
103
104impl TypedResp for R2 {
105 type Word = u128;
106}
107
108impl TypedResp for R3 {
109 type Word = u32;
110}
111
112impl TypedResp for R6 {
113 type Word = u32;
114}
115
116impl TypedResp for R7 {
117 type Word = u32;
118}
119
80/// Frequency used for SD Card initialization. Must be no higher than 400 kHz. 120/// Frequency used for SD Card initialization. Must be no higher than 400 kHz.
81const SD_INIT_FREQ: Hertz = Hertz(400_000); 121const SD_INIT_FREQ: Hertz = Hertz(400_000);
82 122
@@ -99,54 +139,14 @@ impl Default for Signalling {
99 } 139 }
100} 140}
101 141
102/// Aligned data block for SDMMC transfers. 142const fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
103/// 143 let len = x.len() * 4;
104/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements. 144 unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) }
105#[repr(align(4))]
106#[derive(Debug, Clone, PartialEq, Eq)]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))]
108pub struct DataBlock(pub [u8; 512]);
109
110impl Deref for DataBlock {
111 type Target = [u8; 512];
112
113 fn deref(&self) -> &Self::Target {
114 &self.0
115 }
116} 145}
117 146
118impl DerefMut for DataBlock { 147const fn slice8_ref(x: &[u32]) -> &[u8] {
119 fn deref_mut(&mut self) -> &mut Self::Target { 148 let len = x.len() * 4;
120 &mut self.0 149 unsafe { slice::from_raw_parts(x.as_ptr() as _, len) }
121 }
122}
123
124/// Command Block buffer for SDMMC command transfers.
125///
126/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required.
127#[derive(Debug, Clone, PartialEq, Eq)]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub struct CmdBlock(pub [u32; 16]);
130
131impl CmdBlock {
132 /// Creates a new instance of CmdBlock
133 pub const fn new() -> Self {
134 Self([0u32; 16])
135 }
136}
137
138impl Deref for CmdBlock {
139 type Target = [u32; 16];
140
141 fn deref(&self) -> &Self::Target {
142 &self.0
143 }
144}
145
146impl DerefMut for CmdBlock {
147 fn deref_mut(&mut self) -> &mut Self::Target {
148 &mut self.0
149 }
150} 150}
151 151
152/// Errors 152/// Errors
@@ -181,42 +181,6 @@ pub enum Error {
181 StBitErr, 181 StBitErr,
182} 182}
183 183
184#[derive(Clone, Copy, Debug, Default)]
185/// SD Card
186pub struct Card {
187 /// The type of this card
188 pub card_type: CardCapacity,
189 /// Operation Conditions Register
190 pub ocr: OCR<SD>,
191 /// Relative Card Address
192 pub rca: u16,
193 /// Card ID
194 pub cid: CID<SD>,
195 /// Card Specific Data
196 pub csd: CSD<SD>,
197 /// SD CARD Configuration Register
198 pub scr: SCR,
199 /// SD Status
200 pub status: SDStatus,
201}
202
203#[derive(Clone, Copy, Debug, Default)]
204/// eMMC storage
205pub struct Emmc {
206 /// The capacity of this card
207 pub capacity: CardCapacity,
208 /// Operation Conditions Register
209 pub ocr: OCR<EMMC>,
210 /// Relative Card Address
211 pub rca: u16,
212 /// Card ID
213 pub cid: CID<EMMC>,
214 /// Card Specific Data
215 pub csd: CSD<EMMC>,
216 /// Extended Card Specific Data
217 pub ext_csd: ExtCSD,
218}
219
220#[repr(u8)] 184#[repr(u8)]
221enum PowerCtrl { 185enum PowerCtrl {
222 Off = 0b00, 186 Off = 0b00,
@@ -259,6 +223,55 @@ fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
259 Ok((false, clk_div, clk_f)) 223 Ok((false, clk_div, clk_f))
260} 224}
261 225
226fn bus_width_vals(bus_width: BusWidth) -> (u8, u32) {
227 match bus_width {
228 BusWidth::One => (0, 1u32),
229 BusWidth::Four => (1, 4u32),
230 BusWidth::Eight => (2, 8u32),
231 _ => panic!("Invalid Bus Width"),
232 }
233}
234
235#[repr(u8)]
236enum BlockSize {
237 Size1 = 0b0000,
238 Size2 = 0b0001,
239 Size4 = 0b0010,
240 Size8 = 0b0011,
241 Size16 = 0b0100,
242 Size32 = 0b0101,
243 Size64 = 0b0110,
244 Size128 = 0b0111,
245 Size256 = 0b1000,
246 Size512 = 0b1001,
247 Size1024 = 0b1010,
248 Size2048 = 0b1011,
249 Size4096 = 0b1100,
250 Size8192 = 0b1101,
251 Size16384 = 0b1110,
252}
253
254const fn block_size(bytes: usize) -> BlockSize {
255 match bytes {
256 1 => BlockSize::Size1,
257 2 => BlockSize::Size2,
258 4 => BlockSize::Size4,
259 8 => BlockSize::Size8,
260 16 => BlockSize::Size16,
261 32 => BlockSize::Size32,
262 64 => BlockSize::Size64,
263 128 => BlockSize::Size128,
264 256 => BlockSize::Size256,
265 512 => BlockSize::Size512,
266 1024 => BlockSize::Size1024,
267 2048 => BlockSize::Size2048,
268 4096 => BlockSize::Size4096,
269 8192 => BlockSize::Size8192,
270 16384 => BlockSize::Size16384,
271 _ => core::unreachable!(),
272 }
273}
274
262/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to 275/// Calculate clock divisor. Returns a SDMMC_CK less than or equal to
263/// `sdmmc_ck` in Hertz. 276/// `sdmmc_ck` in Hertz.
264/// 277///
@@ -286,6 +299,34 @@ struct Transfer<'a> {
286 _dummy: PhantomData<&'a ()>, 299 _dummy: PhantomData<&'a ()>,
287} 300}
288 301
302struct WrappedTransfer<'a> {
303 _transfer: Transfer<'a>,
304 sdmmc: &'a Sdmmc<'a>,
305 defused: bool,
306}
307
308impl<'a> WrappedTransfer<'a> {
309 pub const fn new(_transfer: Transfer<'a>, sdmmc: &'a Sdmmc) -> Self {
310 Self {
311 _transfer,
312 sdmmc,
313 defused: false,
314 }
315 }
316
317 pub fn defuse(&mut self) {
318 self.defused = true;
319 }
320}
321
322impl<'a> Drop for WrappedTransfer<'a> {
323 fn drop(&mut self) {
324 if !self.defused {
325 self.sdmmc.on_drop();
326 }
327 }
328}
329
289#[cfg(all(sdmmc_v1, dma))] 330#[cfg(all(sdmmc_v1, dma))]
290const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions { 331const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions {
291 pburst: crate::dma::Burst::Incr4, 332 pburst: crate::dma::Burst::Incr4,
@@ -323,64 +364,11 @@ impl Default for Config {
323 } 364 }
324} 365}
325 366
326/// Peripheral that can be operated over SDMMC
327#[derive(Clone, Copy, Debug)]
328pub enum SdmmcPeripheral {
329 /// SD Card
330 SdCard(Card),
331 /// eMMC memory
332 Emmc(Emmc),
333}
334
335impl SdmmcPeripheral {
336 /// Get this peripheral's address on the SDMMC bus
337 fn get_address(&self) -> u16 {
338 match self {
339 Self::SdCard(c) => c.rca,
340 Self::Emmc(e) => e.rca,
341 }
342 }
343 /// Is this a standard or high capacity peripheral?
344 fn get_capacity(&self) -> CardCapacity {
345 match self {
346 Self::SdCard(c) => c.card_type,
347 Self::Emmc(e) => e.capacity,
348 }
349 }
350 /// Size in bytes
351 fn size(&self) -> u64 {
352 match self {
353 // SDHC / SDXC / SDUC
354 Self::SdCard(c) => u64::from(c.csd.block_count()) * 512,
355 // capacity > 2GB
356 Self::Emmc(e) => u64::from(e.ext_csd.sector_count()) * 512,
357 }
358 }
359
360 /// Get a mutable reference to the SD Card.
361 ///
362 /// Panics if there is another peripheral instead.
363 fn get_sd_card(&mut self) -> &mut Card {
364 match *self {
365 Self::SdCard(ref mut c) => c,
366 _ => unreachable!("SD only"),
367 }
368 }
369
370 /// Get a mutable reference to the eMMC.
371 ///
372 /// Panics if there is another peripheral instead.
373 fn get_emmc(&mut self) -> &mut Emmc {
374 match *self {
375 Self::Emmc(ref mut e) => e,
376 _ => unreachable!("eMMC only"),
377 }
378 }
379}
380
381/// Sdmmc device 367/// Sdmmc device
382pub struct Sdmmc<'d, T: Instance> { 368pub struct Sdmmc<'d> {
383 _peri: Peri<'d, T>, 369 info: &'static Info,
370 state: &'static State,
371 ker_clk: Hertz,
384 #[cfg(sdmmc_v1)] 372 #[cfg(sdmmc_v1)]
385 dma: ChannelAndRequest<'d>, 373 dma: ChannelAndRequest<'d>,
386 374
@@ -400,12 +388,6 @@ pub struct Sdmmc<'d, T: Instance> {
400 clock: Hertz, 388 clock: Hertz,
401 /// Current signalling scheme to card 389 /// Current signalling scheme to card
402 signalling: Signalling, 390 signalling: Signalling,
403 /// Card
404 card: Option<SdmmcPeripheral>,
405
406 /// An optional buffer to be used for commands
407 /// This should be used if there are special memory location requirements for dma
408 cmd_block: Option<&'d mut CmdBlock>,
409} 391}
410 392
411const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh); 393const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
@@ -416,9 +398,9 @@ const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh
416const DATA_AF: AfType = CMD_AF; 398const DATA_AF: AfType = CMD_AF;
417 399
418#[cfg(sdmmc_v1)] 400#[cfg(sdmmc_v1)]
419impl<'d, T: Instance> Sdmmc<'d, T> { 401impl<'d> Sdmmc<'d> {
420 /// Create a new SDMMC driver, with 1 data lane. 402 /// Create a new SDMMC driver, with 1 data lane.
421 pub fn new_1bit( 403 pub fn new_1bit<T: Instance>(
422 sdmmc: Peri<'d, T>, 404 sdmmc: Peri<'d, T>,
423 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 405 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
424 dma: Peri<'d, impl SdmmcDma<T>>, 406 dma: Peri<'d, impl SdmmcDma<T>>,
@@ -451,7 +433,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
451 } 433 }
452 434
453 /// Create a new SDMMC driver, with 4 data lanes. 435 /// Create a new SDMMC driver, with 4 data lanes.
454 pub fn new_4bit( 436 pub fn new_4bit<T: Instance>(
455 sdmmc: Peri<'d, T>, 437 sdmmc: Peri<'d, T>,
456 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 438 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
457 dma: Peri<'d, impl SdmmcDma<T>>, 439 dma: Peri<'d, impl SdmmcDma<T>>,
@@ -491,9 +473,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
491} 473}
492 474
493#[cfg(sdmmc_v1)] 475#[cfg(sdmmc_v1)]
494impl<'d, T: Instance> Sdmmc<'d, T> { 476impl<'d> Sdmmc<'d> {
495 /// Create a new SDMMC driver, with 8 data lanes. 477 /// Create a new SDMMC driver, with 8 data lanes.
496 pub fn new_8bit( 478 pub fn new_8bit<T: Instance>(
497 sdmmc: Peri<'d, T>, 479 sdmmc: Peri<'d, T>,
498 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 480 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
499 dma: Peri<'d, impl SdmmcDma<T>>, 481 dma: Peri<'d, impl SdmmcDma<T>>,
@@ -541,9 +523,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
541} 523}
542 524
543#[cfg(sdmmc_v2)] 525#[cfg(sdmmc_v2)]
544impl<'d, T: Instance> Sdmmc<'d, T> { 526impl<'d> Sdmmc<'d> {
545 /// Create a new SDMMC driver, with 1 data lane. 527 /// Create a new SDMMC driver, with 1 data lane.
546 pub fn new_1bit( 528 pub fn new_1bit<T: Instance>(
547 sdmmc: Peri<'d, T>, 529 sdmmc: Peri<'d, T>,
548 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 530 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
549 clk: Peri<'d, impl CkPin<T>>, 531 clk: Peri<'d, impl CkPin<T>>,
@@ -574,7 +556,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
574 } 556 }
575 557
576 /// Create a new SDMMC driver, with 4 data lanes. 558 /// Create a new SDMMC driver, with 4 data lanes.
577 pub fn new_4bit( 559 pub fn new_4bit<T: Instance>(
578 sdmmc: Peri<'d, T>, 560 sdmmc: Peri<'d, T>,
579 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 561 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
580 clk: Peri<'d, impl CkPin<T>>, 562 clk: Peri<'d, impl CkPin<T>>,
@@ -612,9 +594,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
612} 594}
613 595
614#[cfg(sdmmc_v2)] 596#[cfg(sdmmc_v2)]
615impl<'d, T: Instance> Sdmmc<'d, T> { 597impl<'d> Sdmmc<'d> {
616 /// Create a new SDMMC driver, with 8 data lanes. 598 /// Create a new SDMMC driver, with 8 data lanes.
617 pub fn new_8bit( 599 pub fn new_8bit<T: Instance>(
618 sdmmc: Peri<'d, T>, 600 sdmmc: Peri<'d, T>,
619 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 601 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
620 clk: Peri<'d, impl CkPin<T>>, 602 clk: Peri<'d, impl CkPin<T>>,
@@ -659,9 +641,24 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
659 } 641 }
660} 642}
661 643
662impl<'d, T: Instance> Sdmmc<'d, T> { 644impl<'d> Sdmmc<'d> {
663 fn new_inner( 645 fn enable_interrupts(&self) {
664 sdmmc: Peri<'d, T>, 646 let regs = self.info.regs;
647 regs.maskr().write(|w| {
648 w.set_dcrcfailie(true);
649 w.set_dtimeoutie(true);
650 w.set_dataendie(true);
651 w.set_dbckendie(true);
652
653 #[cfg(sdmmc_v1)]
654 w.set_stbiterre(true);
655 #[cfg(sdmmc_v2)]
656 w.set_dabortie(true);
657 });
658 }
659
660 fn new_inner<T: Instance>(
661 _sdmmc: Peri<'d, T>,
665 #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>, 662 #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>,
666 clk: Peri<'d, AnyPin>, 663 clk: Peri<'d, AnyPin>,
667 cmd: Peri<'d, AnyPin>, 664 cmd: Peri<'d, AnyPin>,
@@ -675,13 +672,16 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
675 d7: Option<Peri<'d, AnyPin>>, 672 d7: Option<Peri<'d, AnyPin>>,
676 config: Config, 673 config: Config,
677 ) -> Self { 674 ) -> Self {
678 rcc::enable_and_reset::<T>(); 675 rcc::enable_and_reset_without_stop::<T>();
679 676
680 T::Interrupt::unpend(); 677 T::Interrupt::unpend();
681 unsafe { T::Interrupt::enable() }; 678 unsafe { T::Interrupt::enable() };
682 679
683 let regs = T::regs(); 680 let info = T::info();
684 regs.clkcr().write(|w| { 681 let state = T::state();
682 let ker_clk = T::frequency();
683
684 info.regs.clkcr().write(|w| {
685 w.set_pwrsav(false); 685 w.set_pwrsav(false);
686 w.set_negedge(false); 686 w.set_negedge(false);
687 687
@@ -698,10 +698,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
698 698
699 // Power off, writen 00: Clock to the card is stopped; 699 // Power off, writen 00: Clock to the card is stopped;
700 // D[7:0], CMD, and CK are driven high. 700 // D[7:0], CMD, and CK are driven high.
701 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); 701 info.regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
702 702
703 Self { 703 Self {
704 _peri: sdmmc, 704 info,
705 state,
706 ker_clk,
705 #[cfg(sdmmc_v1)] 707 #[cfg(sdmmc_v1)]
706 dma, 708 dma,
707 709
@@ -719,15 +721,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
719 config, 721 config,
720 clock: SD_INIT_FREQ, 722 clock: SD_INIT_FREQ,
721 signalling: Default::default(), 723 signalling: Default::default(),
722 card: None,
723 cmd_block: None,
724 } 724 }
725 } 725 }
726 726
727 /// Data transfer is in progress 727 /// Data transfer is in progress
728 #[inline] 728 #[inline]
729 fn data_active() -> bool { 729 fn data_active(&self) -> bool {
730 let regs = T::regs(); 730 let regs = self.info.regs;
731 731
732 let status = regs.star().read(); 732 let status = regs.star().read();
733 #[cfg(sdmmc_v1)] 733 #[cfg(sdmmc_v1)]
@@ -738,8 +738,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
738 738
739 /// Coammand transfer is in progress 739 /// Coammand transfer is in progress
740 #[inline] 740 #[inline]
741 fn cmd_active() -> bool { 741 fn cmd_active(&self) -> bool {
742 let regs = T::regs(); 742 let regs = self.info.regs;
743 743
744 let status = regs.star().read(); 744 let status = regs.star().read();
745 #[cfg(sdmmc_v1)] 745 #[cfg(sdmmc_v1)]
@@ -750,8 +750,16 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
750 750
751 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) 751 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
752 #[inline] 752 #[inline]
753 fn wait_idle() { 753 fn wait_idle(&self) {
754 while Self::data_active() || Self::cmd_active() {} 754 while self.data_active() || self.cmd_active() {}
755 }
756
757 fn bus_width(&self) -> BusWidth {
758 match (self.d3.is_some(), self.d7.is_some()) {
759 (true, true) => BusWidth::Eight,
760 (true, false) => BusWidth::Four,
761 _ => BusWidth::One,
762 }
755 } 763 }
756 764
757 /// # Safety 765 /// # Safety
@@ -759,23 +767,25 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
759 /// `buffer` must be valid for the whole transfer and word aligned 767 /// `buffer` must be valid for the whole transfer and word aligned
760 #[allow(unused_variables)] 768 #[allow(unused_variables)]
761 fn prepare_datapath_read<'a>( 769 fn prepare_datapath_read<'a>(
762 config: &Config, 770 &'a self,
763 #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>,
764 buffer: &'a mut [u32], 771 buffer: &'a mut [u32],
765 length_bytes: u32, 772 block_size: BlockSize,
766 block_size: u8, 773 byte_mode: bool,
767 ) -> Transfer<'a> { 774 ) -> WrappedTransfer<'a> {
768 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 775 let regs = self.info.regs;
769 let regs = T::regs();
770 776
771 // Command AND Data state machines must be idle 777 // Command AND Data state machines must be idle
772 Self::wait_idle(); 778 self.wait_idle();
773 Self::clear_interrupt_flags(); 779 self.clear_interrupt_flags();
774 780
775 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 781 regs.dlenr().write(|w| w.set_datalength(size_of_val(buffer) as u32));
776 782
783 // SAFETY: No other functions use the dma
777 #[cfg(sdmmc_v1)] 784 #[cfg(sdmmc_v1)]
778 let transfer = unsafe { dma.read(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) }; 785 let transfer = unsafe {
786 self.dma
787 .read_unchecked(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS)
788 };
779 #[cfg(sdmmc_v2)] 789 #[cfg(sdmmc_v2)]
780 let transfer = { 790 let transfer = {
781 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); 791 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32));
@@ -785,8 +795,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
785 } 795 }
786 }; 796 };
787 797
798 #[cfg(sdmmc_v2)]
799 let byte_mode = byte_mode as u8;
800
788 regs.dctrl().modify(|w| { 801 regs.dctrl().modify(|w| {
789 w.set_dblocksize(block_size); 802 w.set_dtmode(byte_mode);
803 w.set_dblocksize(block_size as u8);
790 w.set_dtdir(true); 804 w.set_dtdir(true);
791 #[cfg(sdmmc_v1)] 805 #[cfg(sdmmc_v1)]
792 { 806 {
@@ -795,26 +809,33 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
795 } 809 }
796 }); 810 });
797 811
798 transfer 812 self.enable_interrupts();
813
814 WrappedTransfer::new(transfer, &self)
799 } 815 }
800 816
801 /// # Safety 817 /// # Safety
802 /// 818 ///
803 /// `buffer` must be valid for the whole transfer and word aligned 819 /// `buffer` must be valid for the whole transfer and word aligned
804 fn prepare_datapath_write<'a>(&'a mut self, buffer: &'a [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> { 820 fn prepare_datapath_write<'a>(
805 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 821 &'a self,
806 let regs = T::regs(); 822 buffer: &'a [u32],
823 block_size: BlockSize,
824 byte_mode: bool,
825 ) -> WrappedTransfer<'a> {
826 let regs = self.info.regs;
807 827
808 // Command AND Data state machines must be idle 828 // Command AND Data state machines must be idle
809 Self::wait_idle(); 829 self.wait_idle();
810 Self::clear_interrupt_flags(); 830 self.clear_interrupt_flags();
811 831
812 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 832 regs.dlenr().write(|w| w.set_datalength(size_of_val(buffer) as u32));
813 833
834 // SAFETY: No other functions use the dma
814 #[cfg(sdmmc_v1)] 835 #[cfg(sdmmc_v1)]
815 let transfer = unsafe { 836 let transfer = unsafe {
816 self.dma 837 self.dma
817 .write(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS) 838 .write_unchecked(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS)
818 }; 839 };
819 #[cfg(sdmmc_v2)] 840 #[cfg(sdmmc_v2)]
820 let transfer = { 841 let transfer = {
@@ -825,8 +846,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
825 } 846 }
826 }; 847 };
827 848
849 #[cfg(sdmmc_v2)]
850 let byte_mode = byte_mode as u8;
851
828 regs.dctrl().modify(|w| { 852 regs.dctrl().modify(|w| {
829 w.set_dblocksize(block_size); 853 w.set_dtmode(byte_mode);
854 w.set_dblocksize(block_size as u8);
830 w.set_dtdir(false); 855 w.set_dtdir(false);
831 #[cfg(sdmmc_v1)] 856 #[cfg(sdmmc_v1)]
832 { 857 {
@@ -835,12 +860,14 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
835 } 860 }
836 }); 861 });
837 862
838 transfer 863 self.enable_interrupts();
864
865 WrappedTransfer::new(transfer, &self)
839 } 866 }
840 867
841 /// Stops the DMA datapath 868 /// Stops the DMA datapath
842 fn stop_datapath() { 869 fn stop_datapath(&self) {
843 let regs = T::regs(); 870 let regs = self.info.regs;
844 871
845 #[cfg(sdmmc_v1)] 872 #[cfg(sdmmc_v1)]
846 regs.dctrl().modify(|w| { 873 regs.dctrl().modify(|w| {
@@ -851,49 +878,58 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
851 regs.idmactrlr().modify(|w| w.set_idmaen(false)); 878 regs.idmactrlr().modify(|w| w.set_idmaen(false));
852 } 879 }
853 880
881 fn init_idle(&mut self) -> Result<(), Error> {
882 let regs = self.info.regs;
883
884 self.clkcr_set_clkdiv(SD_INIT_FREQ, BusWidth::One)?;
885 regs.dtimer()
886 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
887
888 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
889 self.cmd(common_cmd::idle(), false)
890 }
891
854 /// Sets the CLKDIV field in CLKCR. Updates clock field in self 892 /// Sets the CLKDIV field in CLKCR. Updates clock field in self
855 fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> { 893 fn clkcr_set_clkdiv(&mut self, freq: Hertz, width: BusWidth) -> Result<(), Error> {
856 let regs = T::regs(); 894 let regs = self.info.regs;
857
858 let width_u32 = match width {
859 BusWidth::One => 1u32,
860 BusWidth::Four => 4u32,
861 BusWidth::Eight => 8u32,
862 _ => panic!("Invalid Bus Width"),
863 };
864 895
865 let ker_ck = T::frequency(); 896 let (widbus, width_u32) = bus_width_vals(width);
866 let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?; 897 let (_bypass, clkdiv, new_clock) = clk_div(self.ker_clk, freq.0)?;
867 898
868 // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 899 // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
869 // Section 55.5.8 900 // Section 55.5.8
870 let sdmmc_bus_bandwidth = new_clock.0 * width_u32; 901 let sdmmc_bus_bandwidth = new_clock.0 * width_u32;
871 assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); 902 assert!(self.ker_clk.0 > 3 * sdmmc_bus_bandwidth / 32);
872 self.clock = new_clock; 903 self.clock = new_clock;
873 904
874 // CPSMACT and DPSMACT must be 0 to set CLKDIV 905 // CPSMACT and DPSMACT must be 0 to set CLKDIV or WIDBUS
875 Self::wait_idle(); 906 self.wait_idle();
876 regs.clkcr().modify(|w| { 907 regs.clkcr().modify(|w| {
877 w.set_clkdiv(clkdiv); 908 w.set_clkdiv(clkdiv);
878 #[cfg(sdmmc_v1)] 909 #[cfg(sdmmc_v1)]
879 w.set_bypass(_bypass); 910 w.set_bypass(_bypass);
911 w.set_widbus(widbus);
880 }); 912 });
881 913
882 Ok(()) 914 Ok(())
883 } 915 }
884 916
917 fn get_cid(&self) -> Result<u128, Error> {
918 self.cmd(common_cmd::all_send_cid(), false) // CMD2
919 }
920
921 fn get_csd(&self, address: u16) -> Result<u128, Error> {
922 self.cmd(common_cmd::send_csd(address), false)
923 }
924
885 /// Query the card status (CMD13, returns R1) 925 /// Query the card status (CMD13, returns R1)
886 fn read_status<Ext>(&self, card: &SdmmcPeripheral) -> Result<CardStatus<Ext>, Error> 926 fn read_status<A: Addressable>(&self, card: &A) -> Result<CardStatus<A::Ext>, Error>
887 where 927 where
888 CardStatus<Ext>: From<u32>, 928 CardStatus<A::Ext>: From<u32>,
889 { 929 {
890 let regs = T::regs();
891 let rca = card.get_address(); 930 let rca = card.get_address();
892 931
893 Self::cmd(common_cmd::card_status(rca, false), false)?; // CMD13 932 Ok(self.cmd(common_cmd::card_status(rca, false), false)?.into()) // CMD13
894
895 let r1 = regs.respr(0).read().cardstatus();
896 Ok(r1.into())
897 } 933 }
898 934
899 /// Select one card and place it into the _Tranfer State_ 935 /// Select one card and place it into the _Tranfer State_
@@ -904,17 +940,23 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
904 // Determine Relative Card Address (RCA) of given card 940 // Determine Relative Card Address (RCA) of given card
905 let rca = rca.unwrap_or(0); 941 let rca = rca.unwrap_or(0);
906 942
907 let r = Self::cmd(common_cmd::select_card(rca), false); 943 let resp = self.cmd(common_cmd::select_card(rca), false);
908 match (r, rca) { 944
909 (Err(Error::Timeout), 0) => Ok(()), 945 if let Err(Error::Timeout) = resp
910 _ => r, 946 && rca == 0
947 {
948 return Ok(());
911 } 949 }
950
951 resp?;
952
953 Ok(())
912 } 954 }
913 955
914 /// Clear flags in interrupt clear register 956 /// Clear flags in interrupt clear register
915 #[inline] 957 #[inline]
916 fn clear_interrupt_flags() { 958 fn clear_interrupt_flags(&self) {
917 let regs = T::regs(); 959 let regs = self.info.regs;
918 regs.icr().write(|w| { 960 regs.icr().write(|w| {
919 w.set_ccrcfailc(true); 961 w.set_ccrcfailc(true);
920 w.set_dcrcfailc(true); 962 w.set_dcrcfailc(true);
@@ -947,12 +989,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
947 989
948 /// Send command to card 990 /// Send command to card
949 #[allow(unused_variables)] 991 #[allow(unused_variables)]
950 fn cmd<R: Resp>(cmd: Cmd<R>, data: bool) -> Result<(), Error> { 992 fn cmd<R: TypedResp>(&self, cmd: Cmd<R>, data: bool) -> Result<R::Word, Error> {
951 let regs = T::regs(); 993 let regs = self.info.regs;
952 994
953 Self::clear_interrupt_flags(); 995 self.clear_interrupt_flags();
954 // CP state machine must be idle 996 // CP state machine must be idle
955 while Self::cmd_active() {} 997 while self.cmd_active() {}
956 998
957 // Command arg 999 // Command arg
958 regs.argr().write(|w| w.set_cmdarg(cmd.arg)); 1000 regs.argr().write(|w| w.set_cmdarg(cmd.arg));
@@ -994,16 +1036,29 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
994 } else if status.ccrcfail() { 1036 } else if status.ccrcfail() {
995 return Err(Error::Crc); 1037 return Err(Error::Crc);
996 } 1038 }
997 Ok(()) 1039
1040 Ok(match R::LENGTH {
1041 ResponseLen::Zero => U128(0u128),
1042 ResponseLen::R48 => U128(self.info.regs.respr(0).read().cardstatus() as u128),
1043 ResponseLen::R136 => {
1044 let cid0 = self.info.regs.respr(0).read().cardstatus() as u128;
1045 let cid1 = self.info.regs.respr(1).read().cardstatus() as u128;
1046 let cid2 = self.info.regs.respr(2).read().cardstatus() as u128;
1047 let cid3 = self.info.regs.respr(3).read().cardstatus() as u128;
1048
1049 U128((cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3))
1050 }
1051 }
1052 .into())
998 } 1053 }
999 1054
1000 fn on_drop() { 1055 fn on_drop(&self) {
1001 let regs = T::regs(); 1056 let regs = self.info.regs;
1002 if Self::data_active() { 1057 if self.data_active() {
1003 Self::clear_interrupt_flags(); 1058 self.clear_interrupt_flags();
1004 // Send abort 1059 // Send abort
1005 // CP state machine must be idle 1060 // CP state machine must be idle
1006 while Self::cmd_active() {} 1061 while self.cmd_active() {}
1007 1062
1008 // Command arg 1063 // Command arg
1009 regs.argr().write(|w| w.set_cmdarg(0)); 1064 regs.argr().write(|w| w.set_cmdarg(0));
@@ -1023,22 +1078,22 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1023 }); 1078 });
1024 1079
1025 // Wait for the abort 1080 // Wait for the abort
1026 while Self::data_active() {} 1081 while self.data_active() {}
1027 } 1082 }
1028 regs.maskr().write(|_| ()); // disable irqs 1083 regs.maskr().write(|_| ()); // disable irqs
1029 Self::clear_interrupt_flags(); 1084 self.clear_interrupt_flags();
1030 Self::stop_datapath(); 1085 self.stop_datapath();
1031 } 1086 }
1032 1087
1033 /// Wait for a previously started datapath transfer to complete from an interrupt. 1088 /// Wait for a previously started datapath transfer to complete from an interrupt.
1034 #[inline] 1089 #[inline]
1035 #[allow(unused)] 1090 #[allow(unused)]
1036 async fn complete_datapath_transfer(block: bool) -> Result<(), Error> { 1091 async fn complete_datapath_transfer(&self, mut transfer: WrappedTransfer<'_>, block: bool) -> Result<(), Error> {
1037 let res = poll_fn(|cx| { 1092 let res = poll_fn(|cx| {
1038 // Compiler might not be sufficiently constrained here 1093 // Compiler might not be sufficiently constrained here
1039 // https://github.com/embassy-rs/embassy/issues/4723 1094 // https://github.com/embassy-rs/embassy/issues/4723
1040 T::state().register(cx.waker()); 1095 self.state.waker.register(cx.waker());
1041 let status = T::regs().star().read(); 1096 let status = self.info.regs.star().read();
1042 1097
1043 if status.dcrcfail() { 1098 if status.dcrcfail() {
1044 return Poll::Ready(Err(Error::Crc)); 1099 return Poll::Ready(Err(Error::Crc));
@@ -1067,698 +1122,25 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1067 }) 1122 })
1068 .await; 1123 .await;
1069 1124
1070 Self::clear_interrupt_flags(); 1125 self.clear_interrupt_flags();
1071 1126 self.stop_datapath();
1072 res
1073 }
1074
1075 /// Read a data block.
1076 #[inline]
1077 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
1078 let card_capacity = self.card()?.get_capacity();
1079
1080 // NOTE(unsafe) DataBlock uses align 4
1081 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
1082 1127
1083 // Always read 1 block of 512 bytes 1128 transfer.defuse();
1084 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes 1129 drop(transfer);
1085 let address = match card_capacity {
1086 CardCapacity::StandardCapacity => block_idx * 512,
1087 _ => block_idx,
1088 };
1089 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1090 1130
1091 let on_drop = OnDrop::new(|| Self::on_drop());
1092
1093 let transfer = Self::prepare_datapath_read(
1094 &self.config,
1095 #[cfg(sdmmc_v1)]
1096 &mut self.dma,
1097 buffer,
1098 512,
1099 9,
1100 );
1101 InterruptHandler::<T>::enable_interrupts();
1102 Self::cmd(common_cmd::read_single_block(address), true)?;
1103
1104 let res = Self::complete_datapath_transfer(true).await;
1105
1106 if res.is_ok() {
1107 on_drop.defuse();
1108 Self::stop_datapath();
1109 drop(transfer);
1110 }
1111 res 1131 res
1112 } 1132 }
1113 1133
1114 /// Read multiple data blocks.
1115 #[inline]
1116 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
1117 let card_capacity = self.card()?.get_capacity();
1118
1119 // NOTE(unsafe) reinterpret buffer as &mut [u32]
1120 let buffer = unsafe {
1121 let ptr = blocks.as_mut_ptr() as *mut u32;
1122 let len = blocks.len() * 128;
1123 core::slice::from_raw_parts_mut(ptr, len)
1124 };
1125
1126 // Always read 1 block of 512 bytes
1127 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1128 let address = match card_capacity {
1129 CardCapacity::StandardCapacity => block_idx * 512,
1130 _ => block_idx,
1131 };
1132 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1133
1134 let on_drop = OnDrop::new(|| Self::on_drop());
1135
1136 let transfer = Self::prepare_datapath_read(
1137 &self.config,
1138 #[cfg(sdmmc_v1)]
1139 &mut self.dma,
1140 buffer,
1141 512 * blocks.len() as u32,
1142 9,
1143 );
1144 InterruptHandler::<T>::enable_interrupts();
1145
1146 Self::cmd(common_cmd::read_multiple_blocks(address), true)?;
1147
1148 let res = Self::complete_datapath_transfer(false).await;
1149
1150 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12
1151 Self::clear_interrupt_flags();
1152
1153 if res.is_ok() {
1154 on_drop.defuse();
1155 Self::stop_datapath();
1156 drop(transfer);
1157 }
1158 res
1159 }
1160
1161 /// Write a data block.
1162 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
1163 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1164
1165 // NOTE(unsafe) DataBlock uses align 4
1166 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
1167
1168 // Always read 1 block of 512 bytes
1169 // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1170 let address = match card.get_capacity() {
1171 CardCapacity::StandardCapacity => block_idx * 512,
1172 _ => block_idx,
1173 };
1174 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1175
1176 let on_drop = OnDrop::new(|| Self::on_drop());
1177
1178 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
1179 #[cfg(sdmmc_v1)]
1180 Self::cmd(common_cmd::write_single_block(address), true)?;
1181
1182 let transfer = self.prepare_datapath_write(buffer, 512, 9);
1183 InterruptHandler::<T>::enable_interrupts();
1184
1185 #[cfg(sdmmc_v2)]
1186 Self::cmd(common_cmd::write_single_block(address), true)?;
1187
1188 let res = Self::complete_datapath_transfer(true).await;
1189
1190 match res {
1191 Ok(_) => {
1192 on_drop.defuse();
1193 Self::stop_datapath();
1194 drop(transfer);
1195
1196 // TODO: Make this configurable
1197 let mut timeout: u32 = 0x00FF_FFFF;
1198
1199 let card = self.card.as_ref().unwrap();
1200 while timeout > 0 {
1201 let ready_for_data = match card {
1202 SdmmcPeripheral::Emmc(_) => self.read_status::<EMMC>(card)?.ready_for_data(),
1203 SdmmcPeripheral::SdCard(_) => self.read_status::<SD>(card)?.ready_for_data(),
1204 };
1205
1206 if ready_for_data {
1207 return Ok(());
1208 }
1209 timeout -= 1;
1210 }
1211 Err(Error::SoftwareTimeout)
1212 }
1213 Err(e) => Err(e),
1214 }
1215 }
1216
1217 /// Write multiple data blocks.
1218 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error> {
1219 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1220
1221 // NOTE(unsafe) reinterpret buffer as &[u32]
1222 let buffer = unsafe {
1223 let ptr = blocks.as_ptr() as *const u32;
1224 let len = blocks.len() * 128;
1225 core::slice::from_raw_parts(ptr, len)
1226 };
1227
1228 // Always read 1 block of 512 bytes
1229 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1230 let address = match card.get_capacity() {
1231 CardCapacity::StandardCapacity => block_idx * 512,
1232 _ => block_idx,
1233 };
1234
1235 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1236
1237 let block_count = blocks.len();
1238
1239 let on_drop = OnDrop::new(|| Self::on_drop());
1240
1241 #[cfg(sdmmc_v1)]
1242 Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
1243
1244 // Setup write command
1245 let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9);
1246 InterruptHandler::<T>::enable_interrupts();
1247
1248 #[cfg(sdmmc_v2)]
1249 Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
1250
1251 let res = Self::complete_datapath_transfer(false).await;
1252
1253 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12
1254 Self::clear_interrupt_flags();
1255
1256 match res {
1257 Ok(_) => {
1258 on_drop.defuse();
1259 Self::stop_datapath();
1260 drop(transfer);
1261
1262 // TODO: Make this configurable
1263 let mut timeout: u32 = 0x00FF_FFFF;
1264
1265 // Try to read card status (ACMD13)
1266 while timeout > 0 {
1267 match self.read_sd_status().await {
1268 Ok(_) => return Ok(()),
1269 Err(Error::Timeout) => (), // Try again
1270 Err(e) => return Err(e),
1271 }
1272 timeout -= 1;
1273 }
1274 Err(Error::SoftwareTimeout)
1275 }
1276 Err(e) => Err(e),
1277 }
1278 }
1279
1280 /// Get a reference to the initialized card
1281 ///
1282 /// # Errors
1283 ///
1284 /// Returns Error::NoCard if [`init_sd_card`](#method.init_sd_card) or
1285 /// [`init_emmc`](#method.init_emmc) has not previously succeeded
1286 #[inline]
1287 pub fn card(&self) -> Result<&SdmmcPeripheral, Error> {
1288 self.card.as_ref().ok_or(Error::NoCard)
1289 }
1290
1291 /// Get the current SDMMC bus clock 1134 /// Get the current SDMMC bus clock
1292 pub fn clock(&self) -> Hertz { 1135 pub fn clock(&self) -> Hertz {
1293 self.clock 1136 self.clock
1294 } 1137 }
1295
1296 /// Set a specific cmd buffer rather than using the default stack allocated one.
1297 /// This is required if stack RAM cannot be used with DMA and usually manifests
1298 /// itself as an indefinite wait on a dma transfer because the dma peripheral
1299 /// cannot access the memory.
1300 pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) {
1301 self.cmd_block = Some(cmd_block)
1302 }
1303
1304 async fn init_internal(&mut self, freq: Hertz, mut card: SdmmcPeripheral) -> Result<(), Error> {
1305 let regs = T::regs();
1306 let ker_ck = T::frequency();
1307
1308 let bus_width = match (self.d3.is_some(), self.d7.is_some()) {
1309 (true, true) => {
1310 if matches!(card, SdmmcPeripheral::SdCard(_)) {
1311 return Err(Error::BusWidth);
1312 }
1313 BusWidth::Eight
1314 }
1315 (true, false) => BusWidth::Four,
1316 _ => BusWidth::One,
1317 };
1318
1319 // While the SD/SDIO card or eMMC is in identification mode,
1320 // the SDMMC_CK frequency must be no more than 400 kHz.
1321 let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
1322 self.clock = init_clock;
1323
1324 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1325 Self::wait_idle();
1326
1327 regs.clkcr().modify(|w| {
1328 w.set_widbus(0);
1329 w.set_clkdiv(clkdiv);
1330 #[cfg(sdmmc_v1)]
1331 w.set_bypass(_bypass);
1332 });
1333 regs.dtimer()
1334 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
1335
1336 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1337 Self::cmd(common_cmd::idle(), false)?;
1338
1339 match card {
1340 SdmmcPeripheral::SdCard(ref mut card) => {
1341 // Check if cards supports CMD8 (with pattern)
1342 Self::cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
1343 let cic = CIC::from(regs.respr(0).read().cardstatus());
1344
1345 if cic.pattern() != 0xAA {
1346 return Err(Error::UnsupportedCardVersion);
1347 }
1348
1349 if cic.voltage_accepted() & 1 == 0 {
1350 return Err(Error::UnsupportedVoltage);
1351 }
1352
1353 let ocr = loop {
1354 // Signal that next command is a app command
1355 Self::cmd(common_cmd::app_cmd(0), false)?; // CMD55
1356
1357 // 3.2-3.3V
1358 let voltage_window = 1 << 5;
1359 // Initialize card
1360 match Self::cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false) {
1361 // ACMD41
1362 Ok(_) => (),
1363 Err(Error::Crc) => (),
1364 Err(err) => return Err(err),
1365 }
1366 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
1367 if !ocr.is_busy() {
1368 // Power up done
1369 break ocr;
1370 }
1371 };
1372
1373 if ocr.high_capacity() {
1374 // Card is SDHC or SDXC or SDUC
1375 card.card_type = CardCapacity::HighCapacity;
1376 } else {
1377 card.card_type = CardCapacity::StandardCapacity;
1378 }
1379 card.ocr = ocr;
1380 }
1381 SdmmcPeripheral::Emmc(ref mut emmc) => {
1382 let ocr = loop {
1383 let high_voltage = 0b0 << 7;
1384 let access_mode = 0b10 << 29;
1385 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
1386 // Initialize card
1387 match Self::cmd(emmc_cmd::send_op_cond(op_cond), false) {
1388 Ok(_) => (),
1389 Err(Error::Crc) => (),
1390 Err(err) => return Err(err),
1391 }
1392 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
1393 if !ocr.is_busy() {
1394 // Power up done
1395 break ocr;
1396 }
1397 };
1398
1399 emmc.capacity = if ocr.access_mode() == 0b10 {
1400 // Card is SDHC or SDXC or SDUC
1401 CardCapacity::HighCapacity
1402 } else {
1403 CardCapacity::StandardCapacity
1404 };
1405 emmc.ocr = ocr;
1406 }
1407 }
1408
1409 Self::cmd(common_cmd::all_send_cid(), false)?; // CMD2
1410 let cid0 = regs.respr(0).read().cardstatus() as u128;
1411 let cid1 = regs.respr(1).read().cardstatus() as u128;
1412 let cid2 = regs.respr(2).read().cardstatus() as u128;
1413 let cid3 = regs.respr(3).read().cardstatus() as u128;
1414 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1415
1416 match card {
1417 SdmmcPeripheral::SdCard(ref mut card) => {
1418 card.cid = cid.into();
1419
1420 Self::cmd(sd_cmd::send_relative_address(), false)?;
1421 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
1422 card.rca = rca.address();
1423 }
1424 SdmmcPeripheral::Emmc(ref mut emmc) => {
1425 emmc.cid = cid.into();
1426
1427 emmc.rca = 1u16.into();
1428 Self::cmd(emmc_cmd::assign_relative_address(emmc.rca), false)?;
1429 }
1430 }
1431
1432 Self::cmd(common_cmd::send_csd(card.get_address()), false)?;
1433 let csd0 = regs.respr(0).read().cardstatus() as u128;
1434 let csd1 = regs.respr(1).read().cardstatus() as u128;
1435 let csd2 = regs.respr(2).read().cardstatus() as u128;
1436 let csd3 = regs.respr(3).read().cardstatus() as u128;
1437 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1438
1439 self.select_card(Some(card.get_address()))?;
1440
1441 let bus_width = match card {
1442 SdmmcPeripheral::SdCard(ref mut card) => {
1443 card.csd = csd.into();
1444
1445 self.get_scr(card).await?;
1446
1447 if !card.scr.bus_width_four() {
1448 BusWidth::One
1449 } else {
1450 BusWidth::Four
1451 }
1452 }
1453 SdmmcPeripheral::Emmc(ref mut emmc) => {
1454 emmc.csd = csd.into();
1455
1456 bus_width
1457 }
1458 };
1459
1460 // Set bus width
1461 let widbus = match bus_width {
1462 BusWidth::Eight => 2,
1463 BusWidth::Four => 1,
1464 BusWidth::One => 0,
1465 _ => unreachable!(),
1466 };
1467
1468 match card {
1469 SdmmcPeripheral::SdCard(ref mut card) => {
1470 let acmd_arg = match bus_width {
1471 BusWidth::Four if card.scr.bus_width_four() => 2,
1472 _ => 0,
1473 };
1474 Self::cmd(common_cmd::app_cmd(card.rca), false)?;
1475 Self::cmd(sd_cmd::cmd6(acmd_arg), false)?;
1476 }
1477 SdmmcPeripheral::Emmc(_) => {
1478 // Write bus width to ExtCSD byte 183
1479 Self::cmd(
1480 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
1481 false,
1482 )?;
1483
1484 // Wait for ready after R1b response
1485 loop {
1486 let status = self.read_status::<EMMC>(&card)?;
1487
1488 if status.ready_for_data() {
1489 break;
1490 }
1491 }
1492 }
1493 }
1494
1495 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1496 Self::wait_idle();
1497
1498 regs.clkcr().modify(|w| w.set_widbus(widbus));
1499
1500 // Set Clock
1501 if freq.0 <= 25_000_000 {
1502 // Final clock frequency
1503 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1504 } else {
1505 // Switch to max clock for SDR12
1506 self.clkcr_set_clkdiv(25_000_000, bus_width)?;
1507 }
1508
1509 self.card = Some(card);
1510
1511 match card {
1512 SdmmcPeripheral::SdCard(_) => {
1513 // Read status
1514 self.read_sd_status().await?;
1515
1516 if freq.0 > 25_000_000 {
1517 // Switch to SDR25
1518 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?;
1519
1520 if self.signalling == Signalling::SDR25 {
1521 // Set final clock frequency
1522 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1523
1524 if self.read_status::<SD>(self.card.as_ref().unwrap())?.state() != CurrentState::Transfer {
1525 return Err(Error::SignalingSwitchFailed);
1526 }
1527 }
1528 }
1529
1530 // Read status after signalling change
1531 self.read_sd_status().await?;
1532 }
1533 SdmmcPeripheral::Emmc(_) => {
1534 self.read_ext_csd().await?;
1535 }
1536 }
1537
1538 Ok(())
1539 }
1540
1541 /// Initializes card (if present) and sets the bus at the specified frequency.
1542 ///
1543 /// SD only.
1544 pub async fn init_sd_card(&mut self, freq: Hertz) -> Result<(), Error> {
1545 self.init_internal(freq, SdmmcPeripheral::SdCard(Card::default())).await
1546 }
1547
1548 /// Switch mode using CMD6.
1549 ///
1550 /// Attempt to set a new signalling mode. The selected
1551 /// signalling mode is returned. Expects the current clock
1552 /// frequency to be > 12.5MHz.
1553 ///
1554 /// SD only.
1555 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
1556 let _ = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1557 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
1558 // necessary"
1559
1560 let set_function = 0x8000_0000
1561 | match signalling {
1562 // See PLSS v7_10 Table 4-11
1563 Signalling::DDR50 => 0xFF_FF04,
1564 Signalling::SDR104 => 0xFF_1F03,
1565 Signalling::SDR50 => 0xFF_1F02,
1566 Signalling::SDR25 => 0xFF_FF01,
1567 Signalling::SDR12 => 0xFF_FF00,
1568 };
1569
1570 let status = match self.cmd_block.as_deref_mut() {
1571 Some(x) => x,
1572 None => &mut CmdBlock::new(),
1573 };
1574
1575 // Arm `OnDrop` after the buffer, so it will be dropped first
1576 let on_drop = OnDrop::new(|| Self::on_drop());
1577
1578 let transfer = Self::prepare_datapath_read(
1579 &self.config,
1580 #[cfg(sdmmc_v1)]
1581 &mut self.dma,
1582 status.as_mut(),
1583 64,
1584 6,
1585 );
1586 InterruptHandler::<T>::enable_interrupts();
1587 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
1588
1589 let res = Self::complete_datapath_transfer(true).await;
1590
1591 // Host is allowed to use the new functions at least 8
1592 // clocks after the end of the switch command
1593 // transaction. We know the current clock period is < 80ns,
1594 // so a total delay of 640ns is required here
1595 for _ in 0..300 {
1596 cortex_m::asm::nop();
1597 }
1598
1599 match res {
1600 Ok(_) => {
1601 on_drop.defuse();
1602 Self::stop_datapath();
1603 drop(transfer);
1604
1605 // Function Selection of Function Group 1
1606 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
1607
1608 match selection {
1609 0 => Ok(Signalling::SDR12),
1610 1 => Ok(Signalling::SDR25),
1611 2 => Ok(Signalling::SDR50),
1612 3 => Ok(Signalling::SDR104),
1613 4 => Ok(Signalling::DDR50),
1614 _ => Err(Error::UnsupportedCardType),
1615 }
1616 }
1617 Err(e) => Err(e),
1618 }
1619 }
1620
1621 /// Reads the SCR register.
1622 ///
1623 /// SD only.
1624 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
1625 // Read the 64-bit SCR register
1626 Self::cmd(common_cmd::set_block_length(8), false)?; // CMD16
1627 Self::cmd(common_cmd::app_cmd(card.rca), false)?;
1628
1629 let cmd_block = match self.cmd_block.as_deref_mut() {
1630 Some(x) => x,
1631 None => &mut CmdBlock::new(),
1632 };
1633 let scr = &mut cmd_block.0[..2];
1634
1635 // Arm `OnDrop` after the buffer, so it will be dropped first
1636 let on_drop = OnDrop::new(|| Self::on_drop());
1637
1638 let transfer = Self::prepare_datapath_read(
1639 &self.config,
1640 #[cfg(sdmmc_v1)]
1641 &mut self.dma,
1642 scr,
1643 8,
1644 3,
1645 );
1646 InterruptHandler::<T>::enable_interrupts();
1647 Self::cmd(sd_cmd::send_scr(), true)?;
1648
1649 let res = Self::complete_datapath_transfer(true).await;
1650
1651 if res.is_ok() {
1652 on_drop.defuse();
1653 Self::stop_datapath();
1654 drop(transfer);
1655
1656 unsafe {
1657 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
1658 card.scr = SCR(u64::from_be_bytes(*scr_bytes));
1659 }
1660 }
1661 res
1662 }
1663
1664 /// Reads the SD Status (ACMD13)
1665 ///
1666 /// SD only.
1667 async fn read_sd_status(&mut self) -> Result<(), Error> {
1668 let card = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1669 let rca = card.rca;
1670
1671 let cmd_block = match self.cmd_block.as_deref_mut() {
1672 Some(x) => x,
1673 None => &mut CmdBlock::new(),
1674 };
1675
1676 Self::cmd(common_cmd::set_block_length(64), false)?; // CMD16
1677 Self::cmd(common_cmd::app_cmd(rca), false)?; // APP
1678
1679 let status = cmd_block;
1680
1681 // Arm `OnDrop` after the buffer, so it will be dropped first
1682 let on_drop = OnDrop::new(|| Self::on_drop());
1683
1684 let transfer = Self::prepare_datapath_read(
1685 &self.config,
1686 #[cfg(sdmmc_v1)]
1687 &mut self.dma,
1688 status.as_mut(),
1689 64,
1690 6,
1691 );
1692 InterruptHandler::<T>::enable_interrupts();
1693 Self::cmd(sd_cmd::sd_status(), true)?;
1694
1695 let res = Self::complete_datapath_transfer(true).await;
1696
1697 if res.is_ok() {
1698 on_drop.defuse();
1699 Self::stop_datapath();
1700 drop(transfer);
1701
1702 for byte in status.iter_mut() {
1703 *byte = u32::from_be(*byte);
1704 }
1705 card.status = status.0.into();
1706 }
1707 res
1708 }
1709
1710 /// Initializes eMMC and sets the bus at the specified frequency.
1711 ///
1712 /// eMMC only.
1713 pub async fn init_emmc(&mut self, freq: Hertz) -> Result<(), Error> {
1714 self.init_internal(freq, SdmmcPeripheral::Emmc(Emmc::default())).await
1715 }
1716
1717 /// Gets the EXT_CSD register.
1718 ///
1719 /// eMMC only.
1720 async fn read_ext_csd(&mut self) -> Result<(), Error> {
1721 let card = self.card.as_mut().ok_or(Error::NoCard)?.get_emmc();
1722
1723 // Note: cmd_block can't be used because ExtCSD is too long to fit.
1724 let mut data_block = DataBlock([0u8; 512]);
1725
1726 // NOTE(unsafe) DataBlock uses align 4
1727 let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) };
1728
1729 Self::cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16
1730
1731 // Arm `OnDrop` after the buffer, so it will be dropped first
1732 let on_drop = OnDrop::new(|| Self::on_drop());
1733
1734 let transfer = Self::prepare_datapath_read(
1735 &self.config,
1736 #[cfg(sdmmc_v1)]
1737 &mut self.dma,
1738 buffer,
1739 512,
1740 9,
1741 );
1742 InterruptHandler::<T>::enable_interrupts();
1743 Self::cmd(emmc_cmd::send_ext_csd(), true)?;
1744
1745 let res = Self::complete_datapath_transfer(true).await;
1746
1747 if res.is_ok() {
1748 on_drop.defuse();
1749 Self::stop_datapath();
1750 drop(transfer);
1751
1752 card.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into();
1753 }
1754 res
1755 }
1756} 1138}
1757 1139
1758impl<'d, T: Instance> Drop for Sdmmc<'d, T> { 1140impl<'d> Drop for Sdmmc<'d> {
1759 fn drop(&mut self) { 1141 fn drop(&mut self) {
1760 T::Interrupt::disable(); 1142 // T::Interrupt::disable();
1761 Self::on_drop(); 1143 self.on_drop();
1762 1144
1763 critical_section::with(|_| { 1145 critical_section::with(|_| {
1764 self.clk.set_as_disconnected(); 1146 self.clk.set_as_disconnected();
@@ -1791,9 +1173,28 @@ impl<'d, T: Instance> Drop for Sdmmc<'d, T> {
1791 1173
1792////////////////////////////////////////////////////// 1174//////////////////////////////////////////////////////
1793 1175
1176type Regs = RegBlock;
1177
1178struct Info {
1179 regs: Regs,
1180 rcc: RccInfo,
1181}
1182
1183struct State {
1184 waker: AtomicWaker,
1185}
1186
1187impl State {
1188 const fn new() -> Self {
1189 Self {
1190 waker: AtomicWaker::new(),
1191 }
1192 }
1193}
1194
1794trait SealedInstance { 1195trait SealedInstance {
1795 fn regs() -> RegBlock; 1196 fn info() -> &'static Info;
1796 fn state() -> &'static AtomicWaker; 1197 fn state() -> &'static State;
1797} 1198}
1798 1199
1799/// SDMMC instance trait. 1200/// SDMMC instance trait.
@@ -1820,13 +1221,17 @@ dma_trait!(SdmmcDma, Instance);
1820foreach_peripheral!( 1221foreach_peripheral!(
1821 (sdmmc, $inst:ident) => { 1222 (sdmmc, $inst:ident) => {
1822 impl SealedInstance for peripherals::$inst { 1223 impl SealedInstance for peripherals::$inst {
1823 fn regs() -> RegBlock { 1224 fn info() -> &'static Info {
1824 crate::pac::$inst 1225 static INFO: Info = Info {
1226 regs: unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) },
1227 rcc: crate::peripherals::$inst::RCC_INFO,
1228 };
1229 &INFO
1825 } 1230 }
1826 1231
1827 fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker { 1232 fn state() -> &'static State {
1828 static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new(); 1233 static STATE: State = State::new();
1829 &WAKER 1234 &STATE
1830 } 1235 }
1831 } 1236 }
1832 1237
@@ -1835,46 +1240,3 @@ foreach_peripheral!(
1835 } 1240 }
1836 }; 1241 };
1837); 1242);
1838
1839impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> {
1840 type Error = Error;
1841 type Align = aligned::A4;
1842
1843 async fn read(
1844 &mut self,
1845 block_address: u32,
1846 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
1847 ) -> Result<(), Self::Error> {
1848 // TODO: I think block_address needs to be adjusted by the partition start offset
1849 if buf.len() == 1 {
1850 let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) };
1851 self.read_block(block_address, block).await?;
1852 } else {
1853 let blocks: &mut [DataBlock] =
1854 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) };
1855 self.read_blocks(block_address, blocks).await?;
1856 }
1857 Ok(())
1858 }
1859
1860 async fn write(
1861 &mut self,
1862 block_address: u32,
1863 buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
1864 ) -> Result<(), Self::Error> {
1865 // TODO: I think block_address needs to be adjusted by the partition start offset
1866 if buf.len() == 1 {
1867 let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) };
1868 self.write_block(block_address, block).await?;
1869 } else {
1870 let blocks: &[DataBlock] =
1871 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) };
1872 self.write_blocks(block_address, blocks).await?;
1873 }
1874 Ok(())
1875 }
1876
1877 async fn size(&mut self) -> Result<u64, Self::Error> {
1878 Ok(self.card()?.size())
1879 }
1880}
diff --git a/embassy-stm32/src/sdmmc/sd.rs b/embassy-stm32/src/sdmmc/sd.rs
new file mode 100644
index 000000000..6190226b8
--- /dev/null
+++ b/embassy-stm32/src/sdmmc/sd.rs
@@ -0,0 +1,693 @@
1use core::default::Default;
2use core::ops::{Deref, DerefMut};
3
4use sdio_host::emmc::{EMMC, ExtCSD};
5use sdio_host::sd::{BusWidth, CIC, CID, CSD, CardCapacity, CardStatus, CurrentState, OCR, RCA, SCR, SD, SDStatus};
6use sdio_host::{common_cmd, emmc_cmd, sd_cmd};
7
8use crate::sdmmc::{BlockSize, Error, Sdmmc, Signalling, block_size, bus_width_vals, slice8_mut, slice8_ref};
9use crate::time::{Hertz, mhz};
10
11/// Aligned data block for SDMMC transfers.
12///
13/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
14#[repr(align(4))]
15#[derive(Debug, Clone, PartialEq, Eq)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub struct DataBlock(pub [u32; 128]);
18
19impl DataBlock {
20 /// Create a new DataBlock
21 pub const fn new() -> Self {
22 DataBlock([0u32; 128])
23 }
24}
25
26impl Deref for DataBlock {
27 type Target = [u8; 512];
28
29 fn deref(&self) -> &Self::Target {
30 unwrap!(slice8_ref(&self.0[..]).try_into())
31 }
32}
33
34impl DerefMut for DataBlock {
35 fn deref_mut(&mut self) -> &mut Self::Target {
36 unwrap!(slice8_mut(&mut self.0[..]).try_into())
37 }
38}
39
40/// Command Block buffer for SDMMC command transfers.
41///
42/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required.
43#[derive(Debug, Clone, PartialEq, Eq)]
44#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45pub struct CmdBlock(pub [u32; 16]);
46
47impl CmdBlock {
48 /// Creates a new instance of CmdBlock
49 pub const fn new() -> Self {
50 Self([0u32; 16])
51 }
52}
53
54impl Deref for CmdBlock {
55 type Target = [u32; 16];
56
57 fn deref(&self) -> &Self::Target {
58 &self.0
59 }
60}
61
62impl DerefMut for CmdBlock {
63 fn deref_mut(&mut self) -> &mut Self::Target {
64 &mut self.0
65 }
66}
67
68/// Represents either an SD or EMMC card
69pub trait Addressable: Sized + Clone {
70 /// Associated type
71 type Ext;
72
73 /// Get this peripheral's address on the SDMMC bus
74 fn get_address(&self) -> u16;
75
76 /// Is this a standard or high capacity peripheral?
77 fn get_capacity(&self) -> CardCapacity;
78
79 /// Size in bytes
80 fn size(&self) -> u64;
81}
82
83/// Storage Device
84pub struct StorageDevice<'a, 'b, T: Addressable> {
85 info: T,
86 /// Inner member
87 pub sdmmc: &'a mut Sdmmc<'b>,
88}
89
90/// Card Storage Device
91impl<'a, 'b> StorageDevice<'a, 'b, Card> {
92 /// Create a new SD card
93 pub async fn new_sd_card(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
94 let mut s = Self {
95 info: Card::default(),
96 sdmmc,
97 };
98
99 s.acquire(cmd_block, freq).await?;
100
101 Ok(s)
102 }
103
104 /// Initializes the card into a known state (or at least tries to).
105 async fn acquire(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
106 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
107 let regs = self.sdmmc.info.regs;
108
109 let _bus_width = match self.sdmmc.bus_width() {
110 BusWidth::Eight => return Err(Error::BusWidth),
111 bus_width => bus_width,
112 };
113
114 // While the SD/SDIO card or eMMC is in identification mode,
115 // the SDMMC_CK frequency must be no more than 400 kHz.
116 self.sdmmc.init_idle()?;
117
118 // Check if cards supports CMD8 (with pattern)
119 self.sdmmc.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
120 let cic = CIC::from(regs.respr(0).read().cardstatus());
121
122 if cic.pattern() != 0xAA {
123 return Err(Error::UnsupportedCardVersion);
124 }
125
126 if cic.voltage_accepted() & 1 == 0 {
127 return Err(Error::UnsupportedVoltage);
128 }
129
130 let ocr = loop {
131 // Signal that next command is a app command
132 self.sdmmc.cmd(common_cmd::app_cmd(0), false)?; // CMD55
133
134 // 3.2-3.3V
135 let voltage_window = 1 << 5;
136 // Initialize card
137 match self
138 .sdmmc
139 .cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false)
140 {
141 // ACMD41
142 Ok(_) => (),
143 Err(Error::Crc) => (),
144 Err(err) => return Err(err),
145 }
146
147 let ocr: OCR<SD> = regs.respr(0).read().cardstatus().into();
148 if !ocr.is_busy() {
149 // Power up done
150 break ocr;
151 }
152 };
153
154 if ocr.high_capacity() {
155 // Card is SDHC or SDXC or SDUC
156 self.info.card_type = CardCapacity::HighCapacity;
157 } else {
158 self.info.card_type = CardCapacity::StandardCapacity;
159 }
160 self.info.ocr = ocr;
161
162 self.info.cid = self.sdmmc.get_cid()?.into();
163
164 self.sdmmc.cmd(sd_cmd::send_relative_address(), false)?;
165 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
166 self.info.rca = rca.address();
167
168 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
169 self.sdmmc.select_card(Some(self.info.get_address()))?;
170
171 self.info.scr = self.get_scr(cmd_block).await?;
172
173 let (bus_width, acmd_arg) = if !self.info.scr.bus_width_four() {
174 (BusWidth::One, 0)
175 } else {
176 (BusWidth::Four, 2)
177 };
178
179 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
180 self.sdmmc.cmd(sd_cmd::cmd6(acmd_arg), false)?;
181
182 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
183
184 // Read status
185 self.info.status = self.read_sd_status(cmd_block).await?;
186
187 if freq > mhz(25) {
188 // Switch to SDR25
189 self.sdmmc.signalling = self.switch_signalling_mode(cmd_block, Signalling::SDR25).await?;
190
191 if self.sdmmc.signalling == Signalling::SDR25 {
192 // Set final clock frequency
193 self.sdmmc.clkcr_set_clkdiv(freq, bus_width)?;
194
195 if self.sdmmc.read_status(&self.info)?.state() != CurrentState::Transfer {
196 return Err(Error::SignalingSwitchFailed);
197 }
198 }
199
200 // Read status after signalling change
201 self.read_sd_status(cmd_block).await?;
202 }
203
204 Ok(())
205 }
206
207 /// Switch mode using CMD6.
208 ///
209 /// Attempt to set a new signalling mode. The selected
210 /// signalling mode is returned. Expects the current clock
211 /// frequency to be > 12.5MHz.
212 ///
213 /// SD only.
214 async fn switch_signalling_mode(
215 &self,
216 cmd_block: &mut CmdBlock,
217 signalling: Signalling,
218 ) -> Result<Signalling, Error> {
219 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
220 // necessary"
221
222 let set_function = 0x8000_0000
223 | match signalling {
224 // See PLSS v7_10 Table 4-11
225 Signalling::DDR50 => 0xFF_FF04,
226 Signalling::SDR104 => 0xFF_1F03,
227 Signalling::SDR50 => 0xFF_1F02,
228 Signalling::SDR25 => 0xFF_FF01,
229 Signalling::SDR12 => 0xFF_FF00,
230 };
231
232 let buffer = &mut cmd_block.0[..64 / 4];
233
234 let transfer = self
235 .sdmmc
236 .prepare_datapath_read(buffer, block_size(size_of_val(buffer)), false);
237
238 self.sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
239
240 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
241
242 // Host is allowed to use the new functions at least 8
243 // clocks after the end of the switch command
244 // transaction. We know the current clock period is < 80ns,
245 // so a total delay of 640ns is required here
246 for _ in 0..300 {
247 cortex_m::asm::nop();
248 }
249
250 // Function Selection of Function Group 1
251 let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF;
252
253 match selection {
254 0 => Ok(Signalling::SDR12),
255 1 => Ok(Signalling::SDR25),
256 2 => Ok(Signalling::SDR50),
257 3 => Ok(Signalling::SDR104),
258 4 => Ok(Signalling::DDR50),
259 _ => Err(Error::UnsupportedCardType),
260 }
261 }
262
263 /// Reads the SCR register.
264 ///
265 /// SD only.
266 async fn get_scr(&self, cmd_block: &mut CmdBlock) -> Result<SCR, Error> {
267 // Read the 64-bit SCR register
268 self.sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16
269 self.sdmmc.cmd(common_cmd::app_cmd(self.info.rca), false)?;
270
271 let scr = &mut cmd_block.0[..2];
272
273 // Arm `OnDrop` after the buffer, so it will be dropped first
274
275 let transfer = self.sdmmc.prepare_datapath_read(scr, BlockSize::Size8, false);
276 self.sdmmc.cmd(sd_cmd::send_scr(), true)?;
277
278 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
279
280 Ok(SCR(u64::from_be_bytes(unwrap!(slice8_mut(scr).try_into()))))
281 }
282
283 /// Reads the SD Status (ACMD13)
284 ///
285 /// SD only.
286 async fn read_sd_status(&self, cmd_block: &mut CmdBlock) -> Result<SDStatus, Error> {
287 let rca = self.info.rca;
288
289 self.sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16
290 self.sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP
291
292 let buffer = &mut cmd_block.as_mut()[..64 / 4];
293
294 let transfer = self
295 .sdmmc
296 .prepare_datapath_read(buffer, block_size(size_of_val(buffer)), false);
297 self.sdmmc.cmd(sd_cmd::sd_status(), true)?;
298
299 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
300
301 for byte in cmd_block.iter_mut() {
302 *byte = u32::from_be(*byte);
303 }
304
305 Ok(cmd_block.0.into())
306 }
307}
308
309/// Emmc storage device
310impl<'a, 'b> StorageDevice<'a, 'b, Emmc> {
311 /// Create a new EMMC card
312 pub async fn new_emmc(sdmmc: &'a mut Sdmmc<'b>, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Self, Error> {
313 let mut s = Self {
314 info: Emmc::default(),
315 sdmmc,
316 };
317
318 s.acquire(cmd_block, freq).await?;
319
320 Ok(s)
321 }
322
323 async fn acquire(&mut self, _cmd_block: &mut CmdBlock, freq: Hertz) -> Result<(), Error> {
324 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
325 let regs = self.sdmmc.info.regs;
326
327 let bus_width = self.sdmmc.bus_width();
328
329 // While the SD/SDIO card or eMMC is in identification mode,
330 // the SDMMC_CK frequency must be no more than 400 kHz.
331 self.sdmmc.init_idle()?;
332
333 let ocr = loop {
334 let high_voltage = 0b0 << 7;
335 let access_mode = 0b10 << 29;
336 let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15;
337 // Initialize card
338 match self.sdmmc.cmd(emmc_cmd::send_op_cond(op_cond), false) {
339 Ok(_) => (),
340 Err(Error::Crc) => (),
341 Err(err) => return Err(err),
342 }
343 let ocr: OCR<EMMC> = regs.respr(0).read().cardstatus().into();
344 if !ocr.is_busy() {
345 // Power up done
346 break ocr;
347 }
348 };
349
350 self.info.capacity = if ocr.access_mode() == 0b10 {
351 // Card is SDHC or SDXC or SDUC
352 CardCapacity::HighCapacity
353 } else {
354 CardCapacity::StandardCapacity
355 };
356 self.info.ocr = ocr;
357
358 self.info.cid = self.sdmmc.get_cid()?.into();
359
360 self.info.rca = 1u16.into();
361 self.sdmmc
362 .cmd(emmc_cmd::assign_relative_address(self.info.rca), false)?;
363
364 self.info.csd = self.sdmmc.get_csd(self.info.get_address())?.into();
365 self.sdmmc.select_card(Some(self.info.get_address()))?;
366
367 let (widbus, _) = bus_width_vals(bus_width);
368
369 // Write bus width to ExtCSD byte 183
370 self.sdmmc.cmd(
371 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
372 false,
373 )?;
374
375 // Wait for ready after R1b response
376 loop {
377 let status = self.sdmmc.read_status(&self.info)?;
378
379 if status.ready_for_data() {
380 break;
381 }
382 }
383
384 self.sdmmc.clkcr_set_clkdiv(freq.clamp(mhz(0), mhz(25)), bus_width)?;
385 self.info.ext_csd = self.read_ext_csd().await?;
386
387 Ok(())
388 }
389
390 /// Gets the EXT_CSD register.
391 ///
392 /// eMMC only.
393 async fn read_ext_csd(&self) -> Result<ExtCSD, Error> {
394 // Note: cmd_block can't be used because ExtCSD is too long to fit.
395 let mut data_block = DataBlock::new();
396
397 self.sdmmc
398 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)
399 .unwrap(); // CMD16
400
401 let transfer = self
402 .sdmmc
403 .prepare_datapath_read(&mut data_block.0, block_size(size_of::<DataBlock>()), false);
404 self.sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?;
405
406 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
407
408 Ok(data_block.0.into())
409 }
410}
411
412/// Card or Emmc storage device
413impl<'a, 'b, A: Addressable> StorageDevice<'a, 'b, A> {
414 /// Write a block
415 pub fn card(&self) -> A {
416 self.info.clone()
417 }
418
419 /// Read a data block.
420 #[inline]
421 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
422 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
423 let card_capacity = self.info.get_capacity();
424
425 // Always read 1 block of 512 bytes
426 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
427 let address = match card_capacity {
428 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
429 _ => block_idx,
430 };
431 self.sdmmc
432 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
433
434 let transfer = self
435 .sdmmc
436 .prepare_datapath_read(&mut buffer.0, block_size(size_of::<DataBlock>()), false);
437 self.sdmmc.cmd(common_cmd::read_single_block(address), true)?;
438
439 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
440
441 Ok(())
442 }
443
444 /// Read multiple data blocks.
445 #[inline]
446 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
447 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
448 let card_capacity = self.info.get_capacity();
449
450 // NOTE(unsafe) reinterpret buffer as &mut [u32]
451 let buffer = unsafe {
452 core::slice::from_raw_parts_mut(
453 blocks.as_mut_ptr() as *mut u32,
454 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
455 )
456 };
457
458 // Always read 1 block of 512 bytes
459 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
460 let address = match card_capacity {
461 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
462 _ => block_idx,
463 };
464 self.sdmmc
465 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
466
467 let transfer = self
468 .sdmmc
469 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false);
470 self.sdmmc.cmd(common_cmd::read_multiple_blocks(address), true)?;
471
472 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
473
474 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
475 self.sdmmc.clear_interrupt_flags();
476
477 Ok(())
478 }
479
480 /// Write a data block.
481 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error>
482 where
483 CardStatus<A::Ext>: From<u32>,
484 {
485 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
486
487 // Always read 1 block of 512 bytes
488 // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
489 let address = match self.info.get_capacity() {
490 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
491 _ => block_idx,
492 };
493 self.sdmmc
494 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
495
496 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
497 #[cfg(sdmmc_v1)]
498 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
499
500 let transfer = self
501 .sdmmc
502 .prepare_datapath_write(&buffer.0, block_size(size_of::<DataBlock>()), false);
503
504 #[cfg(sdmmc_v2)]
505 self.sdmmc.cmd(common_cmd::write_single_block(address), true)?;
506
507 self.sdmmc.complete_datapath_transfer(transfer, true).await?;
508
509 // TODO: Make this configurable
510 let mut timeout: u32 = 0x00FF_FFFF;
511
512 while timeout > 0 {
513 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
514 if ready_for_data {
515 return Ok(());
516 }
517 timeout -= 1;
518 }
519
520 Err(Error::SoftwareTimeout)
521 }
522
523 /// Write multiple data blocks.
524 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error>
525 where
526 CardStatus<A::Ext>: From<u32>,
527 {
528 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
529
530 // NOTE(unsafe) reinterpret buffer as &[u32]
531 let buffer = unsafe {
532 core::slice::from_raw_parts(
533 blocks.as_ptr() as *const u32,
534 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
535 )
536 };
537 // Always read 1 block of 512 bytes
538 // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
539 let address = match self.info.get_capacity() {
540 CardCapacity::StandardCapacity => block_idx * size_of::<DataBlock>() as u32,
541 _ => block_idx,
542 };
543
544 self.sdmmc
545 .cmd(common_cmd::set_block_length(size_of::<DataBlock>() as u32), false)?; // CMD16
546
547 #[cfg(sdmmc_v1)]
548 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
549
550 // Setup write command
551 let transfer = self
552 .sdmmc
553 .prepare_datapath_write(buffer, block_size(size_of::<DataBlock>()), false);
554
555 #[cfg(sdmmc_v2)]
556 self.sdmmc.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
557
558 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
559
560 self.sdmmc.cmd(common_cmd::stop_transmission(), false)?; // CMD12
561 self.sdmmc.clear_interrupt_flags();
562
563 // TODO: Make this configurable
564 let mut timeout: u32 = 0x00FF_FFFF;
565
566 while timeout > 0 {
567 let ready_for_data = self.sdmmc.read_status(&self.info)?.ready_for_data();
568
569 if ready_for_data {
570 return Ok(());
571 }
572 timeout -= 1;
573 }
574 Err(Error::SoftwareTimeout)
575 }
576}
577
578#[derive(Clone, Copy, Debug, Default)]
579/// SD Card
580pub struct Card {
581 /// The type of this card
582 pub card_type: CardCapacity,
583 /// Operation Conditions Register
584 pub ocr: OCR<SD>,
585 /// Relative Card Address
586 pub rca: u16,
587 /// Card ID
588 pub cid: CID<SD>,
589 /// Card Specific Data
590 pub csd: CSD<SD>,
591 /// SD CARD Configuration Register
592 pub scr: SCR,
593 /// SD Status
594 pub status: SDStatus,
595}
596
597impl Addressable for Card {
598 type Ext = SD;
599
600 /// Get this peripheral's address on the SDMMC bus
601 fn get_address(&self) -> u16 {
602 self.rca
603 }
604
605 /// Is this a standard or high capacity peripheral?
606 fn get_capacity(&self) -> CardCapacity {
607 self.card_type
608 }
609
610 /// Size in bytes
611 fn size(&self) -> u64 {
612 u64::from(self.csd.block_count()) * 512
613 }
614}
615
616#[derive(Clone, Copy, Debug, Default)]
617/// eMMC storage
618pub struct Emmc {
619 /// The capacity of this card
620 pub capacity: CardCapacity,
621 /// Operation Conditions Register
622 pub ocr: OCR<EMMC>,
623 /// Relative Card Address
624 pub rca: u16,
625 /// Card ID
626 pub cid: CID<EMMC>,
627 /// Card Specific Data
628 pub csd: CSD<EMMC>,
629 /// Extended Card Specific Data
630 pub ext_csd: ExtCSD,
631}
632
633impl Addressable for Emmc {
634 type Ext = EMMC;
635
636 /// Get this peripheral's address on the SDMMC bus
637 fn get_address(&self) -> u16 {
638 self.rca
639 }
640
641 /// Is this a standard or high capacity peripheral?
642 fn get_capacity(&self) -> CardCapacity {
643 self.capacity
644 }
645
646 /// Size in bytes
647 fn size(&self) -> u64 {
648 u64::from(self.ext_csd.sector_count()) * 512
649 }
650}
651
652impl<'d, 'e, A: Addressable> block_device_driver::BlockDevice<512> for StorageDevice<'d, 'e, A> {
653 type Error = Error;
654 type Align = aligned::A4;
655
656 async fn read(
657 &mut self,
658 block_address: u32,
659 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
660 ) -> Result<(), Self::Error> {
661 // TODO: I think block_address needs to be adjusted by the partition start offset
662 if buf.len() == 1 {
663 let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut DataBlock) };
664 self.read_block(block_address, block).await?;
665 } else {
666 let blocks: &mut [DataBlock] =
667 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) };
668 self.read_blocks(block_address, blocks).await?;
669 }
670 Ok(())
671 }
672
673 async fn write(
674 &mut self,
675 block_address: u32,
676 buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
677 ) -> Result<(), Self::Error> {
678 // TODO: I think block_address needs to be adjusted by the partition start offset
679 if buf.len() == 1 {
680 let block = unsafe { &*(&buf[0] as *const _ as *const DataBlock) };
681 self.write_block(block_address, block).await?;
682 } else {
683 let blocks: &[DataBlock] =
684 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) };
685 self.write_blocks(block_address, blocks).await?;
686 }
687 Ok(())
688 }
689
690 async fn size(&mut self) -> Result<u64, Self::Error> {
691 Ok(self.info.size())
692 }
693}
diff --git a/embassy-stm32/src/sdmmc/sdio.rs b/embassy-stm32/src/sdmmc/sdio.rs
new file mode 100644
index 000000000..1412b21fc
--- /dev/null
+++ b/embassy-stm32/src/sdmmc/sdio.rs
@@ -0,0 +1,177 @@
1use core::ops::{Deref, DerefMut};
2
3use sdio_host::common_cmd::{R1, Rz, cmd};
4use sdio_host::sd::BusWidth;
5use sdio_host::sd_cmd;
6
7use crate::sdmmc::{Error, Sdmmc, block_size, slice8_mut, slice8_ref};
8use crate::time::Hertz;
9
10/// Aligned data block for SDMMC transfers.
11///
12/// This is a 64-byte array, aligned to 4 bytes to satisfy DMA requirements.
13#[repr(align(4))]
14#[derive(Debug, Clone, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub struct DataBlock(pub [u32; 16]);
17
18impl DataBlock {
19 /// Create a new DataBlock
20 pub const fn new() -> Self {
21 DataBlock([0u32; 16])
22 }
23}
24
25impl Deref for DataBlock {
26 type Target = [u8; 64];
27
28 fn deref(&self) -> &Self::Target {
29 unwrap!(slice8_ref(&self.0[..]).try_into())
30 }
31}
32
33impl DerefMut for DataBlock {
34 fn deref_mut(&mut self) -> &mut Self::Target {
35 unwrap!(slice8_mut(&mut self.0[..]).try_into())
36 }
37}
38
39/// Storage Device
40pub struct SerialDataInterface<'a, 'b> {
41 /// Inner member
42 pub sdmmc: &'a mut Sdmmc<'b>,
43}
44
45/// Card Storage Device
46impl<'a, 'b> SerialDataInterface<'a, 'b> {
47 /// Create a new SD card
48 pub async fn new(sdmmc: &'a mut Sdmmc<'b>, freq: Hertz) -> Result<Self, Error> {
49 let mut s = Self { sdmmc };
50
51 s.acquire(freq).await?;
52
53 Ok(s)
54 }
55
56 /// Initializes the card into a known state (or at least tries to).
57 async fn acquire(&mut self, _freq: Hertz) -> Result<(), Error> {
58 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
59
60 let _bus_width = match self.sdmmc.bus_width() {
61 BusWidth::Eight => return Err(Error::BusWidth),
62 bus_width => bus_width,
63 };
64
65 // While the SD/SDIO card or eMMC is in identification mode,
66 // the SDMMC_CK frequency must be no more than 400 kHz.
67 self.sdmmc.init_idle()?;
68
69 self.sdmmc.cmd(cmd::<Rz>(5, 0), false)?;
70
71 // Get RCA
72 let rca = self.sdmmc.cmd(sd_cmd::send_relative_address(), false)?;
73
74 // Select the card with RCA
75 self.sdmmc.select_card(Some(rca.try_into().unwrap()))?;
76
77 Ok(())
78 }
79
80 /// Set the bus to the 4-bit high-speed frequency
81 pub fn set_bus_to_high_speed(&mut self, frequency: Hertz) -> Result<(), Error> {
82 self.sdmmc.clkcr_set_clkdiv(frequency, BusWidth::Four)?;
83
84 Ok(())
85 }
86
87 /// Run cmd52
88 pub async fn cmd52(&mut self, arg: u32) -> Result<u32, Error> {
89 self.sdmmc.cmd(cmd::<R1>(52, arg), false)
90 }
91
92 /// Read in block mode using cmd53
93 pub async fn cmd53_block_read(&mut self, arg: u32, blocks: &mut [DataBlock]) -> Result<(), Error> {
94 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
95
96 // NOTE(unsafe) reinterpret buffer as &mut [u32]
97 let buffer = unsafe {
98 core::slice::from_raw_parts_mut(
99 blocks.as_mut_ptr() as *mut u32,
100 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
101 )
102 };
103
104 let transfer = self
105 .sdmmc
106 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false);
107 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
108
109 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
110 self.sdmmc.clear_interrupt_flags();
111
112 Ok(())
113 }
114
115 /// Read in multibyte mode using cmd53
116 pub async fn cmd53_byte_read(&mut self, arg: u32, buffer: &mut [u32]) -> Result<(), Error> {
117 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
118
119 let transfer = self
120 .sdmmc
121 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), true);
122 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
123
124 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
125 self.sdmmc.clear_interrupt_flags();
126
127 Ok(())
128 }
129
130 /// Write in block mode using cmd53
131 pub async fn cmd53_block_write(&mut self, arg: u32, blocks: &[DataBlock]) -> Result<(), Error> {
132 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
133
134 // NOTE(unsafe) reinterpret buffer as &mut [u32]
135 let buffer = unsafe {
136 core::slice::from_raw_parts_mut(
137 blocks.as_ptr() as *mut u32,
138 blocks.len() * size_of::<DataBlock>() / size_of::<u32>(),
139 )
140 };
141
142 #[cfg(sdmmc_v1)]
143 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
144
145 let transfer = self
146 .sdmmc
147 .prepare_datapath_read(buffer, block_size(size_of::<DataBlock>()), false);
148
149 #[cfg(sdmmc_v2)]
150 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
151
152 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
153 self.sdmmc.clear_interrupt_flags();
154
155 Ok(())
156 }
157
158 /// Write in multibyte mode using cmd53
159 pub async fn cmd53_byte_write(&mut self, arg: u32, buffer: &[u32]) -> Result<(), Error> {
160 let _scoped_block_stop = self.sdmmc.info.rcc.block_stop();
161
162 #[cfg(sdmmc_v1)]
163 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
164
165 let transfer = self
166 .sdmmc
167 .prepare_datapath_write(buffer, block_size(size_of::<DataBlock>()), true);
168
169 #[cfg(sdmmc_v2)]
170 self.sdmmc.cmd(cmd::<Rz>(53, arg), true)?;
171
172 self.sdmmc.complete_datapath_transfer(transfer, false).await?;
173 self.sdmmc.clear_interrupt_flags();
174
175 Ok(())
176 }
177}
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index abb80ed26..c90e0cef4 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -54,6 +54,16 @@ pub enum BitOrder {
54 MsbFirst, 54 MsbFirst,
55} 55}
56 56
57/// SPI Direction.
58#[derive(Debug, PartialEq, Eq, Clone, Copy)]
59#[cfg_attr(feature = "defmt", derive(defmt::Format))]
60pub enum Direction {
61 /// Transmit
62 Transmit,
63 /// Receive
64 Receive,
65}
66
57/// SPI configuration. 67/// SPI configuration.
58#[non_exhaustive] 68#[non_exhaustive]
59#[derive(Copy, Clone)] 69#[derive(Copy, Clone)]
@@ -72,6 +82,10 @@ pub struct Config {
72 /// signal rise/fall speed (slew rate) - defaults to `Medium`. 82 /// signal rise/fall speed (slew rate) - defaults to `Medium`.
73 /// Increase for high SPI speeds. Change to `Low` to reduce ringing. 83 /// Increase for high SPI speeds. Change to `Low` to reduce ringing.
74 pub gpio_speed: Speed, 84 pub gpio_speed: Speed,
85 /// If True sets SSOE to zero even if SPI is in Master Mode.
86 /// NSS output enabled (SSM = 0, SSOE = 1): The NSS signal is driven low when the master starts the communication and is kept low until the SPI is disabled.
87 /// NSS output disabled (SSM = 0, SSOE = 0): For devices set as slave, the NSS pin acts as a classical NSS input: the slave is selected when NSS is low and deselected when NSS high.
88 pub nss_output_disable: bool,
75} 89}
76 90
77impl Default for Config { 91impl Default for Config {
@@ -82,6 +96,7 @@ impl Default for Config {
82 frequency: Hertz(1_000_000), 96 frequency: Hertz(1_000_000),
83 miso_pull: Pull::None, 97 miso_pull: Pull::None,
84 gpio_speed: Speed::VeryHigh, 98 gpio_speed: Speed::VeryHigh,
99 nss_output_disable: false,
85 } 100 }
86 } 101 }
87} 102}
@@ -215,13 +230,35 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
215 let cpol = config.raw_polarity(); 230 let cpol = config.raw_polarity();
216 let lsbfirst = config.raw_byte_order(); 231 let lsbfirst = config.raw_byte_order();
217 232
218 self.info.rcc.enable_and_reset(); 233 self.info.rcc.enable_and_reset_without_stop();
234
235 /*
236 - Software NSS management (SSM = 1)
237 The slave select information is driven internally by the value of the SSI bit in the
238 SPI_CR1 register. The external NSS pin remains free for other application uses.
239
240 - Hardware NSS management (SSM = 0)
241 Two configurations are possible depending on the NSS output configuration (SSOE bit
242 in register SPI_CR1).
243
244 -- NSS output enabled (SSM = 0, SSOE = 1)
245 This configuration is used only when the device operates in master mode. The
246 NSS signal is driven low when the master starts the communication and is kept
247 low until the SPI is disabled.
248
249 -- NSS output disabled (SSM = 0, SSOE = 0)
250 This configuration allows multimaster capability for devices operating in master
251 mode. For devices set as slave, the NSS pin acts as a classical NSS input: the
252 slave is selected when NSS is low and deselected when NSS high
253 */
254 let ssm = self.nss.is_none();
219 255
220 let regs = self.info.regs; 256 let regs = self.info.regs;
221 #[cfg(any(spi_v1, spi_v2))] 257 #[cfg(any(spi_v1, spi_v2))]
222 { 258 {
259 let ssoe = CM::MASTER == vals::Mstr::MASTER && !config.nss_output_disable;
223 regs.cr2().modify(|w| { 260 regs.cr2().modify(|w| {
224 w.set_ssoe(false); 261 w.set_ssoe(ssoe);
225 }); 262 });
226 regs.cr1().modify(|w| { 263 regs.cr1().modify(|w| {
227 w.set_cpha(cpha); 264 w.set_cpha(cpha);
@@ -232,7 +269,7 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
232 w.set_spe(true); 269 w.set_spe(true);
233 w.set_lsbfirst(lsbfirst); 270 w.set_lsbfirst(lsbfirst);
234 w.set_ssi(CM::MASTER == vals::Mstr::MASTER); 271 w.set_ssi(CM::MASTER == vals::Mstr::MASTER);
235 w.set_ssm(CM::MASTER == vals::Mstr::MASTER); 272 w.set_ssm(ssm);
236 w.set_crcen(false); 273 w.set_crcen(false);
237 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); 274 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL);
238 // we're doing "fake rxonly", by actually writing one 275 // we're doing "fake rxonly", by actually writing one
@@ -244,11 +281,12 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
244 } 281 }
245 #[cfg(spi_v3)] 282 #[cfg(spi_v3)]
246 { 283 {
284 let ssoe = CM::MASTER == vals::Mstr::MASTER && !config.nss_output_disable;
247 regs.cr2().modify(|w| { 285 regs.cr2().modify(|w| {
248 let (ds, frxth) = <u8 as SealedWord>::CONFIG; 286 let (ds, frxth) = <u8 as SealedWord>::CONFIG;
249 w.set_frxth(frxth); 287 w.set_frxth(frxth);
250 w.set_ds(ds); 288 w.set_ds(ds);
251 w.set_ssoe(false); 289 w.set_ssoe(ssoe);
252 }); 290 });
253 regs.cr1().modify(|w| { 291 regs.cr1().modify(|w| {
254 w.set_cpha(cpha); 292 w.set_cpha(cpha);
@@ -258,7 +296,7 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
258 w.set_br(br); 296 w.set_br(br);
259 w.set_lsbfirst(lsbfirst); 297 w.set_lsbfirst(lsbfirst);
260 w.set_ssi(CM::MASTER == vals::Mstr::MASTER); 298 w.set_ssi(CM::MASTER == vals::Mstr::MASTER);
261 w.set_ssm(CM::MASTER == vals::Mstr::MASTER); 299 w.set_ssm(ssm);
262 w.set_crcen(false); 300 w.set_crcen(false);
263 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); 301 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL);
264 w.set_spe(true); 302 w.set_spe(true);
@@ -266,14 +304,14 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
266 } 304 }
267 #[cfg(any(spi_v4, spi_v5, spi_v6))] 305 #[cfg(any(spi_v4, spi_v5, spi_v6))]
268 { 306 {
307 let ssoe = CM::MASTER == vals::Master::MASTER && !config.nss_output_disable;
269 regs.ifcr().write(|w| w.0 = 0xffff_ffff); 308 regs.ifcr().write(|w| w.0 = 0xffff_ffff);
270 regs.cfg2().modify(|w| { 309 regs.cfg2().modify(|w| {
271 //w.set_ssoe(true); 310 w.set_ssoe(ssoe);
272 w.set_ssoe(false);
273 w.set_cpha(cpha); 311 w.set_cpha(cpha);
274 w.set_cpol(cpol); 312 w.set_cpol(cpol);
275 w.set_lsbfirst(lsbfirst); 313 w.set_lsbfirst(lsbfirst);
276 w.set_ssm(CM::MASTER == vals::Master::MASTER); 314 w.set_ssm(ssm);
277 w.set_master(CM::MASTER); 315 w.set_master(CM::MASTER);
278 w.set_comm(vals::Comm::FULL_DUPLEX); 316 w.set_comm(vals::Comm::FULL_DUPLEX);
279 w.set_ssom(vals::Ssom::ASSERTED); 317 w.set_ssom(vals::Ssom::ASSERTED);
@@ -348,6 +386,20 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
348 Ok(()) 386 Ok(())
349 } 387 }
350 388
389 /// Set SPI direction
390 #[cfg(any(spi_v1, spi_v2, spi_v3))]
391 pub fn set_direction(&mut self, dir: Option<Direction>) {
392 let (bidimode, bidioe) = match dir {
393 Some(Direction::Transmit) => (vals::Bidimode::BIDIRECTIONAL, vals::Bidioe::TRANSMIT),
394 Some(Direction::Receive) => (vals::Bidimode::BIDIRECTIONAL, vals::Bidioe::RECEIVE),
395 None => (vals::Bidimode::UNIDIRECTIONAL, vals::Bidioe::TRANSMIT),
396 };
397 self.info.regs.cr1().modify(|w| {
398 w.set_bidimode(bidimode);
399 w.set_bidioe(bidioe);
400 });
401 }
402
351 /// Get current SPI configuration. 403 /// Get current SPI configuration.
352 pub fn get_current_config(&self) -> Config { 404 pub fn get_current_config(&self) -> Config {
353 #[cfg(any(spi_v1, spi_v2, spi_v3))] 405 #[cfg(any(spi_v1, spi_v2, spi_v3))]
@@ -357,6 +409,11 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
357 #[cfg(any(spi_v4, spi_v5, spi_v6))] 409 #[cfg(any(spi_v4, spi_v5, spi_v6))]
358 let cfg1 = self.info.regs.cfg1().read(); 410 let cfg1 = self.info.regs.cfg1().read();
359 411
412 #[cfg(any(spi_v1, spi_v2, spi_v3))]
413 let ssoe = self.info.regs.cr2().read().ssoe();
414 #[cfg(any(spi_v4, spi_v5, spi_v6))]
415 let ssoe = cfg.ssoe();
416
360 let polarity = if cfg.cpol() == vals::Cpol::IDLE_LOW { 417 let polarity = if cfg.cpol() == vals::Cpol::IDLE_LOW {
361 Polarity::IdleLow 418 Polarity::IdleLow
362 } else { 419 } else {
@@ -386,12 +443,16 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
386 443
387 let frequency = compute_frequency(self.kernel_clock, br); 444 let frequency = compute_frequency(self.kernel_clock, br);
388 445
446 // NSS output disabled if SSOE=0 or if SSM=1 software slave management enabled
447 let nss_output_disable = !ssoe || cfg.ssm();
448
389 Config { 449 Config {
390 mode: Mode { polarity, phase }, 450 mode: Mode { polarity, phase },
391 bit_order, 451 bit_order,
392 frequency, 452 frequency,
393 miso_pull, 453 miso_pull,
394 gpio_speed: self.gpio_speed, 454 gpio_speed: self.gpio_speed,
455 nss_output_disable,
395 } 456 }
396 } 457 }
397 458
@@ -708,6 +769,30 @@ impl<'d> Spi<'d, Async, Master> {
708 ) 769 )
709 } 770 }
710 771
772 /// Create a new SPI driver, in bidirectional mode, specifically in tranmit mode
773 #[cfg(any(spi_v1, spi_v2, spi_v3))]
774 pub fn new_bidi<T: Instance, #[cfg(afio)] A>(
775 peri: Peri<'d, T>,
776 sck: Peri<'d, if_afio!(impl SckPin<T, A>)>,
777 sdio: Peri<'d, if_afio!(impl MosiPin<T, A>)>,
778 tx_dma: Peri<'d, impl TxDma<T>>,
779 rx_dma: Peri<'d, impl RxDma<T>>,
780 config: Config,
781 ) -> Self {
782 let mut this = Self::new_inner(
783 peri,
784 new_pin!(sck, config.sck_af()),
785 new_pin!(sdio, AfType::output(OutputType::PushPull, config.gpio_speed)),
786 None,
787 None,
788 new_dma!(tx_dma),
789 new_dma!(rx_dma),
790 config,
791 );
792 this.set_direction(Some(Direction::Transmit));
793 this
794 }
795
711 /// Create a new SPI driver, in TX-only mode, without SCK pin. 796 /// Create a new SPI driver, in TX-only mode, without SCK pin.
712 /// 797 ///
713 /// This can be useful for bit-banging non-SPI protocols. 798 /// This can be useful for bit-banging non-SPI protocols.
@@ -763,6 +848,7 @@ impl<'d> Spi<'d, Async, Master> {
763impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> { 848impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> {
764 /// SPI write, using DMA. 849 /// SPI write, using DMA.
765 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> { 850 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> {
851 let _scoped_block_stop = self.info.rcc.block_stop();
766 if data.is_empty() { 852 if data.is_empty() {
767 return Ok(()); 853 return Ok(());
768 } 854 }
@@ -794,6 +880,7 @@ impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> {
794 /// SPI read, using DMA. 880 /// SPI read, using DMA.
795 #[cfg(any(spi_v4, spi_v5, spi_v6))] 881 #[cfg(any(spi_v4, spi_v5, spi_v6))]
796 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { 882 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
883 let _scoped_block_stop = self.info.rcc.block_stop();
797 if data.is_empty() { 884 if data.is_empty() {
798 return Ok(()); 885 return Ok(());
799 } 886 }
@@ -881,6 +968,7 @@ impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> {
881 /// SPI read, using DMA. 968 /// SPI read, using DMA.
882 #[cfg(any(spi_v1, spi_v2, spi_v3))] 969 #[cfg(any(spi_v1, spi_v2, spi_v3))]
883 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { 970 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
971 let _scoped_block_stop = self.info.rcc.block_stop();
884 if data.is_empty() { 972 if data.is_empty() {
885 return Ok(()); 973 return Ok(());
886 } 974 }
@@ -928,6 +1016,7 @@ impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> {
928 } 1016 }
929 1017
930 async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error> { 1018 async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error> {
1019 let _scoped_block_stop = self.info.rcc.block_stop();
931 assert_eq!(read.len(), write.len()); 1020 assert_eq!(read.len(), write.len());
932 if read.len() == 0 { 1021 if read.len() == 0 {
933 return Ok(()); 1022 return Ok(());
@@ -979,6 +1068,8 @@ impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> {
979 /// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored. 1068 /// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
980 /// If `write` is shorter it is padded with zero bytes. 1069 /// If `write` is shorter it is padded with zero bytes.
981 pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { 1070 pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
1071 let _scoped_block_stop = self.info.rcc.block_stop();
1072
982 self.transfer_inner(read, write).await 1073 self.transfer_inner(read, write).await
983 } 1074 }
984 1075
@@ -986,6 +1077,8 @@ impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> {
986 /// 1077 ///
987 /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time. 1078 /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
988 pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { 1079 pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
1080 let _scoped_block_stop = self.info.rcc.block_stop();
1081
989 self.transfer_inner(data, data).await 1082 self.transfer_inner(data, data).await
990 } 1083 }
991} 1084}
diff --git a/embassy-stm32/src/time.rs b/embassy-stm32/src/time.rs
index 532877f70..88a28ee3d 100644
--- a/embassy-stm32/src/time.rs
+++ b/embassy-stm32/src/time.rs
@@ -4,7 +4,7 @@ use core::fmt::Display;
4use core::ops::{Div, Mul}; 4use core::ops::{Div, Mul};
5 5
6/// Hertz 6/// Hertz
7#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)] 7#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Default)]
8pub struct Hertz(pub u32); 8pub struct Hertz(pub u32);
9 9
10impl Display for Hertz { 10impl Display for Hertz {
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index cfcf5f3fd..ed5d902bd 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -329,6 +329,12 @@ impl RtcDriver {
329 regs_gp16().cr1().modify(|w| w.set_cen(true)); 329 regs_gp16().cr1().modify(|w| w.set_cen(true));
330 } 330 }
331 331
332 #[cfg(feature = "low-power")]
333 /// Returns whether time is currently stopped
334 pub(crate) fn is_stopped(&self) -> bool {
335 !regs_gp16().cr1().read().cen()
336 }
337
332 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { 338 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
333 let r = regs_gp16(); 339 let r = regs_gp16();
334 340
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 77f19a37b..620d7858e 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -2,16 +2,17 @@
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
5pub use stm32_metapac::timer::vals::{Ckd, Mms2, Ossi, Ossr};
6
7use super::low_level::{CountingMode, OutputPolarity, Timer}; 5use super::low_level::{CountingMode, OutputPolarity, Timer};
8use super::simple_pwm::PwmPin; 6use super::simple_pwm::PwmPin;
9use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin}; 7use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin};
10use crate::Peri; 8use crate::Peri;
11use crate::gpio::{AnyPin, OutputType}; 9use crate::dma::word::Word;
10use crate::gpio::{AfType, AnyPin, OutputType};
11pub use crate::pac::timer::vals::{Ccds, Ckd, Mms2, Ossi, Ossr};
12use crate::time::Hertz; 12use crate::time::Hertz;
13use crate::timer::TimerChannel; 13use crate::timer::TimerChannel;
14use crate::timer::low_level::OutputCompareMode; 14use crate::timer::low_level::OutputCompareMode;
15use crate::timer::simple_pwm::PwmPinConfig;
15 16
16/// Complementary PWM pin wrapper. 17/// Complementary PWM pin wrapper.
17/// 18///
@@ -27,9 +28,27 @@ impl<'d, T: AdvancedInstance4Channel, C: TimerChannel, #[cfg(afio)] A> if_afio!(
27 pub fn new(pin: Peri<'d, if_afio!(impl TimerComplementaryPin<T, C, A>)>, output_type: OutputType) -> Self { 28 pub fn new(pin: Peri<'d, if_afio!(impl TimerComplementaryPin<T, C, A>)>, output_type: OutputType) -> Self {
28 critical_section::with(|_| { 29 critical_section::with(|_| {
29 pin.set_low(); 30 pin.set_low();
30 set_as_af!( 31 set_as_af!(pin, AfType::output(output_type, crate::gpio::Speed::VeryHigh));
31 pin, 32 });
32 crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh) 33 ComplementaryPwmPin {
34 pin: pin.into(),
35 phantom: PhantomData,
36 }
37 }
38
39 /// Create a new PWM pin instance with config.
40 pub fn new_with_config(
41 pin: Peri<'d, if_afio!(impl TimerComplementaryPin<T, C, A>)>,
42 pin_config: PwmPinConfig,
43 ) -> Self {
44 critical_section::with(|_| {
45 pin.set_low();
46 #[cfg(gpio_v1)]
47 set_as_af!(pin, AfType::output(pin_config.output_type, pin_config.speed));
48 #[cfg(gpio_v2)]
49 pin.set_as_af(
50 pin.af_num(),
51 AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
33 ); 52 );
34 }); 53 });
35 ComplementaryPwmPin { 54 ComplementaryPwmPin {
@@ -176,20 +195,20 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
176 /// Get max duty value. 195 /// Get max duty value.
177 /// 196 ///
178 /// This value depends on the configured frequency and the timer's clock rate from RCC. 197 /// This value depends on the configured frequency and the timer's clock rate from RCC.
179 pub fn get_max_duty(&self) -> u16 { 198 pub fn get_max_duty(&self) -> u32 {
180 if self.inner.get_counting_mode().is_center_aligned() { 199 if self.inner.get_counting_mode().is_center_aligned() {
181 self.inner.get_max_compare_value() as u16 200 self.inner.get_max_compare_value().into()
182 } else { 201 } else {
183 self.inner.get_max_compare_value() as u16 + 1 202 self.inner.get_max_compare_value().into() + 1
184 } 203 }
185 } 204 }
186 205
187 /// Set the duty for a given channel. 206 /// Set the duty for a given channel.
188 /// 207 ///
189 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. 208 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
190 pub fn set_duty(&mut self, channel: Channel, duty: u16) { 209 pub fn set_duty(&mut self, channel: Channel, duty: u32) {
191 assert!(duty <= self.get_max_duty()); 210 assert!(duty <= self.get_max_duty());
192 self.inner.set_compare_value(channel, duty as _) 211 self.inner.set_compare_value(channel, unwrap!(duty.try_into()))
193 } 212 }
194 213
195 /// Set the output polarity for a given channel. 214 /// Set the output polarity for a given channel.
@@ -219,9 +238,34 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
219 /// Generate a sequence of PWM waveform 238 /// Generate a sequence of PWM waveform
220 /// 239 ///
221 /// Note: 240 /// Note:
241 /// The DMA channel provided does not need to correspond to the requested channel.
242 pub async fn waveform<C: TimerChannel, W: Word + Into<T::Word>>(
243 &mut self,
244 dma: Peri<'_, impl super::Dma<T, C>>,
245 channel: Channel,
246 duty: &[W],
247 ) {
248 self.inner.enable_channel(channel, true);
249 self.inner.enable_channel(C::CHANNEL, true);
250 self.inner.clamp_compare_value::<W>(channel);
251 self.inner.set_cc_dma_selection(Ccds::ON_UPDATE);
252 self.inner.set_cc_dma_enable_state(C::CHANNEL, true);
253 self.inner.setup_channel_update_dma(dma, channel, duty).await;
254 self.inner.set_cc_dma_enable_state(C::CHANNEL, false);
255 }
256
257 /// Generate a sequence of PWM waveform
258 ///
259 /// Note:
222 /// you will need to provide corresponding TIMx_UP DMA channel to use this method. 260 /// you will need to provide corresponding TIMx_UP DMA channel to use this method.
223 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { 261 pub async fn waveform_up<W: Word + Into<T::Word>>(
262 &mut self,
263 dma: Peri<'_, impl super::UpDma<T>>,
264 channel: Channel,
265 duty: &[W],
266 ) {
224 self.inner.enable_channel(channel, true); 267 self.inner.enable_channel(channel, true);
268 self.inner.clamp_compare_value::<W>(channel);
225 self.inner.enable_update_dma(true); 269 self.inner.enable_update_dma(true);
226 self.inner.setup_update_dma(dma, channel, duty).await; 270 self.inner.setup_update_dma(dma, channel, duty).await;
227 self.inner.enable_update_dma(false); 271 self.inner.enable_update_dma(false);
@@ -256,13 +300,21 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
256 /// Also be aware that embassy timers use one of timers internally. It is possible to 300 /// Also be aware that embassy timers use one of timers internally. It is possible to
257 /// switch this timer by using `time-driver-timX` feature. 301 /// switch this timer by using `time-driver-timX` feature.
258 /// 302 ///
259 pub async fn waveform_up_multi_channel( 303 pub async fn waveform_up_multi_channel<W: Word + Into<T::Word>>(
260 &mut self, 304 &mut self,
261 dma: Peri<'_, impl super::UpDma<T>>, 305 dma: Peri<'_, impl super::UpDma<T>>,
262 starting_channel: Channel, 306 starting_channel: Channel,
263 ending_channel: Channel, 307 ending_channel: Channel,
264 duty: &[u16], 308 duty: &[W],
265 ) { 309 ) {
310 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
311 .iter()
312 .filter(|ch| ch.index() >= starting_channel.index())
313 .filter(|ch| ch.index() <= ending_channel.index())
314 .for_each(|ch| {
315 self.inner.enable_channel(*ch, true);
316 self.inner.clamp_compare_value::<W>(*ch);
317 });
266 self.inner.enable_update_dma(true); 318 self.inner.enable_update_dma(true);
267 self.inner 319 self.inner
268 .setup_update_dma_burst(dma, starting_channel, ending_channel, duty) 320 .setup_update_dma_burst(dma, starting_channel, ending_channel, duty)
@@ -291,20 +343,20 @@ impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<
291 } 343 }
292 344
293 fn get_duty(&self, channel: Self::Channel) -> Self::Duty { 345 fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
294 self.inner.get_compare_value(channel) as u16 346 unwrap!(self.inner.get_compare_value(channel).try_into())
295 } 347 }
296 348
297 fn get_max_duty(&self) -> Self::Duty { 349 fn get_max_duty(&self) -> Self::Duty {
298 if self.inner.get_counting_mode().is_center_aligned() { 350 if self.inner.get_counting_mode().is_center_aligned() {
299 self.inner.get_max_compare_value() as u16 351 unwrap!(self.inner.get_max_compare_value().try_into())
300 } else { 352 } else {
301 self.inner.get_max_compare_value() as u16 + 1 353 unwrap!(self.inner.get_max_compare_value().try_into()) + 1
302 } 354 }
303 } 355 }
304 356
305 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { 357 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
306 assert!(duty <= self.get_max_duty()); 358 assert!(duty <= unwrap!(self.get_max_duty().try_into()));
307 self.inner.set_compare_value(channel, duty as u32) 359 self.inner.set_compare_value(channel, unwrap!(duty.try_into()))
308 } 360 }
309 361
310 fn set_period<P>(&mut self, period: P) 362 fn set_period<P>(&mut self, period: P)
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
index 9cf0f8c34..3e1482b67 100644
--- a/embassy-stm32/src/timer/input_capture.rs
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -97,7 +97,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
97 97
98 /// Get capture value for a channel. 98 /// Get capture value for a channel.
99 pub fn get_capture_value(&self, channel: Channel) -> u32 { 99 pub fn get_capture_value(&self, channel: Channel) -> u32 {
100 self.inner.get_capture_value(channel) 100 self.inner.get_capture_value(channel).into()
101 } 101 }
102 102
103 /// Get input interrupt. 103 /// Get input interrupt.
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs
index aba08081f..82e936f3a 100644
--- a/embassy-stm32/src/timer/low_level.rs
+++ b/embassy-stm32/src/timer/low_level.rs
@@ -13,7 +13,7 @@ use embassy_hal_internal::Peri;
13pub use stm32_metapac::timer::vals::{FilterValue, Mms as MasterMode, Sms as SlaveMode, Ts as TriggerSource}; 13pub use stm32_metapac::timer::vals::{FilterValue, Mms as MasterMode, Sms as SlaveMode, Ts as TriggerSource};
14 14
15use super::*; 15use super::*;
16use crate::dma::{Transfer, WritableRingBuffer}; 16use crate::dma::{self, Transfer, WritableRingBuffer};
17use crate::pac::timer::vals; 17use crate::pac::timer::vals;
18use crate::rcc; 18use crate::rcc;
19use crate::time::Hertz; 19use crate::time::Hertz;
@@ -268,6 +268,11 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
268 unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } 268 unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) }
269 } 269 }
270 270
271 #[cfg(stm32l0)]
272 fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp16 {
273 unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }
274 }
275
271 /// Start the timer. 276 /// Start the timer.
272 pub fn start(&self) { 277 pub fn start(&self) {
273 self.regs_core().cr1().modify(|r| r.set_cen(true)); 278 self.regs_core().cr1().modify(|r| r.set_cen(true));
@@ -296,7 +301,12 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
296 301
297 /// get the capability of the timer 302 /// get the capability of the timer
298 pub fn bits(&self) -> TimerBits { 303 pub fn bits(&self) -> TimerBits {
299 T::BITS 304 match T::Word::bits() {
305 16 => TimerBits::Bits16,
306 #[cfg(not(stm32l0))]
307 32 => TimerBits::Bits32,
308 _ => unreachable!(),
309 }
300 } 310 }
301 311
302 /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. 312 /// Set the frequency of how many times per second the timer counts up to the max value or down to 0.
@@ -306,18 +316,10 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
306 /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved 316 /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved
307 /// because it needs to count up and down. 317 /// because it needs to count up and down.
308 pub fn set_frequency(&self, frequency: Hertz) { 318 pub fn set_frequency(&self, frequency: Hertz) {
309 match T::BITS { 319 self.set_frequency_internal(frequency, T::Word::bits());
310 TimerBits::Bits16 => {
311 self.set_frequency_internal(frequency, 16);
312 }
313 #[cfg(not(stm32l0))]
314 TimerBits::Bits32 => {
315 self.set_frequency_internal(frequency, 32);
316 }
317 }
318 } 320 }
319 321
320 pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: u8) { 322 pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: usize) {
321 let f = frequency.0; 323 let f = frequency.0;
322 assert!(f > 0); 324 assert!(f > 0);
323 let timer_f = T::frequency().0; 325 let timer_f = T::frequency().0;
@@ -326,25 +328,15 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
326 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << max_divide_by_bits)).try_into()); 328 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << max_divide_by_bits)).try_into());
327 let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1); 329 let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1);
328 330
329 match T::BITS { 331 // the timer counts `0..=arr`, we want it to count `0..divide_by`
330 TimerBits::Bits16 => { 332 let arr: T::Word = unwrap!(T::Word::try_from(divide_by - 1));
331 // the timer counts `0..=arr`, we want it to count `0..divide_by`
332 let arr = unwrap!(u16::try_from(divide_by - 1));
333
334 let regs = self.regs_core();
335 regs.psc().write_value(psc);
336 regs.arr().write(|r| r.set_arr(arr));
337 }
338 #[cfg(not(stm32l0))]
339 TimerBits::Bits32 => {
340 // the timer counts `0..=arr`, we want it to count `0..divide_by`
341 let arr: u32 = unwrap!(u32::try_from(divide_by - 1));
342 333
343 let regs = self.regs_gp32_unchecked(); 334 let regs = self.regs_gp32_unchecked();
344 regs.psc().write_value(psc); 335 regs.psc().write_value(psc);
345 regs.arr().write_value(arr); 336 #[cfg(stm32l0)]
346 } 337 regs.arr().write(|r| r.set_arr(unwrap!(arr.try_into())));
347 } 338 #[cfg(not(stm32l0))]
339 regs.arr().write_value(arr.into());
348 } 340 }
349 341
350 /// Set tick frequency. 342 /// Set tick frequency.
@@ -393,23 +385,14 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
393 pub fn get_frequency(&self) -> Hertz { 385 pub fn get_frequency(&self) -> Hertz {
394 let timer_f = T::frequency(); 386 let timer_f = T::frequency();
395 387
396 match T::BITS { 388 let regs = self.regs_gp32_unchecked();
397 TimerBits::Bits16 => { 389 #[cfg(not(stm32l0))]
398 let regs = self.regs_core(); 390 let arr = regs.arr().read();
399 let arr = regs.arr().read().arr(); 391 #[cfg(stm32l0)]
400 let psc = regs.psc().read(); 392 let arr = regs.arr().read().arr();
393 let psc = regs.psc().read();
401 394
402 timer_f / arr / (psc + 1) 395 timer_f / arr / (psc + 1)
403 }
404 #[cfg(not(stm32l0))]
405 TimerBits::Bits32 => {
406 let regs = self.regs_gp32_unchecked();
407 let arr = regs.arr().read();
408 let psc = regs.psc().read();
409
410 timer_f / arr / (psc + 1)
411 }
412 }
413 } 396 }
414 397
415 /// Get the clock frequency of the timer (before prescaler is applied). 398 /// Get the clock frequency of the timer (before prescaler is applied).
@@ -469,42 +452,29 @@ impl<'d, T: GeneralInstance1Channel> Timer<'d, T> {
469 } 452 }
470 453
471 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. 454 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
472 pub fn get_max_compare_value(&self) -> u32 { 455 pub fn get_max_compare_value(&self) -> T::Word {
473 match T::BITS { 456 #[cfg(not(stm32l0))]
474 TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32, 457 return unwrap!(self.regs_gp32_unchecked().arr().read().try_into());
475 #[cfg(not(stm32l0))] 458 #[cfg(stm32l0)]
476 TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), 459 return unwrap!(self.regs_gp32_unchecked().arr().read().arr().try_into());
477 }
478 } 460 }
479 461
480 /// Set the max compare value. 462 /// Set the max compare value.
481 /// 463 ///
482 /// An update event is generated to load the new value. The update event is 464 /// An update event is generated to load the new value. The update event is
483 /// generated such that it will not cause an interrupt or DMA request. 465 /// generated such that it will not cause an interrupt or DMA request.
484 pub fn set_max_compare_value(&self, ticks: u32) { 466 pub fn set_max_compare_value(&self, ticks: T::Word) {
485 match T::BITS { 467 let arr = ticks;
486 TimerBits::Bits16 => {
487 let arr = unwrap!(u16::try_from(ticks));
488 468
489 let regs = self.regs_1ch(); 469 let regs = self.regs_gp32_unchecked();
490 regs.arr().write(|r| r.set_arr(arr)); 470 #[cfg(not(stm32l0))]
471 regs.arr().write_value(arr.into());
472 #[cfg(stm32l0)]
473 regs.arr().write(|r| r.set_arr(unwrap!(arr.try_into())));
491 474
492 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); 475 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
493 regs.egr().write(|r| r.set_ug(true)); 476 regs.egr().write(|r| r.set_ug(true));
494 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); 477 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
495 }
496 #[cfg(not(stm32l0))]
497 TimerBits::Bits32 => {
498 let arr = ticks;
499
500 let regs = self.regs_gp32_unchecked();
501 regs.arr().write_value(arr);
502
503 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
504 regs.egr().write(|r| r.set_ug(true));
505 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
506 }
507 }
508 } 478 }
509} 479}
510 480
@@ -638,35 +608,44 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
638 } 608 }
639 609
640 /// Set compare value for a channel. 610 /// Set compare value for a channel.
641 pub fn set_compare_value(&self, channel: Channel, value: u32) { 611 pub fn set_compare_value(&self, channel: Channel, value: T::Word) {
642 match T::BITS { 612 #[cfg(not(stm32l0))]
643 TimerBits::Bits16 => { 613 self.regs_gp32_unchecked()
644 let value = unwrap!(u16::try_from(value)); 614 .ccr(channel.index())
645 self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); 615 .write_value(value.into());
646 } 616 #[cfg(stm32l0)]
647 #[cfg(not(stm32l0))] 617 self.regs_gp16()
648 TimerBits::Bits32 => { 618 .ccr(channel.index())
649 self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); 619 .modify(|w| w.set_ccr(unwrap!(value.try_into())));
650 }
651 }
652 } 620 }
653 621
654 /// Get compare value for a channel. 622 /// Get compare value for a channel.
655 pub fn get_compare_value(&self, channel: Channel) -> u32 { 623 pub fn get_compare_value(&self, channel: Channel) -> T::Word {
656 match T::BITS { 624 #[cfg(not(stm32l0))]
657 TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, 625 return unwrap!(self.regs_gp32_unchecked().ccr(channel.index()).read().try_into());
658 #[cfg(not(stm32l0))] 626 #[cfg(stm32l0)]
659 TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), 627 return unwrap!(self.regs_gp32_unchecked().ccr(channel.index()).read().ccr().try_into());
660 } 628 }
629
630 pub(crate) fn clamp_compare_value<W: Word>(&mut self, channel: Channel) {
631 self.set_compare_value(
632 channel,
633 unwrap!(
634 self.get_compare_value(channel)
635 .into()
636 .clamp(0, W::max() as u32)
637 .try_into()
638 ),
639 );
661 } 640 }
662 641
663 /// Setup a ring buffer for the channel 642 /// Setup a ring buffer for the channel
664 pub fn setup_ring_buffer<'a>( 643 pub fn setup_ring_buffer<'a, W: Word + Into<T::Word>>(
665 &mut self, 644 &mut self,
666 dma: Peri<'a, impl super::UpDma<T>>, 645 dma: Peri<'a, impl super::UpDma<T>>,
667 channel: Channel, 646 channel: Channel,
668 dma_buf: &'a mut [u16], 647 dma_buf: &'a mut [W],
669 ) -> WritableRingBuffer<'a, u16> { 648 ) -> WritableRingBuffer<'a, W> {
670 #[allow(clippy::let_unit_value)] // eg. stm32f334 649 #[allow(clippy::let_unit_value)] // eg. stm32f334
671 let req = dma.request(); 650 let req = dma.request();
672 651
@@ -686,7 +665,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
686 WritableRingBuffer::new( 665 WritableRingBuffer::new(
687 dma, 666 dma,
688 req, 667 req,
689 self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, 668 self.regs_1ch().ccr(channel.index()).as_ptr() as *mut W,
690 dma_buf, 669 dma_buf,
691 dma_transfer_option, 670 dma_transfer_option,
692 ) 671 )
@@ -697,15 +676,35 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
697 /// 676 ///
698 /// Note: 677 /// Note:
699 /// you will need to provide corresponding TIMx_UP DMA channel to use this method. 678 /// you will need to provide corresponding TIMx_UP DMA channel to use this method.
700 pub fn setup_update_dma<'a>( 679 pub fn setup_update_dma<'a, W: Word + Into<T::Word>>(
701 &mut self, 680 &mut self,
702 dma: Peri<'a, impl super::UpDma<T>>, 681 dma: Peri<'a, impl super::UpDma<T>>,
703 channel: Channel, 682 channel: Channel,
704 duty: &'a [u16], 683 duty: &'a [W],
705 ) -> Transfer<'a> { 684 ) -> Transfer<'a> {
706 #[allow(clippy::let_unit_value)] // eg. stm32f334 685 self.setup_update_dma_inner(dma.request(), dma, channel, duty)
707 let req = dma.request(); 686 }
708 687
688 /// Generate a sequence of PWM waveform
689 ///
690 /// Note:
691 /// The DMA channel provided does not need to correspond to the requested channel.
692 pub fn setup_channel_update_dma<'a, C: TimerChannel, W: Word + Into<T::Word>>(
693 &mut self,
694 dma: Peri<'a, impl super::Dma<T, C>>,
695 channel: Channel,
696 duty: &'a [W],
697 ) -> Transfer<'a> {
698 self.setup_update_dma_inner(dma.request(), dma, channel, duty)
699 }
700
701 fn setup_update_dma_inner<'a, W: Word + Into<T::Word>>(
702 &mut self,
703 request: dma::Request,
704 dma: Peri<'a, impl dma::Channel>,
705 channel: Channel,
706 duty: &'a [W],
707 ) -> Transfer<'a> {
709 unsafe { 708 unsafe {
710 #[cfg(not(any(bdma, gpdma)))] 709 #[cfg(not(any(bdma, gpdma)))]
711 use crate::dma::{Burst, FifoThreshold}; 710 use crate::dma::{Burst, FifoThreshold};
@@ -719,29 +718,13 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
719 ..Default::default() 718 ..Default::default()
720 }; 719 };
721 720
722 match self.bits() { 721 Transfer::new_write(
723 TimerBits::Bits16 => Transfer::new_write( 722 dma,
724 dma, 723 request,
725 req, 724 duty,
726 duty, 725 self.regs_gp16().ccr(channel.index()).as_ptr() as *mut W,
727 self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, 726 dma_transfer_option,
728 dma_transfer_option, 727 )
729 ),
730 #[cfg(not(any(stm32l0)))]
731 TimerBits::Bits32 => {
732 #[cfg(not(any(bdma, gpdma)))]
733 panic!("unsupported timer bits");
734
735 #[cfg(any(bdma, gpdma))]
736 Transfer::new_write(
737 dma,
738 req,
739 duty,
740 self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u32,
741 dma_transfer_option,
742 )
743 }
744 }
745 } 728 }
746 } 729 }
747 730
@@ -774,12 +757,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
774 /// Also be aware that embassy timers use one of timers internally. It is possible to 757 /// Also be aware that embassy timers use one of timers internally. It is possible to
775 /// switch this timer by using `time-driver-timX` feature. 758 /// switch this timer by using `time-driver-timX` feature.
776 /// 759 ///
777 pub fn setup_update_dma_burst<'a>( 760 pub fn setup_update_dma_burst<'a, W: Word + Into<T::Word>>(
778 &mut self, 761 &mut self,
779 dma: Peri<'a, impl super::UpDma<T>>, 762 dma: Peri<'a, impl super::UpDma<T>>,
780 starting_channel: Channel, 763 starting_channel: Channel,
781 ending_channel: Channel, 764 ending_channel: Channel,
782 duty: &'a [u16], 765 duty: &'a [W],
783 ) -> Transfer<'a> { 766 ) -> Transfer<'a> {
784 let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32; 767 let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32;
785 let start_ch_index = starting_channel.index(); 768 let start_ch_index = starting_channel.index();
@@ -815,14 +798,14 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
815 dma, 798 dma,
816 req, 799 req,
817 duty, 800 duty,
818 self.regs_gp16().dmar().as_ptr() as *mut u16, 801 self.regs_gp16().dmar().as_ptr() as *mut W,
819 dma_transfer_option, 802 dma_transfer_option,
820 ) 803 )
821 } 804 }
822 } 805 }
823 806
824 /// Get capture value for a channel. 807 /// Get capture value for a channel.
825 pub fn get_capture_value(&self, channel: Channel) -> u32 { 808 pub fn get_capture_value(&self, channel: Channel) -> T::Word {
826 self.get_compare_value(channel) 809 self.get_compare_value(channel)
827 } 810 }
828 811
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 3fa363881..998e3a6f4 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -15,6 +15,8 @@ pub mod qei;
15pub mod ringbuffered; 15pub mod ringbuffered;
16pub mod simple_pwm; 16pub mod simple_pwm;
17 17
18use crate::dma::word::Word;
19use crate::fmt::Debuggable;
18use crate::interrupt; 20use crate::interrupt;
19use crate::rcc::RccPeripheral; 21use crate::rcc::RccPeripheral;
20 22
@@ -163,7 +165,12 @@ pub trait CoreInstance: SealedInstance + 'static {
163 type UpdateInterrupt: interrupt::typelevel::Interrupt; 165 type UpdateInterrupt: interrupt::typelevel::Interrupt;
164 166
165 /// Amount of bits this timer has. 167 /// Amount of bits this timer has.
166 const BITS: TimerBits; 168 type Word: Word
169 + TryInto<u16, Error: Debuggable>
170 + From<u16>
171 + TryFrom<u32, Error: Debuggable>
172 + Into<u32>
173 + TryFrom<u64, Error: Debuggable>;
167 174
168 /// Registers for this timer. 175 /// Registers for this timer.
169 /// 176 ///
@@ -241,7 +248,7 @@ dma_trait!(Dma, GeneralInstance4Channel, TimerChannel);
241 248
242#[allow(unused)] 249#[allow(unused)]
243macro_rules! impl_core_timer { 250macro_rules! impl_core_timer {
244 ($inst:ident, $bits:expr) => { 251 ($inst:ident, $bits:ident) => {
245 impl SealedInstance for crate::peripherals::$inst { 252 impl SealedInstance for crate::peripherals::$inst {
246 fn state() -> &'static State { 253 fn state() -> &'static State {
247 static STATE: State = State::new(); 254 static STATE: State = State::new();
@@ -251,8 +258,7 @@ macro_rules! impl_core_timer {
251 258
252 impl CoreInstance for crate::peripherals::$inst { 259 impl CoreInstance for crate::peripherals::$inst {
253 type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP; 260 type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP;
254 261 type Word = $bits;
255 const BITS: TimerBits = $bits;
256 262
257 fn regs() -> *mut () { 263 fn regs() -> *mut () {
258 crate::pac::$inst.as_ptr() 264 crate::pac::$inst.as_ptr()
@@ -306,13 +312,13 @@ macro_rules! impl_general_4ch_blank_sealed {
306 312
307foreach_interrupt! { 313foreach_interrupt! {
308 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { 314 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
309 impl_core_timer!($inst, TimerBits::Bits16); 315 impl_core_timer!($inst, u16);
310 impl BasicNoCr2Instance for crate::peripherals::$inst {} 316 impl BasicNoCr2Instance for crate::peripherals::$inst {}
311 impl BasicInstance for crate::peripherals::$inst {} 317 impl BasicInstance for crate::peripherals::$inst {}
312 }; 318 };
313 319
314 ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { 320 ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
315 impl_core_timer!($inst, TimerBits::Bits16); 321 impl_core_timer!($inst, u16);
316 impl BasicNoCr2Instance for crate::peripherals::$inst {} 322 impl BasicNoCr2Instance for crate::peripherals::$inst {}
317 impl BasicInstance for crate::peripherals::$inst {} 323 impl BasicInstance for crate::peripherals::$inst {}
318 impl_general_1ch!($inst); 324 impl_general_1ch!($inst);
@@ -322,7 +328,7 @@ foreach_interrupt! {
322 }; 328 };
323 329
324 ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { 330 ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
325 impl_core_timer!($inst, TimerBits::Bits16); 331 impl_core_timer!($inst, u16);
326 impl BasicNoCr2Instance for crate::peripherals::$inst {} 332 impl BasicNoCr2Instance for crate::peripherals::$inst {}
327 impl BasicInstance for crate::peripherals::$inst {} 333 impl BasicInstance for crate::peripherals::$inst {}
328 impl_general_1ch!($inst); 334 impl_general_1ch!($inst);
@@ -332,7 +338,7 @@ foreach_interrupt! {
332 }; 338 };
333 339
334 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { 340 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
335 impl_core_timer!($inst, TimerBits::Bits16); 341 impl_core_timer!($inst, u16);
336 impl BasicNoCr2Instance for crate::peripherals::$inst {} 342 impl BasicNoCr2Instance for crate::peripherals::$inst {}
337 impl BasicInstance for crate::peripherals::$inst {} 343 impl BasicInstance for crate::peripherals::$inst {}
338 impl_general_1ch!($inst); 344 impl_general_1ch!($inst);
@@ -342,7 +348,7 @@ foreach_interrupt! {
342 }; 348 };
343 349
344 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { 350 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
345 impl_core_timer!($inst, TimerBits::Bits32); 351 impl_core_timer!($inst, u32);
346 impl BasicNoCr2Instance for crate::peripherals::$inst {} 352 impl BasicNoCr2Instance for crate::peripherals::$inst {}
347 impl BasicInstance for crate::peripherals::$inst {} 353 impl BasicInstance for crate::peripherals::$inst {}
348 impl_general_1ch!($inst); 354 impl_general_1ch!($inst);
@@ -353,7 +359,7 @@ foreach_interrupt! {
353 }; 359 };
354 360
355 ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { 361 ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
356 impl_core_timer!($inst, TimerBits::Bits16); 362 impl_core_timer!($inst, u16);
357 impl BasicNoCr2Instance for crate::peripherals::$inst {} 363 impl BasicNoCr2Instance for crate::peripherals::$inst {}
358 impl BasicInstance for crate::peripherals::$inst {} 364 impl BasicInstance for crate::peripherals::$inst {}
359 impl_general_1ch!($inst); 365 impl_general_1ch!($inst);
@@ -366,7 +372,7 @@ foreach_interrupt! {
366 }; 372 };
367 373
368 ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { 374 ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => {
369 impl_core_timer!($inst, TimerBits::Bits16); 375 impl_core_timer!($inst, u16);
370 impl BasicNoCr2Instance for crate::peripherals::$inst {} 376 impl BasicNoCr2Instance for crate::peripherals::$inst {}
371 impl BasicInstance for crate::peripherals::$inst {} 377 impl BasicInstance for crate::peripherals::$inst {}
372 impl_general_1ch!($inst); 378 impl_general_1ch!($inst);
@@ -379,7 +385,7 @@ foreach_interrupt! {
379 }; 385 };
380 386
381 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { 387 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
382 impl_core_timer!($inst, TimerBits::Bits16); 388 impl_core_timer!($inst, u16);
383 impl BasicNoCr2Instance for crate::peripherals::$inst {} 389 impl BasicNoCr2Instance for crate::peripherals::$inst {}
384 impl BasicInstance for crate::peripherals::$inst {} 390 impl BasicInstance for crate::peripherals::$inst {}
385 impl_general_1ch!($inst); 391 impl_general_1ch!($inst);
@@ -400,7 +406,7 @@ pub struct UpdateInterruptHandler<T: CoreInstance> {
400impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> { 406impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> {
401 unsafe fn on_interrupt() { 407 unsafe fn on_interrupt() {
402 #[cfg(feature = "low-power")] 408 #[cfg(feature = "low-power")]
403 crate::low_power::Executor::on_wakeup_irq(); 409 crate::low_power::Executor::on_wakeup_irq_or_event();
404 410
405 let regs = crate::pac::timer::TimCore::from_ptr(T::regs()); 411 let regs = crate::pac::timer::TimCore::from_ptr(T::regs());
406 412
@@ -430,7 +436,7 @@ impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompare
430{ 436{
431 unsafe fn on_interrupt() { 437 unsafe fn on_interrupt() {
432 #[cfg(feature = "low-power")] 438 #[cfg(feature = "low-power")]
433 crate::low_power::Executor::on_wakeup_irq(); 439 crate::low_power::Executor::on_wakeup_irq_or_event();
434 440
435 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs()); 441 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs());
436 442
diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs
index fe8681356..989e1d630 100644
--- a/embassy-stm32/src/timer/one_pulse.rs
+++ b/embassy-stm32/src/timer/one_pulse.rs
@@ -199,7 +199,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
199 fn new_inner(&mut self, freq: Hertz, pulse_end: u32, counting_mode: CountingMode) { 199 fn new_inner(&mut self, freq: Hertz, pulse_end: u32, counting_mode: CountingMode) {
200 self.inner.set_counting_mode(counting_mode); 200 self.inner.set_counting_mode(counting_mode);
201 self.inner.set_tick_freq(freq); 201 self.inner.set_tick_freq(freq);
202 self.inner.set_max_compare_value(pulse_end); 202 self.inner.set_max_compare_value(unwrap!(pulse_end.try_into()));
203 self.inner.regs_core().cr1().modify(|r| r.set_opm(true)); 203 self.inner.regs_core().cr1().modify(|r| r.set_opm(true));
204 // Required for advanced timers, see GeneralInstance4Channel for details 204 // Required for advanced timers, see GeneralInstance4Channel for details
205 self.inner.enable_outputs(); 205 self.inner.enable_outputs();
@@ -211,14 +211,14 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
211 211
212 /// Get the end of the pulse in ticks from the trigger. 212 /// Get the end of the pulse in ticks from the trigger.
213 pub fn pulse_end(&self) -> u32 { 213 pub fn pulse_end(&self) -> u32 {
214 let max = self.inner.get_max_compare_value(); 214 let max: u32 = self.inner.get_max_compare_value().into();
215 assert!(max < u32::MAX); 215 assert!(max < u32::MAX);
216 max + 1 216 max + 1
217 } 217 }
218 218
219 /// Set the end of the pulse in ticks from the trigger. 219 /// Set the end of the pulse in ticks from the trigger.
220 pub fn set_pulse_end(&mut self, ticks: u32) { 220 pub fn set_pulse_end(&mut self, ticks: u32) {
221 self.inner.set_max_compare_value(ticks) 221 self.inner.set_max_compare_value(unwrap!(ticks.try_into()))
222 } 222 }
223 223
224 /// Reset the timer on each trigger 224 /// Reset the timer on each trigger
@@ -327,7 +327,7 @@ pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> {
327impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { 327impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
328 /// Get the end of the pulse in ticks from the trigger. 328 /// Get the end of the pulse in ticks from the trigger.
329 pub fn pulse_end(&self) -> u32 { 329 pub fn pulse_end(&self) -> u32 {
330 let max = self.inner.get_max_compare_value(); 330 let max: u32 = self.inner.get_max_compare_value().into();
331 assert!(max < u32::MAX); 331 assert!(max < u32::MAX);
332 max + 1 332 max + 1
333 } 333 }
@@ -339,13 +339,13 @@ impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
339 339
340 /// Get the start of the pulse in ticks from the trigger. 340 /// Get the start of the pulse in ticks from the trigger.
341 pub fn pulse_delay(&mut self) -> u32 { 341 pub fn pulse_delay(&mut self) -> u32 {
342 self.inner.get_compare_value(self.channel) 342 self.inner.get_compare_value(self.channel).into()
343 } 343 }
344 344
345 /// Set the start of the pulse in ticks from the trigger. 345 /// Set the start of the pulse in ticks from the trigger.
346 pub fn set_pulse_delay(&mut self, delay: u32) { 346 pub fn set_pulse_delay(&mut self, delay: u32) {
347 assert!(delay <= self.pulse_end()); 347 assert!(delay <= self.pulse_end());
348 self.inner.set_compare_value(self.channel, delay); 348 self.inner.set_compare_value(self.channel, unwrap!(delay.try_into()));
349 } 349 }
350 350
351 /// Set the pulse width in ticks. 351 /// Set the pulse width in ticks.
diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs
index 057ab011a..f2f00927d 100644
--- a/embassy-stm32/src/timer/pwm_input.rs
+++ b/embassy-stm32/src/timer/pwm_input.rs
@@ -91,16 +91,18 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
91 91
92 /// Get the period tick count 92 /// Get the period tick count
93 pub fn get_period_ticks(&self) -> u32 { 93 pub fn get_period_ticks(&self) -> u32 {
94 self.inner.get_capture_value(self.channel) 94 self.inner.get_capture_value(self.channel).into()
95 } 95 }
96 96
97 /// Get the pulse width tick count 97 /// Get the pulse width tick count
98 pub fn get_width_ticks(&self) -> u32 { 98 pub fn get_width_ticks(&self) -> u32 {
99 self.inner.get_capture_value(match self.channel { 99 self.inner
100 Channel::Ch1 => Channel::Ch2, 100 .get_capture_value(match self.channel {
101 Channel::Ch2 => Channel::Ch1, 101 Channel::Ch1 => Channel::Ch2,
102 _ => panic!("Invalid channel for PWM input"), 102 Channel::Ch2 => Channel::Ch1,
103 }) 103 _ => panic!("Invalid channel for PWM input"),
104 })
105 .into()
104 } 106 }
105 107
106 /// Get the duty cycle in 100% 108 /// Get the duty cycle in 100%
diff --git a/embassy-stm32/src/timer/ringbuffered.rs b/embassy-stm32/src/timer/ringbuffered.rs
index e8f97bf59..fbb6b19ea 100644
--- a/embassy-stm32/src/timer/ringbuffered.rs
+++ b/embassy-stm32/src/timer/ringbuffered.rs
@@ -7,6 +7,7 @@ use super::low_level::Timer;
7use super::{Channel, GeneralInstance4Channel}; 7use super::{Channel, GeneralInstance4Channel};
8use crate::dma::WritableRingBuffer; 8use crate::dma::WritableRingBuffer;
9use crate::dma::ringbuffer::Error; 9use crate::dma::ringbuffer::Error;
10use crate::dma::word::Word;
10 11
11/// A PWM channel that uses a DMA ring buffer for continuous waveform generation. 12/// A PWM channel that uses a DMA ring buffer for continuous waveform generation.
12/// 13///
@@ -23,17 +24,17 @@ use crate::dma::ringbuffer::Error;
23/// channel.start(); // Start DMA transfer 24/// channel.start(); // Start DMA transfer
24/// channel.write(&[100, 200, 300]).ok(); // Update duty cycles 25/// channel.write(&[100, 200, 300]).ok(); // Update duty cycles
25/// ``` 26/// ```
26pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel> { 27pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel, W: Word + Into<T::Word>> {
27 timer: ManuallyDrop<Timer<'d, T>>, 28 timer: ManuallyDrop<Timer<'d, T>>,
28 ring_buf: WritableRingBuffer<'d, u16>, 29 ring_buf: WritableRingBuffer<'d, W>,
29 channel: Channel, 30 channel: Channel,
30} 31}
31 32
32impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> { 33impl<'d, T: GeneralInstance4Channel, W: Word + Into<T::Word>> RingBufferedPwmChannel<'d, T, W> {
33 pub(crate) fn new( 34 pub(crate) fn new(
34 timer: ManuallyDrop<Timer<'d, T>>, 35 timer: ManuallyDrop<Timer<'d, T>>,
35 channel: Channel, 36 channel: Channel,
36 ring_buf: WritableRingBuffer<'d, u16>, 37 ring_buf: WritableRingBuffer<'d, W>,
37 ) -> Self { 38 ) -> Self {
38 Self { 39 Self {
39 timer, 40 timer,
@@ -55,18 +56,18 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> {
55 } 56 }
56 57
57 /// Write elements directly to the raw buffer. This can be used to fill the buffer before starting the DMA transfer. 58 /// Write elements directly to the raw buffer. This can be used to fill the buffer before starting the DMA transfer.
58 pub fn write_immediate(&mut self, buf: &[u16]) -> Result<(usize, usize), Error> { 59 pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
59 self.ring_buf.write_immediate(buf) 60 self.ring_buf.write_immediate(buf)
60 } 61 }
61 62
62 /// Write elements from the ring buffer 63 /// Write elements from the ring buffer
63 /// Return a tuple of the length written and the length remaining in the buffer 64 /// Return a tuple of the length written and the length remaining in the buffer
64 pub fn write(&mut self, buf: &[u16]) -> Result<(usize, usize), Error> { 65 pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
65 self.ring_buf.write(buf) 66 self.ring_buf.write(buf)
66 } 67 }
67 68
68 /// Write an exact number of elements to the ringbuffer. 69 /// Write an exact number of elements to the ringbuffer.
69 pub async fn write_exact(&mut self, buffer: &[u16]) -> Result<usize, Error> { 70 pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, Error> {
70 self.ring_buf.write_exact(buffer).await 71 self.ring_buf.write_exact(buffer).await
71 } 72 }
72 73
@@ -140,7 +141,7 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> {
140 /// 141 ///
141 /// This value depends on the configured frequency and the timer's clock rate from RCC. 142 /// This value depends on the configured frequency and the timer's clock rate from RCC.
142 pub fn max_duty_cycle(&self) -> u16 { 143 pub fn max_duty_cycle(&self) -> u16 {
143 let max = self.timer.get_max_compare_value(); 144 let max: u32 = self.timer.get_max_compare_value().into();
144 assert!(max < u16::MAX as u32); 145 assert!(max < u16::MAX as u32);
145 max as u16 + 1 146 max as u16 + 1
146 } 147 }
@@ -155,15 +156,3 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> {
155 self.timer.set_output_compare_mode(self.channel, mode); 156 self.timer.set_output_compare_mode(self.channel, mode);
156 } 157 }
157} 158}
158
159/// A group of four [`SimplePwmChannel`]s, obtained from [`SimplePwm::split`].
160pub struct RingBufferedPwmChannels<'d, T: GeneralInstance4Channel> {
161 /// Channel 1
162 pub ch1: RingBufferedPwmChannel<'d, T>,
163 /// Channel 2
164 pub ch2: RingBufferedPwmChannel<'d, T>,
165 /// Channel 3
166 pub ch3: RingBufferedPwmChannel<'d, T>,
167 /// Channel 4
168 pub ch4: RingBufferedPwmChannel<'d, T>,
169}
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 484e9fd81..9a5f0fd1d 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -7,9 +7,11 @@ use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
7use super::ringbuffered::RingBufferedPwmChannel; 7use super::ringbuffered::RingBufferedPwmChannel;
8use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerChannel, TimerPin}; 8use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerChannel, TimerPin};
9use crate::Peri; 9use crate::Peri;
10use crate::dma::word::Word;
10#[cfg(gpio_v2)] 11#[cfg(gpio_v2)]
11use crate::gpio::Pull; 12use crate::gpio::Pull;
12use crate::gpio::{AfType, AnyPin, OutputType, Speed}; 13use crate::gpio::{AfType, AnyPin, OutputType, Speed};
14use crate::pac::timer::vals::Ccds;
13use crate::time::Hertz; 15use crate::time::Hertz;
14 16
15/// PWM pin wrapper. 17/// PWM pin wrapper.
@@ -98,18 +100,16 @@ impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> {
98 /// Get max duty value. 100 /// Get max duty value.
99 /// 101 ///
100 /// This value depends on the configured frequency and the timer's clock rate from RCC. 102 /// This value depends on the configured frequency and the timer's clock rate from RCC.
101 pub fn max_duty_cycle(&self) -> u16 { 103 pub fn max_duty_cycle(&self) -> u32 {
102 let max = self.timer.get_max_compare_value(); 104 self.timer.get_max_compare_value().into() + 1
103 assert!(max < u16::MAX as u32);
104 max as u16 + 1
105 } 105 }
106 106
107 /// Set the duty for a given channel. 107 /// Set the duty for a given channel.
108 /// 108 ///
109 /// The value ranges from 0 for 0% duty, to [`max_duty_cycle`](Self::max_duty_cycle) for 100% duty, both included. 109 /// The value ranges from 0 for 0% duty, to [`max_duty_cycle`](Self::max_duty_cycle) for 100% duty, both included.
110 pub fn set_duty_cycle(&mut self, duty: u16) { 110 pub fn set_duty_cycle(&mut self, duty: u32) {
111 assert!(duty <= (*self).max_duty_cycle()); 111 assert!(duty <= (*self).max_duty_cycle());
112 self.timer.set_compare_value(self.channel, duty.into()) 112 self.timer.set_compare_value(self.channel, unwrap!(duty.try_into()))
113 } 113 }
114 114
115 /// Set the duty cycle to 0%, or always inactive. 115 /// Set the duty cycle to 0%, or always inactive.
@@ -126,21 +126,21 @@ impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> {
126 /// 126 ///
127 /// The caller is responsible for ensuring that `num` is less than or equal to `denom`, 127 /// The caller is responsible for ensuring that `num` is less than or equal to `denom`,
128 /// and that `denom` is not zero. 128 /// and that `denom` is not zero.
129 pub fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) { 129 pub fn set_duty_cycle_fraction(&mut self, num: u32, denom: u32) {
130 assert!(denom != 0); 130 assert!(denom != 0);
131 assert!(num <= denom); 131 assert!(num <= denom);
132 let duty = u32::from(num) * u32::from(self.max_duty_cycle()) / u32::from(denom); 132 let duty = u32::from(num) * u32::from(self.max_duty_cycle()) / u32::from(denom);
133 133
134 // This is safe because we know that `num <= denom`, so `duty <= self.max_duty_cycle()` (u16) 134 // This is safe because we know that `num <= denom`, so `duty <= self.max_duty_cycle()` (u16)
135 #[allow(clippy::cast_possible_truncation)] 135 #[allow(clippy::cast_possible_truncation)]
136 self.set_duty_cycle(duty as u16); 136 self.set_duty_cycle(unwrap!(duty.try_into()));
137 } 137 }
138 138
139 /// Set the duty cycle to `percent / 100` 139 /// Set the duty cycle to `percent / 100`
140 /// 140 ///
141 /// The caller is responsible for ensuring that `percent` is less than or equal to 100. 141 /// The caller is responsible for ensuring that `percent` is less than or equal to 100.
142 pub fn set_duty_cycle_percent(&mut self, percent: u8) { 142 pub fn set_duty_cycle_percent(&mut self, percent: u8) {
143 self.set_duty_cycle_fraction(u16::from(percent), 100) 143 self.set_duty_cycle_fraction(percent as u32, 100)
144 } 144 }
145 145
146 /// Get the duty for a given channel. 146 /// Get the duty for a given channel.
@@ -171,13 +171,14 @@ impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> {
171 /// 171 ///
172 /// # Panics 172 /// # Panics
173 /// Panics if `dma_buf` is empty or longer than 65535 elements. 173 /// Panics if `dma_buf` is empty or longer than 65535 elements.
174 pub fn into_ring_buffered_channel( 174 pub fn into_ring_buffered_channel<W: Word + Into<T::Word>>(
175 mut self, 175 mut self,
176 tx_dma: Peri<'d, impl super::UpDma<T>>, 176 tx_dma: Peri<'d, impl super::UpDma<T>>,
177 dma_buf: &'d mut [u16], 177 dma_buf: &'d mut [W],
178 ) -> RingBufferedPwmChannel<'d, T> { 178 ) -> RingBufferedPwmChannel<'d, T, W> {
179 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); 179 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
180 180
181 self.timer.clamp_compare_value::<W>(self.channel);
181 self.timer.enable_update_dma(true); 182 self.timer.enable_update_dma(true);
182 183
183 RingBufferedPwmChannel::new( 184 RingBufferedPwmChannel::new(
@@ -332,10 +333,27 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
332 /// Get max duty value. 333 /// Get max duty value.
333 /// 334 ///
334 /// This value depends on the configured frequency and the timer's clock rate from RCC. 335 /// This value depends on the configured frequency and the timer's clock rate from RCC.
335 pub fn max_duty_cycle(&self) -> u16 { 336 pub fn max_duty_cycle(&self) -> u32 {
336 let max = self.inner.get_max_compare_value(); 337 self.inner.get_max_compare_value().into() + 1
337 assert!(max < u16::MAX as u32); 338 }
338 max as u16 + 1 339
340 /// Generate a sequence of PWM waveform
341 ///
342 /// Note:
343 /// The DMA channel provided does not need to correspond to the requested channel.
344 pub async fn waveform<C: TimerChannel, W: Word + Into<T::Word>>(
345 &mut self,
346 dma: Peri<'_, impl super::Dma<T, C>>,
347 channel: Channel,
348 duty: &[W],
349 ) {
350 self.inner.enable_channel(channel, true);
351 self.inner.enable_channel(C::CHANNEL, true);
352 self.inner.clamp_compare_value::<W>(channel);
353 self.inner.set_cc_dma_selection(Ccds::ON_UPDATE);
354 self.inner.set_cc_dma_enable_state(C::CHANNEL, true);
355 self.inner.setup_channel_update_dma(dma, channel, duty).await;
356 self.inner.set_cc_dma_enable_state(C::CHANNEL, false);
339 } 357 }
340 358
341 /// Generate a sequence of PWM waveform 359 /// Generate a sequence of PWM waveform
@@ -344,8 +362,14 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
344 /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method. 362 /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method.
345 /// Also be aware that embassy timers use one of timers internally. It is possible to 363 /// Also be aware that embassy timers use one of timers internally. It is possible to
346 /// switch this timer by using `time-driver-timX` feature. 364 /// switch this timer by using `time-driver-timX` feature.
347 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { 365 pub async fn waveform_up<W: Word + Into<T::Word>>(
366 &mut self,
367 dma: Peri<'_, impl super::UpDma<T>>,
368 channel: Channel,
369 duty: &[W],
370 ) {
348 self.inner.enable_channel(channel, true); 371 self.inner.enable_channel(channel, true);
372 self.inner.clamp_compare_value::<W>(channel);
349 self.inner.enable_update_dma(true); 373 self.inner.enable_update_dma(true);
350 self.inner.setup_update_dma(dma, channel, duty).await; 374 self.inner.setup_update_dma(dma, channel, duty).await;
351 self.inner.enable_update_dma(false); 375 self.inner.enable_update_dma(false);
@@ -380,13 +404,21 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
380 /// Also be aware that embassy timers use one of timers internally. It is possible to 404 /// Also be aware that embassy timers use one of timers internally. It is possible to
381 /// switch this timer by using `time-driver-timX` feature. 405 /// switch this timer by using `time-driver-timX` feature.
382 /// 406 ///
383 pub async fn waveform_up_multi_channel( 407 pub async fn waveform_up_multi_channel<W: Word + Into<T::Word>>(
384 &mut self, 408 &mut self,
385 dma: Peri<'_, impl super::UpDma<T>>, 409 dma: Peri<'_, impl super::UpDma<T>>,
386 starting_channel: Channel, 410 starting_channel: Channel,
387 ending_channel: Channel, 411 ending_channel: Channel,
388 duty: &[u16], 412 duty: &[W],
389 ) { 413 ) {
414 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
415 .iter()
416 .filter(|ch| ch.index() >= starting_channel.index())
417 .filter(|ch| ch.index() <= ending_channel.index())
418 .for_each(|ch| {
419 self.inner.enable_channel(*ch, true);
420 self.inner.clamp_compare_value::<W>(*ch);
421 });
390 self.inner.enable_update_dma(true); 422 self.inner.enable_update_dma(true);
391 self.inner 423 self.inner
392 .setup_update_dma_burst(dma, starting_channel, ending_channel, duty) 424 .setup_update_dma_burst(dma, starting_channel, ending_channel, duty)
@@ -401,11 +433,11 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePw
401 433
402impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for SimplePwmChannel<'d, T> { 434impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for SimplePwmChannel<'d, T> {
403 fn max_duty_cycle(&self) -> u16 { 435 fn max_duty_cycle(&self) -> u16 {
404 self.max_duty_cycle() 436 unwrap!(self.max_duty_cycle().try_into())
405 } 437 }
406 438
407 fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { 439 fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
408 self.set_duty_cycle(duty); 440 self.set_duty_cycle(duty.into());
409 Ok(()) 441 Ok(())
410 } 442 }
411 443
@@ -420,7 +452,7 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for Simpl
420 } 452 }
421 453
422 fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) -> Result<(), Self::Error> { 454 fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) -> Result<(), Self::Error> {
423 self.set_duty_cycle_fraction(num, denom); 455 self.set_duty_cycle_fraction(num.into(), denom.into());
424 Ok(()) 456 Ok(())
425 } 457 }
426 458
@@ -448,16 +480,16 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> {
448 } 480 }
449 481
450 fn get_duty(&self, channel: Self::Channel) -> Self::Duty { 482 fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
451 self.inner.get_compare_value(channel) 483 self.inner.get_compare_value(channel).into()
452 } 484 }
453 485
454 fn get_max_duty(&self) -> Self::Duty { 486 fn get_max_duty(&self) -> Self::Duty {
455 self.inner.get_max_compare_value() + 1 487 self.inner.get_max_compare_value().into() + 1
456 } 488 }
457 489
458 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { 490 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
459 assert!(duty <= self.max_duty_cycle() as u32); 491 assert!(duty <= self.max_duty_cycle() as u32);
460 self.inner.set_compare_value(channel, duty) 492 self.inner.set_compare_value(channel, unwrap!(duty.try_into()))
461 } 493 }
462 494
463 fn set_period<P>(&mut self, period: P) 495 fn set_period<P>(&mut self, period: P)
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 8047d6005..d2c361c61 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -491,7 +491,7 @@ impl<'d> UartTx<'d, Async> {
491 491
492 /// Initiate an asynchronous UART write 492 /// Initiate an asynchronous UART write
493 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 493 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
494 let _ = self.info.rcc.block_stop(); 494 let _scoped_block_stop = self.info.rcc.block_stop();
495 495
496 let r = self.info.regs; 496 let r = self.info.regs;
497 497
@@ -510,7 +510,7 @@ impl<'d> UartTx<'d, Async> {
510 510
511 /// Wait until transmission complete 511 /// Wait until transmission complete
512 pub async fn flush(&mut self) -> Result<(), Error> { 512 pub async fn flush(&mut self) -> Result<(), Error> {
513 let _ = self.info.rcc.block_stop(); 513 let _scoped_block_stop = self.info.rcc.block_stop();
514 514
515 flush(&self.info, &self.state).await 515 flush(&self.info, &self.state).await
516 } 516 }
@@ -730,7 +730,7 @@ impl<'d> UartRx<'d, Async> {
730 730
731 /// Initiate an asynchronous UART read 731 /// Initiate an asynchronous UART read
732 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 732 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
733 let _ = self.info.rcc.block_stop(); 733 let _scoped_block_stop = self.info.rcc.block_stop();
734 734
735 self.inner_read(buffer, false).await?; 735 self.inner_read(buffer, false).await?;
736 736
@@ -739,7 +739,7 @@ impl<'d> UartRx<'d, Async> {
739 739
740 /// Initiate an asynchronous read with idle line detection enabled 740 /// Initiate an asynchronous read with idle line detection enabled
741 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 741 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
742 let _ = self.info.rcc.block_stop(); 742 let _scoped_block_stop = self.info.rcc.block_stop();
743 743
744 self.inner_read(buffer, true).await 744 self.inner_read(buffer, true).await
745 } 745 }