aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-06-19 21:18:46 -0500
committerxoviat <[email protected]>2023-06-19 21:18:46 -0500
commit0d67ef795e4dfecef90690bce51f2820f77fc4bc (patch)
treefa6b8a092652a9d0af9f67576b1b99063c3aa184
parent978e7b5e77f86dc82c393442702defa38b516f4b (diff)
parent37a1e9f971214c11a614b06b230be27c688fff1d (diff)
Merge branch 'main' of https://github.com/embassy-rs/embassy into tl-mbox-2
-rw-r--r--docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs24
-rw-r--r--embassy-lora/src/iv.rs16
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/build.rs6
-rw-r--r--embassy-stm32/src/adc/f1.rs92
-rw-r--r--embassy-stm32/src/adc/v1.rs50
-rw-r--r--embassy-stm32/src/adc/v2.rs87
-rw-r--r--embassy-stm32/src/adc/v3.rs184
-rw-r--r--embassy-stm32/src/adc/v4.rs172
-rw-r--r--embassy-stm32/src/can/bxcan.rs16
-rw-r--r--embassy-stm32/src/crc/v1.rs10
-rw-r--r--embassy-stm32/src/crc/v2v3.rs98
-rw-r--r--embassy-stm32/src/dac.rs72
-rw-r--r--embassy-stm32/src/dcmi.rs102
-rw-r--r--embassy-stm32/src/dma/bdma.rs57
-rw-r--r--embassy-stm32/src/dma/dma.rs84
-rw-r--r--embassy-stm32/src/dma/dmamux.rs2
-rw-r--r--embassy-stm32/src/dma/gpdma.rs25
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs397
-rw-r--r--embassy-stm32/src/eth/v1/rx_desc.rs13
-rw-r--r--embassy-stm32/src/eth/v1/tx_desc.rs11
-rw-r--r--embassy-stm32/src/eth/v2/descriptors.rs29
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs435
-rw-r--r--embassy-stm32/src/exti.rs6
-rw-r--r--embassy-stm32/src/flash/f4.rs30
-rw-r--r--embassy-stm32/src/fmc.rs8
-rw-r--r--embassy-stm32/src/gpio.rs36
-rw-r--r--embassy-stm32/src/i2c/v1.rs164
-rw-r--r--embassy-stm32/src/i2c/v2.rs384
-rw-r--r--embassy-stm32/src/i2s.rs34
-rw-r--r--embassy-stm32/src/ipcc.rs40
-rw-r--r--embassy-stm32/src/lib.rs56
-rw-r--r--embassy-stm32/src/pwm/complementary_pwm.rs46
-rw-r--r--embassy-stm32/src/pwm/mod.rs58
-rw-r--r--embassy-stm32/src/pwm/simple_pwm.rs36
-rw-r--r--embassy-stm32/src/qspi/mod.rs238
-rw-r--r--embassy-stm32/src/rcc/f4.rs16
-rw-r--r--embassy-stm32/src/rcc/f7.rs4
-rw-r--r--embassy-stm32/src/rcc/g0.rs2
-rw-r--r--embassy-stm32/src/rcc/h5.rs15
-rw-r--r--embassy-stm32/src/rcc/h7.rs22
-rw-r--r--embassy-stm32/src/rng.rs44
-rw-r--r--embassy-stm32/src/rtc/datetime.rs44
-rw-r--r--embassy-stm32/src/rtc/mod.rs38
-rw-r--r--embassy-stm32/src/rtc/v2.rs230
-rw-r--r--embassy-stm32/src/rtc/v3.rs229
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs649
-rw-r--r--embassy-stm32/src/spi/mod.rs280
-rw-r--r--embassy-stm32/src/time_driver.rs20
-rw-r--r--embassy-stm32/src/timer/mod.rs64
-rw-r--r--embassy-stm32/src/usart/buffered.rs148
-rw-r--r--embassy-stm32/src/usart/mod.rs407
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs81
-rw-r--r--embassy-stm32/src/usb/usb.rs414
-rw-r--r--embassy-stm32/src/usb_otg/mod.rs2
-rw-r--r--embassy-stm32/src/usb_otg/usb.rs550
-rw-r--r--embassy-stm32/src/wdg/mod.rs12
-rw-r--r--examples/stm32f0/src/bin/wdg.rs4
-rw-r--r--examples/stm32f4/src/bin/wdt.rs8
-rw-r--r--examples/stm32g4/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32h5/src/bin/usb_serial.rs8
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs54
-rw-r--r--examples/stm32h7/src/bin/wdg.rs4
-rw-r--r--examples/stm32l4/src/bin/adc.rs10
-rw-r--r--examples/stm32l4/src/bin/dac.rs8
-rw-r--r--examples/stm32wl/src/bin/lora_lorawan.rs2
-rw-r--r--examples/stm32wl/src/bin/random.rs8
-rw-r--r--tests/stm32/src/bin/rtc.rs6
-rw-r--r--tests/stm32/src/bin/usart_dma.rs29
69 files changed, 2934 insertions, 3604 deletions
diff --git a/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs b/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs
index 743d0c342..aecba0755 100644
--- a/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs
+++ b/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs
@@ -20,13 +20,13 @@ fn main() -> ! {
20 let led = Output::new(p.PB14, Level::Low, Speed::Low); 20 let led = Output::new(p.PB14, Level::Low, Speed::Low);
21 let mut button = Input::new(p.PC13, Pull::Up); 21 let mut button = Input::new(p.PC13, Pull::Up);
22 22
23 cortex_m::interrupt::free(|cs| unsafe { 23 cortex_m::interrupt::free(|cs| {
24 enable_interrupt(&mut button); 24 enable_interrupt(&mut button);
25 25
26 LED.borrow(cs).borrow_mut().replace(led); 26 LED.borrow(cs).borrow_mut().replace(led);
27 BUTTON.borrow(cs).borrow_mut().replace(button); 27 BUTTON.borrow(cs).borrow_mut().replace(button);
28 28
29 NVIC::unmask(pac::Interrupt::EXTI15_10); 29 unsafe { NVIC::unmask(pac::Interrupt::EXTI15_10) };
30 }); 30 });
31 31
32 loop { 32 loop {
@@ -64,25 +64,21 @@ const PORT: u8 = 2;
64const PIN: usize = 13; 64const PIN: usize = 13;
65fn check_interrupt<P: Pin>(_pin: &mut Input<'static, P>) -> bool { 65fn check_interrupt<P: Pin>(_pin: &mut Input<'static, P>) -> bool {
66 let exti = pac::EXTI; 66 let exti = pac::EXTI;
67 unsafe { 67 let pin = PIN;
68 let pin = PIN; 68 let lines = exti.pr(0).read();
69 let lines = exti.pr(0).read(); 69 lines.line(pin)
70 lines.line(pin)
71 }
72} 70}
73 71
74fn clear_interrupt<P: Pin>(_pin: &mut Input<'static, P>) { 72fn clear_interrupt<P: Pin>(_pin: &mut Input<'static, P>) {
75 let exti = pac::EXTI; 73 let exti = pac::EXTI;
76 unsafe { 74 let pin = PIN;
77 let pin = PIN; 75 let mut lines = exti.pr(0).read();
78 let mut lines = exti.pr(0).read(); 76 lines.set_line(pin, true);
79 lines.set_line(pin, true); 77 exti.pr(0).write_value(lines);
80 exti.pr(0).write_value(lines);
81 }
82} 78}
83 79
84fn enable_interrupt<P: Pin>(_pin: &mut Input<'static, P>) { 80fn enable_interrupt<P: Pin>(_pin: &mut Input<'static, P>) {
85 cortex_m::interrupt::free(|_| unsafe { 81 cortex_m::interrupt::free(|_| {
86 let rcc = pac::RCC; 82 let rcc = pac::RCC;
87 rcc.apb2enr().modify(|w| w.set_syscfgen(true)); 83 rcc.apb2enr().modify(|w| w.set_syscfgen(true));
88 84
diff --git a/embassy-lora/src/iv.rs b/embassy-lora/src/iv.rs
index 2e0b68d1a..136973fe3 100644
--- a/embassy-lora/src/iv.rs
+++ b/embassy-lora/src/iv.rs
@@ -68,29 +68,23 @@ where
68 } 68 }
69 async fn set_nss_low(&mut self) -> Result<(), RadioError> { 69 async fn set_nss_low(&mut self) -> Result<(), RadioError> {
70 let pwr = pac::PWR; 70 let pwr = pac::PWR;
71 unsafe { 71 pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW));
72 pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW));
73 }
74 Ok(()) 72 Ok(())
75 } 73 }
76 async fn set_nss_high(&mut self) -> Result<(), RadioError> { 74 async fn set_nss_high(&mut self) -> Result<(), RadioError> {
77 let pwr = pac::PWR; 75 let pwr = pac::PWR;
78 unsafe { 76 pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH));
79 pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH));
80 }
81 Ok(()) 77 Ok(())
82 } 78 }
83 async fn reset(&mut self, _delay: &mut impl DelayUs) -> Result<(), RadioError> { 79 async fn reset(&mut self, _delay: &mut impl DelayUs) -> Result<(), RadioError> {
84 let rcc = pac::RCC; 80 let rcc = pac::RCC;
85 unsafe { 81 rcc.csr().modify(|w| w.set_rfrst(true));
86 rcc.csr().modify(|w| w.set_rfrst(true)); 82 rcc.csr().modify(|w| w.set_rfrst(false));
87 rcc.csr().modify(|w| w.set_rfrst(false));
88 }
89 Ok(()) 83 Ok(())
90 } 84 }
91 async fn wait_on_busy(&mut self) -> Result<(), RadioError> { 85 async fn wait_on_busy(&mut self) -> Result<(), RadioError> {
92 let pwr = pac::PWR; 86 let pwr = pac::PWR;
93 while unsafe { pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY } {} 87 while pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY {}
94 Ok(()) 88 Ok(())
95 } 89 }
96 90
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index f876c7146..3d9ee8261 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -57,7 +57,7 @@ sdio-host = "0.5.0"
57embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 57embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
58critical-section = "1.1" 58critical-section = "1.1"
59atomic-polyfill = "1.0.1" 59atomic-polyfill = "1.0.1"
60stm32-metapac = "9" 60stm32-metapac = "10"
61vcell = "0.1.3" 61vcell = "0.1.3"
62bxcan = "0.7.0" 62bxcan = "0.7.0"
63nb = "1.0.0" 63nb = "1.0.0"
@@ -74,7 +74,7 @@ critical-section = { version = "1.1", features = ["std"] }
74[build-dependencies] 74[build-dependencies]
75proc-macro2 = "1.0.36" 75proc-macro2 = "1.0.36"
76quote = "1.0.15" 76quote = "1.0.15"
77stm32-metapac = { version = "9", default-features = false, features = ["metadata"]} 77stm32-metapac = { version = "10", default-features = false, features = ["metadata"]}
78 78
79[features] 79[features]
80default = ["rt"] 80default = ["rt"]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 9e597f187..f71074bcf 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -322,7 +322,7 @@ fn main() {
322 let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase()); 322 let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase());
323 let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase()); 323 let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase());
324 quote! { 324 quote! {
325 critical_section::with(|_| unsafe { 325 critical_section::with(|_| {
326 crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true)); 326 crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true));
327 crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false)); 327 crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false));
328 }); 328 });
@@ -353,13 +353,13 @@ fn main() {
353 }) 353 })
354 } 354 }
355 fn enable() { 355 fn enable() {
356 critical_section::with(|_| unsafe { 356 critical_section::with(|_| {
357 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); 357 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
358 #after_enable 358 #after_enable
359 }) 359 })
360 } 360 }
361 fn disable() { 361 fn disable() {
362 critical_section::with(|_| unsafe { 362 critical_section::with(|_| {
363 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); 363 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
364 }) 364 })
365 } 365 }
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index d30ec001d..2322204d5 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -32,26 +32,22 @@ impl<'d, T: Instance> Adc<'d, T> {
32 into_ref!(adc); 32 into_ref!(adc);
33 T::enable(); 33 T::enable();
34 T::reset(); 34 T::reset();
35 unsafe { 35 T::regs().cr2().modify(|reg| reg.set_adon(true));
36 T::regs().cr2().modify(|reg| reg.set_adon(true));
37 }
38 36
39 // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) 37 // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’)
40 // for at least two ADC clock cycles 38 // for at least two ADC clock cycles
41 delay.delay_us((1_000_000 * 2) / Self::freq().0 + 1); 39 delay.delay_us((1_000_000 * 2) / Self::freq().0 + 1);
42 40
43 unsafe { 41 // Reset calibration
44 // Reset calibration 42 T::regs().cr2().modify(|reg| reg.set_rstcal(true));
45 T::regs().cr2().modify(|reg| reg.set_rstcal(true)); 43 while T::regs().cr2().read().rstcal() {
46 while T::regs().cr2().read().rstcal() { 44 // spin
47 // spin 45 }
48 } 46
49 47 // Calibrate
50 // Calibrate 48 T::regs().cr2().modify(|reg| reg.set_cal(true));
51 T::regs().cr2().modify(|reg| reg.set_cal(true)); 49 while T::regs().cr2().read().cal() {
52 while T::regs().cr2().read().cal() { 50 // spin
53 // spin
54 }
55 } 51 }
56 52
57 // One cycle after calibration 53 // One cycle after calibration
@@ -81,20 +77,16 @@ impl<'d, T: Instance> Adc<'d, T> {
81 } 77 }
82 78
83 pub fn enable_vref(&self, _delay: &mut impl DelayUs<u32>) -> Vref { 79 pub fn enable_vref(&self, _delay: &mut impl DelayUs<u32>) -> Vref {
84 unsafe { 80 T::regs().cr2().modify(|reg| {
85 T::regs().cr2().modify(|reg| { 81 reg.set_tsvrefe(true);
86 reg.set_tsvrefe(true); 82 });
87 })
88 }
89 Vref {} 83 Vref {}
90 } 84 }
91 85
92 pub fn enable_temperature(&self) -> Temperature { 86 pub fn enable_temperature(&self) -> Temperature {
93 unsafe { 87 T::regs().cr2().modify(|reg| {
94 T::regs().cr2().modify(|reg| { 88 reg.set_tsvrefe(true);
95 reg.set_tsvrefe(true); 89 });
96 })
97 }
98 Temperature {} 90 Temperature {}
99 } 91 }
100 92
@@ -104,41 +96,37 @@ impl<'d, T: Instance> Adc<'d, T> {
104 96
105 /// Perform a single conversion. 97 /// Perform a single conversion.
106 fn convert(&mut self) -> u16 { 98 fn convert(&mut self) -> u16 {
107 unsafe { 99 T::regs().cr2().modify(|reg| {
108 T::regs().cr2().modify(|reg| { 100 reg.set_adon(true);
109 reg.set_adon(true); 101 reg.set_swstart(true);
110 reg.set_swstart(true); 102 });
111 }); 103 while T::regs().cr2().read().swstart() {}
112 while T::regs().cr2().read().swstart() {} 104 while !T::regs().sr().read().eoc() {}
113 while !T::regs().sr().read().eoc() {} 105
114 106 T::regs().dr().read().0 as u16
115 T::regs().dr().read().0 as u16
116 }
117 } 107 }
118 108
119 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { 109 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
120 unsafe { 110 Self::set_channel_sample_time(pin.channel(), self.sample_time);
121 Self::set_channel_sample_time(pin.channel(), self.sample_time); 111 T::regs().cr1().modify(|reg| {
122 T::regs().cr1().modify(|reg| { 112 reg.set_scan(false);
123 reg.set_scan(false); 113 reg.set_discen(false);
124 reg.set_discen(false); 114 });
125 }); 115 T::regs().sqr1().modify(|reg| reg.set_l(0));
126 T::regs().sqr1().modify(|reg| reg.set_l(0)); 116
127 117 T::regs().cr2().modify(|reg| {
128 T::regs().cr2().modify(|reg| { 118 reg.set_cont(false);
129 reg.set_cont(false); 119 reg.set_exttrig(true);
130 reg.set_exttrig(true); 120 reg.set_swstart(false);
131 reg.set_swstart(false); 121 reg.set_extsel(crate::pac::adc::vals::Extsel::SWSTART);
132 reg.set_extsel(crate::pac::adc::vals::Extsel::SWSTART); 122 });
133 });
134 }
135 123
136 // Configure the channel to sample 124 // Configure the channel to sample
137 unsafe { T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())) } 125 T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel()));
138 self.convert() 126 self.convert()
139 } 127 }
140 128
141 unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 129 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
142 let sample_time = sample_time.into(); 130 let sample_time = sample_time.into();
143 if ch <= 9 { 131 if ch <= 9 {
144 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); 132 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time));
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index 82a8c3efb..d9af0c55e 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -57,18 +57,14 @@ impl<'d, T: Instance> Adc<'d, T> {
57 // 57 //
58 // 6.3.20 Vbat monitoring characteristics 58 // 6.3.20 Vbat monitoring characteristics
59 // ts_vbat ≥ 4μs 59 // ts_vbat ≥ 4μs
60 unsafe { 60 T::regs().ccr().modify(|reg| reg.set_vbaten(true));
61 T::regs().ccr().modify(|reg| reg.set_vbaten(true));
62 }
63 Vbat 61 Vbat
64 } 62 }
65 63
66 pub fn enable_vref(&self, delay: &mut impl DelayUs<u32>) -> Vref { 64 pub fn enable_vref(&self, delay: &mut impl DelayUs<u32>) -> Vref {
67 // Table 28. Embedded internal reference voltage 65 // Table 28. Embedded internal reference voltage
68 // tstart = 10μs 66 // tstart = 10μs
69 unsafe { 67 T::regs().ccr().modify(|reg| reg.set_vrefen(true));
70 T::regs().ccr().modify(|reg| reg.set_vrefen(true));
71 }
72 delay.delay_us(10); 68 delay.delay_us(10);
73 Vref 69 Vref
74 } 70 }
@@ -79,27 +75,23 @@ impl<'d, T: Instance> Adc<'d, T> {
79 // 6.3.19 Temperature sensor characteristics 75 // 6.3.19 Temperature sensor characteristics
80 // tstart ≤ 10μs 76 // tstart ≤ 10μs
81 // ts_temp ≥ 4μs 77 // ts_temp ≥ 4μs
82 unsafe { 78 T::regs().ccr().modify(|reg| reg.set_tsen(true));
83 T::regs().ccr().modify(|reg| reg.set_tsen(true));
84 }
85 delay.delay_us(10); 79 delay.delay_us(10);
86 Temperature 80 Temperature
87 } 81 }
88 82
89 fn calibrate(&self) { 83 fn calibrate(&self) {
90 unsafe { 84 // A.7.1 ADC calibration code example
91 // A.7.1 ADC calibration code example 85 if T::regs().cr().read().aden() {
92 if T::regs().cr().read().aden() { 86 T::regs().cr().modify(|reg| reg.set_addis(true));
93 T::regs().cr().modify(|reg| reg.set_addis(true)); 87 }
94 } 88 while T::regs().cr().read().aden() {
95 while T::regs().cr().read().aden() { 89 // spin
96 // spin 90 }
97 } 91 T::regs().cfgr1().modify(|reg| reg.set_dmaen(false));
98 T::regs().cfgr1().modify(|reg| reg.set_dmaen(false)); 92 T::regs().cr().modify(|reg| reg.set_adcal(true));
99 T::regs().cr().modify(|reg| reg.set_adcal(true)); 93 while T::regs().cr().read().adcal() {
100 while T::regs().cr().read().adcal() { 94 // spin
101 // spin
102 }
103 } 95 }
104 } 96 }
105 97
@@ -108,9 +100,7 @@ impl<'d, T: Instance> Adc<'d, T> {
108 } 100 }
109 101
110 pub fn set_resolution(&mut self, resolution: Resolution) { 102 pub fn set_resolution(&mut self, resolution: Resolution) {
111 unsafe { 103 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
112 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
113 }
114 } 104 }
115 105
116 pub fn read<P>(&mut self, pin: &mut P) -> u16 106 pub fn read<P>(&mut self, pin: &mut P) -> u16
@@ -118,18 +108,16 @@ impl<'d, T: Instance> Adc<'d, T> {
118 P: AdcPin<T> + crate::gpio::sealed::Pin, 108 P: AdcPin<T> + crate::gpio::sealed::Pin,
119 { 109 {
120 let channel = pin.channel(); 110 let channel = pin.channel();
121 unsafe { 111 pin.set_as_analog();
122 pin.set_as_analog(); 112 self.read_channel(channel)
123 self.read_channel(channel)
124 }
125 } 113 }
126 114
127 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { 115 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
128 let channel = channel.channel(); 116 let channel = channel.channel();
129 unsafe { self.read_channel(channel) } 117 self.read_channel(channel)
130 } 118 }
131 119
132 unsafe fn read_channel(&mut self, channel: u8) -> u16 { 120 fn read_channel(&mut self, channel: u8) -> u16 {
133 // A.7.2 ADC enable sequence code example 121 // A.7.2 ADC enable sequence code example
134 if T::regs().isr().read().adrdy() { 122 if T::regs().isr().read().adrdy() {
135 T::regs().isr().modify(|reg| reg.set_adrdy(true)); 123 T::regs().isr().modify(|reg| reg.set_adrdy(true));
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 11a51f993..091c1d447 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -100,13 +100,10 @@ where
100 T::reset(); 100 T::reset();
101 101
102 let presc = Prescaler::from_pclk2(T::frequency()); 102 let presc = Prescaler::from_pclk2(T::frequency());
103 unsafe { 103 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre()));
104 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); 104 T::regs().cr2().modify(|reg| {
105 105 reg.set_adon(crate::pac::adc::vals::Adon::ENABLED);
106 T::regs().cr2().modify(|reg| { 106 });
107 reg.set_adon(crate::pac::adc::vals::Adon::ENABLED);
108 });
109 }
110 107
111 delay.delay_us(ADC_POWERUP_TIME_US); 108 delay.delay_us(ADC_POWERUP_TIME_US);
112 109
@@ -121,19 +118,15 @@ where
121 } 118 }
122 119
123 pub fn set_resolution(&mut self, resolution: Resolution) { 120 pub fn set_resolution(&mut self, resolution: Resolution) {
124 unsafe { 121 T::regs().cr1().modify(|reg| reg.set_res(resolution.into()));
125 T::regs().cr1().modify(|reg| reg.set_res(resolution.into()));
126 }
127 } 122 }
128 123
129 /// Enables internal voltage reference and returns [VrefInt], which can be used in 124 /// Enables internal voltage reference and returns [VrefInt], which can be used in
130 /// [Adc::read_internal()] to perform conversion. 125 /// [Adc::read_internal()] to perform conversion.
131 pub fn enable_vrefint(&self) -> VrefInt { 126 pub fn enable_vrefint(&self) -> VrefInt {
132 unsafe { 127 T::common_regs().ccr().modify(|reg| {
133 T::common_regs().ccr().modify(|reg| { 128 reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED);
134 reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); 129 });
135 });
136 }
137 130
138 VrefInt {} 131 VrefInt {}
139 } 132 }
@@ -144,11 +137,9 @@ where
144 /// On STM32F42 and STM32F43 this can not be used together with [Vbat]. If both are enabled, 137 /// On STM32F42 and STM32F43 this can not be used together with [Vbat]. If both are enabled,
145 /// temperature sensor will return vbat value. 138 /// temperature sensor will return vbat value.
146 pub fn enable_temperature(&self) -> Temperature { 139 pub fn enable_temperature(&self) -> Temperature {
147 unsafe { 140 T::common_regs().ccr().modify(|reg| {
148 T::common_regs().ccr().modify(|reg| { 141 reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED);
149 reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); 142 });
150 });
151 }
152 143
153 Temperature {} 144 Temperature {}
154 } 145 }
@@ -156,37 +147,33 @@ where
156 /// Enables vbat input and returns [Vbat], which can be used in 147 /// Enables vbat input and returns [Vbat], which can be used in
157 /// [Adc::read_internal()] to perform conversion. 148 /// [Adc::read_internal()] to perform conversion.
158 pub fn enable_vbat(&self) -> Vbat { 149 pub fn enable_vbat(&self) -> Vbat {
159 unsafe { 150 T::common_regs().ccr().modify(|reg| {
160 T::common_regs().ccr().modify(|reg| { 151 reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED);
161 reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); 152 });
162 });
163 }
164 153
165 Vbat {} 154 Vbat {}
166 } 155 }
167 156
168 /// Perform a single conversion. 157 /// Perform a single conversion.
169 fn convert(&mut self) -> u16 { 158 fn convert(&mut self) -> u16 {
170 unsafe { 159 // clear end of conversion flag
171 // clear end of conversion flag 160 T::regs().sr().modify(|reg| {
172 T::regs().sr().modify(|reg| { 161 reg.set_eoc(crate::pac::adc::vals::Eoc::NOTCOMPLETE);
173 reg.set_eoc(crate::pac::adc::vals::Eoc::NOTCOMPLETE); 162 });
174 }); 163
175 164 // Start conversion
176 // Start conversion 165 T::regs().cr2().modify(|reg| {
177 T::regs().cr2().modify(|reg| { 166 reg.set_swstart(true);
178 reg.set_swstart(true); 167 });
179 }); 168
180 169 while T::regs().sr().read().strt() == crate::pac::adc::vals::Strt::NOTSTARTED {
181 while T::regs().sr().read().strt() == crate::pac::adc::vals::Strt::NOTSTARTED { 170 // spin //wait for actual start
182 // spin //wait for actual start
183 }
184 while T::regs().sr().read().eoc() == crate::pac::adc::vals::Eoc::NOTCOMPLETE {
185 // spin //wait for finish
186 }
187
188 T::regs().dr().read().0 as u16
189 } 171 }
172 while T::regs().sr().read().eoc() == crate::pac::adc::vals::Eoc::NOTCOMPLETE {
173 // spin //wait for finish
174 }
175
176 T::regs().dr().read().0 as u16
190 } 177 }
191 178
192 pub fn read<P>(&mut self, pin: &mut P) -> u16 179 pub fn read<P>(&mut self, pin: &mut P) -> u16
@@ -194,18 +181,16 @@ where
194 P: AdcPin<T>, 181 P: AdcPin<T>,
195 P: crate::gpio::sealed::Pin, 182 P: crate::gpio::sealed::Pin,
196 { 183 {
197 unsafe { 184 pin.set_as_analog();
198 pin.set_as_analog();
199 185
200 self.read_channel(pin.channel()) 186 self.read_channel(pin.channel())
201 }
202 } 187 }
203 188
204 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { 189 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
205 unsafe { self.read_channel(channel.channel()) } 190 self.read_channel(channel.channel())
206 } 191 }
207 192
208 unsafe fn read_channel(&mut self, channel: u8) -> u16 { 193 fn read_channel(&mut self, channel: u8) -> u16 {
209 // Configure ADC 194 // Configure ADC
210 195
211 // Select channel 196 // Select channel
@@ -219,7 +204,7 @@ where
219 val 204 val
220 } 205 }
221 206
222 unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 207 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
223 let sample_time = sample_time.into(); 208 let sample_time = sample_time.into();
224 if ch <= 9 { 209 if ch <= 9 {
225 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); 210 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time));
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 90aa7d3b9..94cdc86cd 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -12,7 +12,7 @@ pub const VREF_CALIB_MV: u32 = 3000;
12/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock 12/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock
13/// configuration. 13/// configuration.
14fn enable() { 14fn enable() {
15 critical_section::with(|_| unsafe { 15 critical_section::with(|_| {
16 #[cfg(stm32h7)] 16 #[cfg(stm32h7)]
17 crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true)); 17 crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true));
18 #[cfg(stm32g0)] 18 #[cfg(stm32g0)]
@@ -62,29 +62,25 @@ impl<'d, T: Instance> Adc<'d, T> {
62 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 62 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
63 into_ref!(adc); 63 into_ref!(adc);
64 enable(); 64 enable();
65 unsafe { 65 T::regs().cr().modify(|reg| {
66 T::regs().cr().modify(|reg| { 66 #[cfg(not(adc_g0))]
67 #[cfg(not(adc_g0))] 67 reg.set_deeppwd(false);
68 reg.set_deeppwd(false); 68 reg.set_advregen(true);
69 reg.set_advregen(true); 69 });
70 }); 70
71 71 #[cfg(adc_g0)]
72 #[cfg(adc_g0)] 72 T::regs().cfgr1().modify(|reg| {
73 T::regs().cfgr1().modify(|reg| { 73 reg.set_chselrmod(false);
74 reg.set_chselrmod(false); 74 });
75 });
76 }
77 75
78 delay.delay_us(20); 76 delay.delay_us(20);
79 77
80 unsafe { 78 T::regs().cr().modify(|reg| {
81 T::regs().cr().modify(|reg| { 79 reg.set_adcal(true);
82 reg.set_adcal(true); 80 });
83 });
84 81
85 while T::regs().cr().read().adcal() { 82 while T::regs().cr().read().adcal() {
86 // spin 83 // spin
87 }
88 } 84 }
89 85
90 delay.delay_us(1); 86 delay.delay_us(1);
@@ -96,11 +92,9 @@ impl<'d, T: Instance> Adc<'d, T> {
96 } 92 }
97 93
98 pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt { 94 pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt {
99 unsafe { 95 T::common_regs().ccr().modify(|reg| {
100 T::common_regs().ccr().modify(|reg| { 96 reg.set_vrefen(true);
101 reg.set_vrefen(true); 97 });
102 });
103 }
104 98
105 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us 99 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
106 // to stabilize the internal voltage reference, we wait a little more. 100 // to stabilize the internal voltage reference, we wait a little more.
@@ -112,21 +106,17 @@ impl<'d, T: Instance> Adc<'d, T> {
112 } 106 }
113 107
114 pub fn enable_temperature(&self) -> Temperature { 108 pub fn enable_temperature(&self) -> Temperature {
115 unsafe { 109 T::common_regs().ccr().modify(|reg| {
116 T::common_regs().ccr().modify(|reg| { 110 reg.set_ch17sel(true);
117 reg.set_ch17sel(true); 111 });
118 });
119 }
120 112
121 Temperature {} 113 Temperature {}
122 } 114 }
123 115
124 pub fn enable_vbat(&self) -> Vbat { 116 pub fn enable_vbat(&self) -> Vbat {
125 unsafe { 117 T::common_regs().ccr().modify(|reg| {
126 T::common_regs().ccr().modify(|reg| { 118 reg.set_ch18sel(true);
127 reg.set_ch18sel(true); 119 });
128 });
129 }
130 120
131 Vbat {} 121 Vbat {}
132 } 122 }
@@ -136,12 +126,10 @@ impl<'d, T: Instance> Adc<'d, T> {
136 } 126 }
137 127
138 pub fn set_resolution(&mut self, resolution: Resolution) { 128 pub fn set_resolution(&mut self, resolution: Resolution) {
139 unsafe { 129 #[cfg(not(stm32g0))]
140 #[cfg(not(stm32g0))] 130 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
141 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); 131 #[cfg(stm32g0)]
142 #[cfg(stm32g0)] 132 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
143 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
144 }
145 } 133 }
146 134
147 /* 135 /*
@@ -155,77 +143,73 @@ impl<'d, T: Instance> Adc<'d, T> {
155 143
156 /// Perform a single conversion. 144 /// Perform a single conversion.
157 fn convert(&mut self) -> u16 { 145 fn convert(&mut self) -> u16 {
158 unsafe { 146 T::regs().isr().modify(|reg| {
159 T::regs().isr().modify(|reg| { 147 reg.set_eos(true);
160 reg.set_eos(true); 148 reg.set_eoc(true);
161 reg.set_eoc(true); 149 });
162 }); 150
163 151 // Start conversion
164 // Start conversion 152 T::regs().cr().modify(|reg| {
165 T::regs().cr().modify(|reg| { 153 reg.set_adstart(true);
166 reg.set_adstart(true); 154 });
167 }); 155
168 156 while !T::regs().isr().read().eos() {
169 while !T::regs().isr().read().eos() { 157 // spin
170 // spin
171 }
172
173 T::regs().dr().read().0 as u16
174 } 158 }
159
160 T::regs().dr().read().0 as u16
175 } 161 }
176 162
177 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { 163 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
178 unsafe { 164 // Make sure bits are off
179 // Make sure bits are off 165 while T::regs().cr().read().addis() {
180 while T::regs().cr().read().addis() { 166 // spin
181 // spin
182 }
183
184 // Enable ADC
185 T::regs().isr().modify(|reg| {
186 reg.set_adrdy(true);
187 });
188 T::regs().cr().modify(|reg| {
189 reg.set_aden(true);
190 });
191
192 while !T::regs().isr().read().adrdy() {
193 // spin
194 }
195
196 // Configure channel
197 Self::set_channel_sample_time(pin.channel(), self.sample_time);
198
199 // Select channel
200 #[cfg(not(stm32g0))]
201 T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel()));
202 #[cfg(stm32g0)]
203 T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel()));
204
205 // Some models are affected by an erratum:
206 // If we perform conversions slower than 1 kHz, the first read ADC value can be
207 // corrupted, so we discard it and measure again.
208 //
209 // STM32L471xx: Section 2.7.3
210 // STM32G4: Section 2.7.3
211 #[cfg(any(rcc_l4, rcc_g4))]
212 let _ = self.convert();
213
214 let val = self.convert();
215
216 T::regs().cr().modify(|reg| reg.set_addis(true));
217
218 val
219 } 167 }
168
169 // Enable ADC
170 T::regs().isr().modify(|reg| {
171 reg.set_adrdy(true);
172 });
173 T::regs().cr().modify(|reg| {
174 reg.set_aden(true);
175 });
176
177 while !T::regs().isr().read().adrdy() {
178 // spin
179 }
180
181 // Configure channel
182 Self::set_channel_sample_time(pin.channel(), self.sample_time);
183
184 // Select channel
185 #[cfg(not(stm32g0))]
186 T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel()));
187 #[cfg(stm32g0)]
188 T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel()));
189
190 // Some models are affected by an erratum:
191 // If we perform conversions slower than 1 kHz, the first read ADC value can be
192 // corrupted, so we discard it and measure again.
193 //
194 // STM32L471xx: Section 2.7.3
195 // STM32G4: Section 2.7.3
196 #[cfg(any(rcc_l4, rcc_g4))]
197 let _ = self.convert();
198
199 let val = self.convert();
200
201 T::regs().cr().modify(|reg| reg.set_addis(true));
202
203 val
220 } 204 }
221 205
222 #[cfg(stm32g0)] 206 #[cfg(stm32g0)]
223 unsafe fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { 207 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
224 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); 208 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into()));
225 } 209 }
226 210
227 #[cfg(not(stm32g0))] 211 #[cfg(not(stm32g0))]
228 unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 212 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
229 let sample_time = sample_time.into(); 213 let sample_time = sample_time.into();
230 if ch <= 9 { 214 if ch <= 9 {
231 T::regs().smpr1().modify(|reg| reg.set_smp(ch as _, sample_time)); 215 T::regs().smpr1().modify(|reg| reg.set_smp(ch as _, sample_time));
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index 4707b7c95..c51c6840f 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -46,8 +46,8 @@ foreach_peripheral!(
46 (adc, ADC1) => { 46 (adc, ADC1) => {
47 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC1 { 47 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC1 {
48 fn frequency() -> crate::time::Hertz { 48 fn frequency() -> crate::time::Hertz {
49 critical_section::with(|_| unsafe { 49 critical_section::with(|_| {
50 match crate::rcc::get_freqs().adc { 50 match unsafe { crate::rcc::get_freqs() }.adc {
51 Some(ck) => ck, 51 Some(ck) => ck,
52 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") 52 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.")
53 } 53 }
@@ -55,7 +55,7 @@ foreach_peripheral!(
55 } 55 }
56 56
57 fn enable() { 57 fn enable() {
58 critical_section::with(|_| unsafe { 58 critical_section::with(|_| {
59 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) 59 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true))
60 }); 60 });
61 ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); 61 ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst);
@@ -63,7 +63,7 @@ foreach_peripheral!(
63 63
64 fn disable() { 64 fn disable() {
65 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { 65 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 {
66 critical_section::with(|_| unsafe { 66 critical_section::with(|_| {
67 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); 67 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false));
68 }) 68 })
69 } 69 }
@@ -72,7 +72,7 @@ foreach_peripheral!(
72 72
73 fn reset() { 73 fn reset() {
74 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { 74 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 {
75 critical_section::with(|_| unsafe { 75 critical_section::with(|_| {
76 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); 76 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true));
77 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); 77 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false));
78 }); 78 });
@@ -85,8 +85,8 @@ foreach_peripheral!(
85 (adc, ADC2) => { 85 (adc, ADC2) => {
86 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC2 { 86 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC2 {
87 fn frequency() -> crate::time::Hertz { 87 fn frequency() -> crate::time::Hertz {
88 critical_section::with(|_| unsafe { 88 critical_section::with(|_| {
89 match crate::rcc::get_freqs().adc { 89 match unsafe { crate::rcc::get_freqs() }.adc {
90 Some(ck) => ck, 90 Some(ck) => ck,
91 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") 91 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.")
92 } 92 }
@@ -94,7 +94,7 @@ foreach_peripheral!(
94 } 94 }
95 95
96 fn enable() { 96 fn enable() {
97 critical_section::with(|_| unsafe { 97 critical_section::with(|_| {
98 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) 98 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true))
99 }); 99 });
100 ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); 100 ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst);
@@ -102,7 +102,7 @@ foreach_peripheral!(
102 102
103 fn disable() { 103 fn disable() {
104 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { 104 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 {
105 critical_section::with(|_| unsafe { 105 critical_section::with(|_| {
106 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); 106 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false));
107 }) 107 })
108 } 108 }
@@ -111,7 +111,7 @@ foreach_peripheral!(
111 111
112 fn reset() { 112 fn reset() {
113 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { 113 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 {
114 critical_section::with(|_| unsafe { 114 critical_section::with(|_| {
115 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); 115 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true));
116 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); 116 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false));
117 }); 117 });
@@ -124,8 +124,8 @@ foreach_peripheral!(
124 (adc, ADC3) => { 124 (adc, ADC3) => {
125 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC3 { 125 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC3 {
126 fn frequency() -> crate::time::Hertz { 126 fn frequency() -> crate::time::Hertz {
127 critical_section::with(|_| unsafe { 127 critical_section::with(|_| {
128 match crate::rcc::get_freqs().adc { 128 match unsafe { crate::rcc::get_freqs() }.adc {
129 Some(ck) => ck, 129 Some(ck) => ck,
130 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") 130 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.")
131 } 131 }
@@ -133,22 +133,22 @@ foreach_peripheral!(
133 } 133 }
134 134
135 fn enable() { 135 fn enable() {
136 critical_section::with(|_| unsafe { 136 critical_section::with(|_| {
137 crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(true)) 137 crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(true))
138 }); 138 });
139 } 139 }
140 140
141 fn disable() { 141 fn disable() {
142 critical_section::with(|_| unsafe { 142 critical_section::with(|_| {
143 crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false)); 143 crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false));
144 }) 144 })
145 } 145 }
146 146
147 fn reset() { 147 fn reset() {
148 critical_section::with(|_| unsafe { 148 critical_section::with(|_| {
149 crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true)); 149 crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true));
150 crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false)); 150 crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false));
151 }); 151 });
152 } 152 }
153 } 153 }
154 154
@@ -232,9 +232,7 @@ impl<'d, T: Instance> Adc<'d, T> {
232 232
233 let prescaler = Prescaler::from_ker_ck(T::frequency()); 233 let prescaler = Prescaler::from_ker_ck(T::frequency());
234 234
235 unsafe { 235 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
236 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
237 }
238 236
239 let frequency = Hertz(T::frequency().0 / prescaler.divisor()); 237 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
240 info!("ADC frequency set to {} Hz", frequency.0); 238 info!("ADC frequency set to {} Hz", frequency.0);
@@ -251,9 +249,7 @@ impl<'d, T: Instance> Adc<'d, T> {
251 } else { 249 } else {
252 Boost::LT50 250 Boost::LT50
253 }; 251 };
254 unsafe { 252 T::regs().cr().modify(|w| w.set_boost(boost));
255 T::regs().cr().modify(|w| w.set_boost(boost));
256 }
257 253
258 let mut s = Self { 254 let mut s = Self {
259 adc, 255 adc,
@@ -272,84 +268,68 @@ impl<'d, T: Instance> Adc<'d, T> {
272 } 268 }
273 269
274 fn power_up(&mut self, delay: &mut impl DelayUs<u16>) { 270 fn power_up(&mut self, delay: &mut impl DelayUs<u16>) {
275 unsafe { 271 T::regs().cr().modify(|reg| {
276 T::regs().cr().modify(|reg| { 272 reg.set_deeppwd(false);
277 reg.set_deeppwd(false); 273 reg.set_advregen(true);
278 reg.set_advregen(true); 274 });
279 });
280 }
281 275
282 delay.delay_us(10); 276 delay.delay_us(10);
283 } 277 }
284 278
285 fn configure_differential_inputs(&mut self) { 279 fn configure_differential_inputs(&mut self) {
286 unsafe { 280 T::regs().difsel().modify(|w| {
287 T::regs().difsel().modify(|w| { 281 for n in 0..20 {
288 for n in 0..20 { 282 w.set_difsel(n, Difsel::SINGLEENDED);
289 w.set_difsel(n, Difsel::SINGLEENDED); 283 }
290 } 284 });
291 })
292 };
293 } 285 }
294 286
295 fn calibrate(&mut self) { 287 fn calibrate(&mut self) {
296 unsafe { 288 T::regs().cr().modify(|w| {
297 T::regs().cr().modify(|w| { 289 w.set_adcaldif(Adcaldif::SINGLEENDED);
298 w.set_adcaldif(Adcaldif::SINGLEENDED); 290 w.set_adcallin(true);
299 w.set_adcallin(true); 291 });
300 });
301 292
302 T::regs().cr().modify(|w| w.set_adcal(true)); 293 T::regs().cr().modify(|w| w.set_adcal(true));
303 294
304 while T::regs().cr().read().adcal() {} 295 while T::regs().cr().read().adcal() {}
305 }
306 } 296 }
307 297
308 fn enable(&mut self) { 298 fn enable(&mut self) {
309 unsafe { 299 T::regs().isr().write(|w| w.set_adrdy(true));
310 T::regs().isr().write(|w| w.set_adrdy(true)); 300 T::regs().cr().modify(|w| w.set_aden(true));
311 T::regs().cr().modify(|w| w.set_aden(true)); 301 while !T::regs().isr().read().adrdy() {}
312 while !T::regs().isr().read().adrdy() {} 302 T::regs().isr().write(|w| w.set_adrdy(true));
313 T::regs().isr().write(|w| w.set_adrdy(true));
314 }
315 } 303 }
316 304
317 fn configure(&mut self) { 305 fn configure(&mut self) {
318 // single conversion mode, software trigger 306 // single conversion mode, software trigger
319 unsafe { 307 T::regs().cfgr().modify(|w| {
320 T::regs().cfgr().modify(|w| { 308 w.set_cont(false);
321 w.set_cont(false); 309 w.set_exten(Exten::DISABLED);
322 w.set_exten(Exten::DISABLED); 310 });
323 })
324 }
325 } 311 }
326 312
327 pub fn enable_vrefint(&self) -> VrefInt { 313 pub fn enable_vrefint(&self) -> VrefInt {
328 unsafe { 314 T::common_regs().ccr().modify(|reg| {
329 T::common_regs().ccr().modify(|reg| { 315 reg.set_vrefen(true);
330 reg.set_vrefen(true); 316 });
331 });
332 }
333 317
334 VrefInt {} 318 VrefInt {}
335 } 319 }
336 320
337 pub fn enable_temperature(&self) -> Temperature { 321 pub fn enable_temperature(&self) -> Temperature {
338 unsafe { 322 T::common_regs().ccr().modify(|reg| {
339 T::common_regs().ccr().modify(|reg| { 323 reg.set_vsenseen(true);
340 reg.set_vsenseen(true); 324 });
341 });
342 }
343 325
344 Temperature {} 326 Temperature {}
345 } 327 }
346 328
347 pub fn enable_vbat(&self) -> Vbat { 329 pub fn enable_vbat(&self) -> Vbat {
348 unsafe { 330 T::common_regs().ccr().modify(|reg| {
349 T::common_regs().ccr().modify(|reg| { 331 reg.set_vbaten(true);
350 reg.set_vbaten(true); 332 });
351 });
352 }
353 333
354 Vbat {} 334 Vbat {}
355 } 335 }
@@ -359,30 +339,26 @@ impl<'d, T: Instance> Adc<'d, T> {
359 } 339 }
360 340
361 pub fn set_resolution(&mut self, resolution: Resolution) { 341 pub fn set_resolution(&mut self, resolution: Resolution) {
362 unsafe { 342 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
363 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
364 }
365 } 343 }
366 344
367 /// Perform a single conversion. 345 /// Perform a single conversion.
368 fn convert(&mut self) -> u16 { 346 fn convert(&mut self) -> u16 {
369 unsafe { 347 T::regs().isr().modify(|reg| {
370 T::regs().isr().modify(|reg| { 348 reg.set_eos(true);
371 reg.set_eos(true); 349 reg.set_eoc(true);
372 reg.set_eoc(true); 350 });
373 });
374
375 // Start conversion
376 T::regs().cr().modify(|reg| {
377 reg.set_adstart(true);
378 });
379
380 while !T::regs().isr().read().eos() {
381 // spin
382 }
383 351
384 T::regs().dr().read().0 as u16 352 // Start conversion
353 T::regs().cr().modify(|reg| {
354 reg.set_adstart(true);
355 });
356
357 while !T::regs().isr().read().eos() {
358 // spin
385 } 359 }
360
361 T::regs().dr().read().0 as u16
386 } 362 }
387 363
388 pub fn read<P>(&mut self, pin: &mut P) -> u16 364 pub fn read<P>(&mut self, pin: &mut P) -> u16
@@ -390,18 +366,16 @@ impl<'d, T: Instance> Adc<'d, T> {
390 P: AdcPin<T>, 366 P: AdcPin<T>,
391 P: crate::gpio::sealed::Pin, 367 P: crate::gpio::sealed::Pin,
392 { 368 {
393 unsafe { 369 pin.set_as_analog();
394 pin.set_as_analog();
395 370
396 self.read_channel(pin.channel()) 371 self.read_channel(pin.channel())
397 }
398 } 372 }
399 373
400 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { 374 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
401 unsafe { self.read_channel(channel.channel()) } 375 self.read_channel(channel.channel())
402 } 376 }
403 377
404 unsafe fn read_channel(&mut self, channel: u8) -> u16 { 378 fn read_channel(&mut self, channel: u8) -> u16 {
405 // Configure channel 379 // Configure channel
406 Self::set_channel_sample_time(channel, self.sample_time); 380 Self::set_channel_sample_time(channel, self.sample_time);
407 381
@@ -417,7 +391,7 @@ impl<'d, T: Instance> Adc<'d, T> {
417 self.convert() 391 self.convert()
418 } 392 }
419 393
420 unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 394 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
421 let sample_time = sample_time.into(); 395 let sample_time = sample_time.into();
422 if ch <= 9 { 396 if ch <= 9 {
423 T::regs().smpr(0).modify(|reg| reg.set_smp(ch as _, sample_time)); 397 T::regs().smpr(0).modify(|reg| reg.set_smp(ch as _, sample_time));
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index bd92b35a0..85f6e99ac 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -20,10 +20,8 @@ impl<'d, T: Instance> Can<'d, T> {
20 ) -> Self { 20 ) -> Self {
21 into_ref!(peri, rx, tx); 21 into_ref!(peri, rx, tx);
22 22
23 unsafe { 23 rx.set_as_af(rx.af_num(), AFType::Input);
24 rx.set_as_af(rx.af_num(), AFType::Input); 24 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
25 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
26 }
27 25
28 T::enable(); 26 T::enable();
29 T::reset(); 27 T::reset();
@@ -42,10 +40,8 @@ impl<'d, T: Instance> Can<'d, T> {
42 ) -> Self { 40 ) -> Self {
43 into_ref!(peri, rx, tx); 41 into_ref!(peri, rx, tx);
44 42
45 unsafe { 43 rx.set_as_af(rx.af_num(), AFType::Input);
46 rx.set_as_af(rx.af_num(), AFType::Input); 44 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
47 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
48 }
49 45
50 T::enable(); 46 T::enable();
51 T::reset(); 47 T::reset();
@@ -60,7 +56,7 @@ impl<'d, T: Instance> Drop for Can<'d, T> {
60 fn drop(&mut self) { 56 fn drop(&mut self) {
61 // Cannot call `free()` because it moves the instance. 57 // Cannot call `free()` because it moves the instance.
62 // Manually reset the peripheral. 58 // Manually reset the peripheral.
63 unsafe { T::regs().mcr().write(|w| w.set_reset(true)) } 59 T::regs().mcr().write(|w| w.set_reset(true));
64 T::disable(); 60 T::disable();
65 } 61 }
66} 62}
@@ -98,7 +94,7 @@ unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> {
98foreach_peripheral!( 94foreach_peripheral!(
99 (can, $inst:ident) => { 95 (can, $inst:ident) => {
100 impl sealed::Instance for peripherals::$inst { 96 impl sealed::Instance for peripherals::$inst {
101 const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.0 as *mut _; 97 const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _;
102 98
103 fn regs() -> &'static crate::pac::can::Can { 99 fn regs() -> &'static crate::pac::can::Can {
104 &crate::pac::$inst 100 &crate::pac::$inst
diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs
index 393089eed..3946a2d47 100644
--- a/embassy-stm32/src/crc/v1.rs
+++ b/embassy-stm32/src/crc/v1.rs
@@ -27,26 +27,24 @@ impl<'d> Crc<'d> {
27 27
28 /// Resets the CRC unit to default value (0xFFFF_FFFF) 28 /// Resets the CRC unit to default value (0xFFFF_FFFF)
29 pub fn reset(&mut self) { 29 pub fn reset(&mut self) {
30 unsafe { PAC_CRC.cr().write(|w| w.set_reset(true)) }; 30 PAC_CRC.cr().write(|w| w.set_reset(true));
31 } 31 }
32 32
33 /// Feeds a word to the peripheral and returns the current CRC value 33 /// Feeds a word to the peripheral and returns the current CRC value
34 pub fn feed_word(&mut self, word: u32) -> u32 { 34 pub fn feed_word(&mut self, word: u32) -> u32 {
35 // write a single byte to the device, and return the result 35 // write a single byte to the device, and return the result
36 unsafe { 36 PAC_CRC.dr().write_value(word);
37 PAC_CRC.dr().write_value(word);
38 }
39 self.read() 37 self.read()
40 } 38 }
41 /// Feed a slice of words to the peripheral and return the result. 39 /// Feed a slice of words to the peripheral and return the result.
42 pub fn feed_words(&mut self, words: &[u32]) -> u32 { 40 pub fn feed_words(&mut self, words: &[u32]) -> u32 {
43 for word in words { 41 for word in words {
44 unsafe { PAC_CRC.dr().write_value(*word) } 42 PAC_CRC.dr().write_value(*word);
45 } 43 }
46 44
47 self.read() 45 self.read()
48 } 46 }
49 pub fn read(&self) -> u32 { 47 pub fn read(&self) -> u32 {
50 unsafe { PAC_CRC.dr().read() } 48 PAC_CRC.dr().read()
51 } 49 }
52} 50}
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs
index 8acb3a770..f337055a7 100644
--- a/embassy-stm32/src/crc/v2v3.rs
+++ b/embassy-stm32/src/crc/v2v3.rs
@@ -85,95 +85,79 @@ impl<'d> Crc<'d> {
85 } 85 }
86 86
87 pub fn reset(&mut self) { 87 pub fn reset(&mut self) {
88 unsafe { 88 PAC_CRC.cr().modify(|w| w.set_reset(true));
89 PAC_CRC.cr().modify(|w| w.set_reset(true));
90 }
91 } 89 }
92 90
93 /// Reconfigures the CRC peripheral. Doesn't reset. 91 /// Reconfigures the CRC peripheral. Doesn't reset.
94 fn reconfigure(&mut self) { 92 fn reconfigure(&mut self) {
95 unsafe { 93 // Init CRC value
96 // Init CRC value 94 PAC_CRC.init().write_value(self._config.crc_init_value);
97 PAC_CRC.init().write_value(self._config.crc_init_value); 95 #[cfg(crc_v3)]
98 #[cfg(crc_v3)] 96 PAC_CRC.pol().write_value(self._config.crc_poly);
99 PAC_CRC.pol().write_value(self._config.crc_poly);
100 97
101 // configure CR components 98 // configure CR components
102 // (reverse I/O, polysize, poly) 99 // (reverse I/O, polysize, poly)
103 PAC_CRC.cr().write(|w| { 100 PAC_CRC.cr().write(|w| {
104 // configure reverse output 101 // configure reverse output
105 w.set_rev_out(match self._config.reverse_out { 102 w.set_rev_out(match self._config.reverse_out {
106 true => vals::RevOut::REVERSED, 103 true => vals::RevOut::REVERSED,
107 false => vals::RevOut::NORMAL, 104 false => vals::RevOut::NORMAL,
108 }); 105 });
109 // configure reverse input 106 // configure reverse input
110 w.set_rev_in(match self._config.reverse_in { 107 w.set_rev_in(match self._config.reverse_in {
111 InputReverseConfig::None => vals::RevIn::NORMAL, 108 InputReverseConfig::None => vals::RevIn::NORMAL,
112 InputReverseConfig::Byte => vals::RevIn::BYTE, 109 InputReverseConfig::Byte => vals::RevIn::BYTE,
113 InputReverseConfig::Halfword => vals::RevIn::HALFWORD, 110 InputReverseConfig::Halfword => vals::RevIn::HALFWORD,
114 InputReverseConfig::Word => vals::RevIn::WORD, 111 InputReverseConfig::Word => vals::RevIn::WORD,
115 }); 112 });
116 // configure the polynomial. 113 // configure the polynomial.
117 #[cfg(crc_v3)] 114 #[cfg(crc_v3)]
118 w.set_polysize(match self._config.poly_size { 115 w.set_polysize(match self._config.poly_size {
119 PolySize::Width7 => vals::Polysize::POLYSIZE7, 116 PolySize::Width7 => vals::Polysize::POLYSIZE7,
120 PolySize::Width8 => vals::Polysize::POLYSIZE8, 117 PolySize::Width8 => vals::Polysize::POLYSIZE8,
121 PolySize::Width16 => vals::Polysize::POLYSIZE16, 118 PolySize::Width16 => vals::Polysize::POLYSIZE16,
122 PolySize::Width32 => vals::Polysize::POLYSIZE32, 119 PolySize::Width32 => vals::Polysize::POLYSIZE32,
123 }); 120 });
124 }) 121 });
125 }
126 122
127 self.reset(); 123 self.reset();
128 } 124 }
129 125
130 /// Feeds a byte into the CRC peripheral. Returns the computed checksum. 126 /// Feeds a byte into the CRC peripheral. Returns the computed checksum.
131 pub fn feed_byte(&mut self, byte: u8) -> u32 { 127 pub fn feed_byte(&mut self, byte: u8) -> u32 {
132 unsafe { 128 PAC_CRC.dr8().write_value(byte);
133 PAC_CRC.dr8().write_value(byte); 129 PAC_CRC.dr().read()
134 PAC_CRC.dr().read()
135 }
136 } 130 }
137 131
138 /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. 132 /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum.
139 pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { 133 pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 {
140 for byte in bytes { 134 for byte in bytes {
141 unsafe { 135 PAC_CRC.dr8().write_value(*byte);
142 PAC_CRC.dr8().write_value(*byte);
143 }
144 } 136 }
145 unsafe { PAC_CRC.dr().read() } 137 PAC_CRC.dr().read()
146 } 138 }
147 /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. 139 /// Feeds a halfword into the CRC peripheral. Returns the computed checksum.
148 pub fn feed_halfword(&mut self, halfword: u16) -> u32 { 140 pub fn feed_halfword(&mut self, halfword: u16) -> u32 {
149 unsafe { 141 PAC_CRC.dr16().write_value(halfword);
150 PAC_CRC.dr16().write_value(halfword); 142 PAC_CRC.dr().read()
151 PAC_CRC.dr().read()
152 }
153 } 143 }
154 /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. 144 /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum.
155 pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { 145 pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 {
156 for halfword in halfwords { 146 for halfword in halfwords {
157 unsafe { 147 PAC_CRC.dr16().write_value(*halfword);
158 PAC_CRC.dr16().write_value(*halfword);
159 }
160 } 148 }
161 unsafe { PAC_CRC.dr().read() } 149 PAC_CRC.dr().read()
162 } 150 }
163 /// Feeds a words into the CRC peripheral. Returns the computed checksum. 151 /// Feeds a words into the CRC peripheral. Returns the computed checksum.
164 pub fn feed_word(&mut self, word: u32) -> u32 { 152 pub fn feed_word(&mut self, word: u32) -> u32 {
165 unsafe { 153 PAC_CRC.dr().write_value(word as u32);
166 PAC_CRC.dr().write_value(word as u32); 154 PAC_CRC.dr().read()
167 PAC_CRC.dr().read()
168 }
169 } 155 }
170 /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. 156 /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum.
171 pub fn feed_words(&mut self, words: &[u32]) -> u32 { 157 pub fn feed_words(&mut self, words: &[u32]) -> u32 {
172 for word in words { 158 for word in words {
173 unsafe { 159 PAC_CRC.dr().write_value(*word as u32);
174 PAC_CRC.dr().write_value(*word as u32);
175 }
176 } 160 }
177 unsafe { PAC_CRC.dr().read() } 161 PAC_CRC.dr().read()
178 } 162 }
179} 163}
diff --git a/embassy-stm32/src/dac.rs b/embassy-stm32/src/dac.rs
index 60e856c78..631118877 100644
--- a/embassy-stm32/src/dac.rs
+++ b/embassy-stm32/src/dac.rs
@@ -121,13 +121,11 @@ impl<'d, T: Instance> Dac<'d, T> {
121 T::enable(); 121 T::enable();
122 T::reset(); 122 T::reset();
123 123
124 unsafe { 124 T::regs().cr().modify(|reg| {
125 T::regs().cr().modify(|reg| { 125 for ch in 0..channels {
126 for ch in 0..channels { 126 reg.set_en(ch as usize, true);
127 reg.set_en(ch as usize, true); 127 }
128 } 128 });
129 });
130 }
131 129
132 Self { channels, _peri: peri } 130 Self { channels, _peri: peri }
133 } 131 }
@@ -143,11 +141,9 @@ impl<'d, T: Instance> Dac<'d, T> {
143 141
144 fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { 142 fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> {
145 self.check_channel_exists(ch)?; 143 self.check_channel_exists(ch)?;
146 unsafe { 144 T::regs().cr().modify(|reg| {
147 T::regs().cr().modify(|reg| { 145 reg.set_en(ch.index(), on);
148 reg.set_en(ch.index(), on); 146 });
149 })
150 }
151 Ok(()) 147 Ok(())
152 } 148 }
153 149
@@ -162,56 +158,42 @@ impl<'d, T: Instance> Dac<'d, T> {
162 pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { 158 pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> {
163 self.check_channel_exists(Channel::Ch1)?; 159 self.check_channel_exists(Channel::Ch1)?;
164 unwrap!(self.disable_channel(Channel::Ch1)); 160 unwrap!(self.disable_channel(Channel::Ch1));
165 unsafe { 161 T::regs().cr().modify(|reg| {
166 T::regs().cr().modify(|reg| { 162 reg.set_tsel1(trigger.tsel());
167 reg.set_tsel1(trigger.tsel()); 163 });
168 })
169 }
170 Ok(()) 164 Ok(())
171 } 165 }
172 166
173 pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { 167 pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> {
174 self.check_channel_exists(Channel::Ch2)?; 168 self.check_channel_exists(Channel::Ch2)?;
175 unwrap!(self.disable_channel(Channel::Ch2)); 169 unwrap!(self.disable_channel(Channel::Ch2));
176 unsafe { 170 T::regs().cr().modify(|reg| {
177 T::regs().cr().modify(|reg| { 171 reg.set_tsel2(trigger.tsel());
178 reg.set_tsel2(trigger.tsel()); 172 });
179 })
180 }
181 Ok(()) 173 Ok(())
182 } 174 }
183 175
184 pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { 176 pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> {
185 self.check_channel_exists(ch)?; 177 self.check_channel_exists(ch)?;
186 unsafe { 178 T::regs().swtrigr().write(|reg| {
187 T::regs().swtrigr().write(|reg| { 179 reg.set_swtrig(ch.index(), true);
188 reg.set_swtrig(ch.index(), true); 180 });
189 });
190 }
191 Ok(()) 181 Ok(())
192 } 182 }
193 183
194 pub fn trigger_all(&mut self) { 184 pub fn trigger_all(&mut self) {
195 unsafe { 185 T::regs().swtrigr().write(|reg| {
196 T::regs().swtrigr().write(|reg| { 186 reg.set_swtrig(Channel::Ch1.index(), true);
197 reg.set_swtrig(Channel::Ch1.index(), true); 187 reg.set_swtrig(Channel::Ch2.index(), true);
198 reg.set_swtrig(Channel::Ch2.index(), true); 188 });
199 })
200 }
201 } 189 }
202 190
203 pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { 191 pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> {
204 self.check_channel_exists(ch)?; 192 self.check_channel_exists(ch)?;
205 match value { 193 match value {
206 Value::Bit8(v) => unsafe { 194 Value::Bit8(v) => T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)),
207 T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)); 195 Value::Bit12(v, Alignment::Left) => T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)),
208 }, 196 Value::Bit12(v, Alignment::Right) => T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)),
209 Value::Bit12(v, Alignment::Left) => unsafe {
210 T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v));
211 },
212 Value::Bit12(v, Alignment::Right) => unsafe {
213 T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v));
214 },
215 } 197 }
216 Ok(()) 198 Ok(())
217 } 199 }
@@ -239,20 +221,20 @@ foreach_peripheral!(
239 } 221 }
240 222
241 fn reset() { 223 fn reset() {
242 critical_section::with(|_| unsafe { 224 critical_section::with(|_| {
243 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); 225 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true));
244 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); 226 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false));
245 }) 227 })
246 } 228 }
247 229
248 fn enable() { 230 fn enable() {
249 critical_section::with(|_| unsafe { 231 critical_section::with(|_| {
250 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); 232 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
251 }) 233 })
252 } 234 }
253 235
254 fn disable() { 236 fn disable() {
255 critical_section::with(|_| unsafe { 237 critical_section::with(|_| {
256 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)); 238 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false));
257 }) 239 })
258 } 240 }
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index 41305d273..78b026cb6 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -96,8 +96,7 @@ impl Default for Config {
96macro_rules! config_pins { 96macro_rules! config_pins {
97 ($($pin:ident),*) => { 97 ($($pin:ident),*) => {
98 into_ref!($($pin),*); 98 into_ref!($($pin),*);
99 // NOTE(unsafe) Exclusive access to the registers 99 critical_section::with(|_| {
100 critical_section::with(|_| unsafe {
101 $( 100 $(
102 $pin.set_as_af($pin.af_num(), AFType::Input); 101 $pin.set_as_af($pin.af_num(), AFType::Input);
103 $pin.set_speed(Speed::VeryHigh); 102 $pin.set_speed(Speed::VeryHigh);
@@ -334,17 +333,15 @@ where
334 T::reset(); 333 T::reset();
335 T::enable(); 334 T::enable();
336 335
337 unsafe { 336 peri.regs().cr().modify(|r| {
338 peri.regs().cr().modify(|r| { 337 r.set_cm(true); // disable continuous mode (snapshot mode)
339 r.set_cm(true); // disable continuous mode (snapshot mode) 338 r.set_ess(use_embedded_synchronization);
340 r.set_ess(use_embedded_synchronization); 339 r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge);
341 r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge); 340 r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High);
342 r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High); 341 r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High);
343 r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High); 342 r.set_fcrc(0x00); // capture every frame
344 r.set_fcrc(0x00); // capture every frame 343 r.set_edm(edm); // extended data mode
345 r.set_edm(edm); // extended data mode 344 });
346 });
347 }
348 345
349 T::Interrupt::unpend(); 346 T::Interrupt::unpend();
350 unsafe { T::Interrupt::enable() }; 347 unsafe { T::Interrupt::enable() };
@@ -352,7 +349,7 @@ where
352 Self { inner: peri, dma } 349 Self { inner: peri, dma }
353 } 350 }
354 351
355 unsafe fn toggle(enable: bool) { 352 fn toggle(enable: bool) {
356 crate::pac::DCMI.cr().modify(|r| { 353 crate::pac::DCMI.cr().modify(|r| {
357 r.set_enable(enable); 354 r.set_enable(enable);
358 r.set_capture(enable); 355 r.set_capture(enable);
@@ -360,23 +357,19 @@ where
360 } 357 }
361 358
362 fn enable_irqs() { 359 fn enable_irqs() {
363 unsafe { 360 crate::pac::DCMI.ier().modify(|r| {
364 crate::pac::DCMI.ier().modify(|r| { 361 r.set_err_ie(true);
365 r.set_err_ie(true); 362 r.set_ovr_ie(true);
366 r.set_ovr_ie(true); 363 r.set_frame_ie(true);
367 r.set_frame_ie(true); 364 });
368 });
369 }
370 } 365 }
371 366
372 fn clear_interrupt_flags() { 367 fn clear_interrupt_flags() {
373 unsafe { 368 crate::pac::DCMI.icr().write(|r| {
374 crate::pac::DCMI.icr().write(|r| { 369 r.set_ovr_isc(true);
375 r.set_ovr_isc(true); 370 r.set_err_isc(true);
376 r.set_err_isc(true); 371 r.set_frame_isc(true);
377 r.set_frame_isc(true); 372 })
378 })
379 }
380 } 373 }
381 374
382 /// This method starts the capture and finishes when both the dma transfer and DCMI finish the frame transfer. 375 /// This method starts the capture and finishes when both the dma transfer and DCMI finish the frame transfer.
@@ -392,41 +385,30 @@ where
392 return self.capture_giant(buffer).await; 385 return self.capture_giant(buffer).await;
393 } 386 }
394 } 387 }
388
395 async fn capture_small(&mut self, buffer: &mut [u32]) -> Result<(), Error> { 389 async fn capture_small(&mut self, buffer: &mut [u32]) -> Result<(), Error> {
396 let r = self.inner.regs(); 390 let r = self.inner.regs();
397 let src = r.dr().ptr() as *mut u32; 391 let src = r.dr().as_ptr() as *mut u32;
398 let request = self.dma.request(); 392 let request = self.dma.request();
399 let dma_read = unsafe { Transfer::new_read(&mut self.dma, request, src, buffer, Default::default()) }; 393 let dma_read = unsafe { Transfer::new_read(&mut self.dma, request, src, buffer, Default::default()) };
400 394
401 Self::clear_interrupt_flags(); 395 Self::clear_interrupt_flags();
402 Self::enable_irqs(); 396 Self::enable_irqs();
403 397
404 unsafe { Self::toggle(true) }; 398 Self::toggle(true);
405 399
406 let result = poll_fn(|cx| { 400 let result = poll_fn(|cx| {
407 STATE.waker.register(cx.waker()); 401 STATE.waker.register(cx.waker());
408 402
409 let ris = unsafe { crate::pac::DCMI.ris().read() }; 403 let ris = crate::pac::DCMI.ris().read();
410 if ris.err_ris() { 404 if ris.err_ris() {
411 unsafe { 405 crate::pac::DCMI.icr().write(|r| r.set_err_isc(true));
412 crate::pac::DCMI.icr().write(|r| {
413 r.set_err_isc(true);
414 })
415 };
416 Poll::Ready(Err(Error::PeripheralError)) 406 Poll::Ready(Err(Error::PeripheralError))
417 } else if ris.ovr_ris() { 407 } else if ris.ovr_ris() {
418 unsafe { 408 crate::pac::DCMI.icr().write(|r| r.set_ovr_isc(true));
419 crate::pac::DCMI.icr().write(|r| {
420 r.set_ovr_isc(true);
421 })
422 };
423 Poll::Ready(Err(Error::Overrun)) 409 Poll::Ready(Err(Error::Overrun))
424 } else if ris.frame_ris() { 410 } else if ris.frame_ris() {
425 unsafe { 411 crate::pac::DCMI.icr().write(|r| r.set_frame_isc(true));
426 crate::pac::DCMI.icr().write(|r| {
427 r.set_frame_isc(true);
428 })
429 };
430 Poll::Ready(Ok(())) 412 Poll::Ready(Ok(()))
431 } else { 413 } else {
432 Poll::Pending 414 Poll::Pending
@@ -435,7 +417,7 @@ where
435 417
436 let (_, result) = embassy_futures::join::join(dma_read, result).await; 418 let (_, result) = embassy_futures::join::join(dma_read, result).await;
437 419
438 unsafe { Self::toggle(false) }; 420 Self::toggle(false);
439 421
440 result 422 result
441 } 423 }
@@ -468,7 +450,7 @@ where
468 let request = channel.request(); 450 let request = channel.request();
469 451
470 let r = self.inner.regs(); 452 let r = self.inner.regs();
471 let src = r.dr().ptr() as *mut u32; 453 let src = r.dr().as_ptr() as *mut u32;
472 454
473 let mut transfer = unsafe { 455 let mut transfer = unsafe {
474 crate::dma::DoubleBuffered::new_read( 456 crate::dma::DoubleBuffered::new_read(
@@ -526,38 +508,26 @@ where
526 let result = poll_fn(|cx| { 508 let result = poll_fn(|cx| {
527 STATE.waker.register(cx.waker()); 509 STATE.waker.register(cx.waker());
528 510
529 let ris = unsafe { crate::pac::DCMI.ris().read() }; 511 let ris = crate::pac::DCMI.ris().read();
530 if ris.err_ris() { 512 if ris.err_ris() {
531 unsafe { 513 crate::pac::DCMI.icr().write(|r| r.set_err_isc(true));
532 crate::pac::DCMI.icr().write(|r| {
533 r.set_err_isc(true);
534 })
535 };
536 Poll::Ready(Err(Error::PeripheralError)) 514 Poll::Ready(Err(Error::PeripheralError))
537 } else if ris.ovr_ris() { 515 } else if ris.ovr_ris() {
538 unsafe { 516 crate::pac::DCMI.icr().write(|r| r.set_ovr_isc(true));
539 crate::pac::DCMI.icr().write(|r| {
540 r.set_ovr_isc(true);
541 })
542 };
543 Poll::Ready(Err(Error::Overrun)) 517 Poll::Ready(Err(Error::Overrun))
544 } else if ris.frame_ris() { 518 } else if ris.frame_ris() {
545 unsafe { 519 crate::pac::DCMI.icr().write(|r| r.set_frame_isc(true));
546 crate::pac::DCMI.icr().write(|r| {
547 r.set_frame_isc(true);
548 })
549 };
550 Poll::Ready(Ok(())) 520 Poll::Ready(Ok(()))
551 } else { 521 } else {
552 Poll::Pending 522 Poll::Pending
553 } 523 }
554 }); 524 });
555 525
556 unsafe { Self::toggle(true) }; 526 Self::toggle(true);
557 527
558 let (_, result) = embassy_futures::join::join(dma_result, result).await; 528 let (_, result) = embassy_futures::join::join(dma_result, result).await;
559 529
560 unsafe { Self::toggle(false) }; 530 Self::toggle(false);
561 531
562 result 532 result
563 } 533 }
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index c0a503e25..a307c803c 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -107,7 +107,7 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index
107 let cr = dma.ch(channel_num).cr(); 107 let cr = dma.ch(channel_num).cr();
108 108
109 if isr.teif(channel_num) { 109 if isr.teif(channel_num) {
110 panic!("DMA: error on BDMA@{:08x} channel {}", dma.0 as u32, channel_num); 110 panic!("DMA: error on BDMA@{:08x} channel {}", dma.as_ptr() as u32, channel_num);
111 } 111 }
112 112
113 if isr.htif(channel_num) && cr.read().htie() { 113 if isr.htif(channel_num) && cr.read().htie() {
@@ -291,29 +291,25 @@ impl<'a, C: Channel> Transfer<'a, C> {
291 } 291 }
292 292
293 fn clear_irqs(&mut self) { 293 fn clear_irqs(&mut self) {
294 unsafe { 294 self.channel.regs().ifcr().write(|w| {
295 self.channel.regs().ifcr().write(|w| { 295 w.set_tcif(self.channel.num(), true);
296 w.set_tcif(self.channel.num(), true); 296 w.set_teif(self.channel.num(), true);
297 w.set_teif(self.channel.num(), true); 297 });
298 })
299 }
300 } 298 }
301 299
302 pub fn request_stop(&mut self) { 300 pub fn request_stop(&mut self) {
303 let ch = self.channel.regs().ch(self.channel.num()); 301 let ch = self.channel.regs().ch(self.channel.num());
304 302
305 // Disable the channel. Keep the IEs enabled so the irqs still fire. 303 // Disable the channel. Keep the IEs enabled so the irqs still fire.
306 unsafe { 304 ch.cr().write(|w| {
307 ch.cr().write(|w| { 305 w.set_teie(true);
308 w.set_teie(true); 306 w.set_tcie(true);
309 w.set_tcie(true); 307 });
310 })
311 }
312 } 308 }
313 309
314 pub fn is_running(&mut self) -> bool { 310 pub fn is_running(&mut self) -> bool {
315 let ch = self.channel.regs().ch(self.channel.num()); 311 let ch = self.channel.regs().ch(self.channel.num());
316 let en = unsafe { ch.cr().read() }.en(); 312 let en = ch.cr().read().en();
317 let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; 313 let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0;
318 en && !tcif 314 en && !tcif
319 } 315 }
@@ -322,11 +318,12 @@ impl<'a, C: Channel> Transfer<'a, C> {
322 /// Note: this will be zero for transfers that completed without cancellation. 318 /// Note: this will be zero for transfers that completed without cancellation.
323 pub fn get_remaining_transfers(&self) -> u16 { 319 pub fn get_remaining_transfers(&self) -> u16 {
324 let ch = self.channel.regs().ch(self.channel.num()); 320 let ch = self.channel.regs().ch(self.channel.num());
325 unsafe { ch.ndtr().read() }.ndt() 321 ch.ndtr().read().ndt()
326 } 322 }
327 323
328 pub fn blocking_wait(mut self) { 324 pub fn blocking_wait(mut self) {
329 while self.is_running() {} 325 while self.is_running() {}
326 self.request_stop();
330 327
331 // "Subsequent reads and writes cannot be moved ahead of preceding reads." 328 // "Subsequent reads and writes cannot be moved ahead of preceding reads."
332 fence(Ordering::SeqCst); 329 fence(Ordering::SeqCst);
@@ -366,7 +363,7 @@ struct DmaCtrlImpl<'a, C: Channel>(PeripheralRef<'a, C>);
366impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { 363impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
367 fn get_remaining_transfers(&self) -> usize { 364 fn get_remaining_transfers(&self) -> usize {
368 let ch = self.0.regs().ch(self.0.num()); 365 let ch = self.0.regs().ch(self.0.num());
369 unsafe { ch.ndtr().read() }.ndt() as usize 366 ch.ndtr().read().ndt() as usize
370 } 367 }
371 368
372 fn get_complete_count(&self) -> usize { 369 fn get_complete_count(&self) -> usize {
@@ -442,7 +439,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
442 439
443 pub fn start(&mut self) { 440 pub fn start(&mut self) {
444 let ch = self.channel.regs().ch(self.channel.num()); 441 let ch = self.channel.regs().ch(self.channel.num());
445 unsafe { ch.cr().write_value(self.cr) } 442 ch.cr().write_value(self.cr)
446 } 443 }
447 444
448 pub fn clear(&mut self) { 445 pub fn clear(&mut self) {
@@ -469,31 +466,27 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
469 466
470 fn clear_irqs(&mut self) { 467 fn clear_irqs(&mut self) {
471 let dma = self.channel.regs(); 468 let dma = self.channel.regs();
472 unsafe { 469 dma.ifcr().write(|w| {
473 dma.ifcr().write(|w| { 470 w.set_htif(self.channel.num(), true);
474 w.set_htif(self.channel.num(), true); 471 w.set_tcif(self.channel.num(), true);
475 w.set_tcif(self.channel.num(), true); 472 w.set_teif(self.channel.num(), true);
476 w.set_teif(self.channel.num(), true); 473 });
477 })
478 }
479 } 474 }
480 475
481 pub fn request_stop(&mut self) { 476 pub fn request_stop(&mut self) {
482 let ch = self.channel.regs().ch(self.channel.num()); 477 let ch = self.channel.regs().ch(self.channel.num());
483 478
484 // Disable the channel. Keep the IEs enabled so the irqs still fire. 479 // Disable the channel. Keep the IEs enabled so the irqs still fire.
485 unsafe { 480 ch.cr().write(|w| {
486 ch.cr().write(|w| { 481 w.set_teie(true);
487 w.set_teie(true); 482 w.set_htie(true);
488 w.set_htie(true); 483 w.set_tcie(true);
489 w.set_tcie(true); 484 });
490 })
491 }
492 } 485 }
493 486
494 pub fn is_running(&mut self) -> bool { 487 pub fn is_running(&mut self) -> bool {
495 let ch = self.channel.regs().ch(self.channel.num()); 488 let ch = self.channel.regs().ch(self.channel.num());
496 unsafe { ch.cr().read() }.en() 489 ch.cr().read().en()
497 } 490 }
498} 491}
499 492
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index 874cb013a..8abe541d3 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -183,7 +183,7 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: usize, index:
183 let isr = dma.isr(channel_num / 4).read(); 183 let isr = dma.isr(channel_num / 4).read();
184 184
185 if isr.teif(channel_num % 4) { 185 if isr.teif(channel_num % 4) {
186 panic!("DMA: error on DMA@{:08x} channel {}", dma.0 as u32, channel_num); 186 panic!("DMA: error on DMA@{:08x} channel {}", dma.as_ptr() as u32, channel_num);
187 } 187 }
188 188
189 if isr.htif(channel_num % 4) && cr.read().htie() { 189 if isr.htif(channel_num % 4) && cr.read().htie() {
@@ -387,36 +387,32 @@ impl<'a, C: Channel> Transfer<'a, C> {
387 let isrn = self.channel.num() / 4; 387 let isrn = self.channel.num() / 4;
388 let isrbit = self.channel.num() % 4; 388 let isrbit = self.channel.num() % 4;
389 389
390 unsafe { 390 self.channel.regs().ifcr(isrn).write(|w| {
391 self.channel.regs().ifcr(isrn).write(|w| { 391 w.set_tcif(isrbit, true);
392 w.set_tcif(isrbit, true); 392 w.set_teif(isrbit, true);
393 w.set_teif(isrbit, true); 393 });
394 })
395 }
396 } 394 }
397 395
398 pub fn request_stop(&mut self) { 396 pub fn request_stop(&mut self) {
399 let ch = self.channel.regs().st(self.channel.num()); 397 let ch = self.channel.regs().st(self.channel.num());
400 398
401 // Disable the channel. Keep the IEs enabled so the irqs still fire. 399 // Disable the channel. Keep the IEs enabled so the irqs still fire.
402 unsafe { 400 ch.cr().write(|w| {
403 ch.cr().write(|w| { 401 w.set_teie(true);
404 w.set_teie(true); 402 w.set_tcie(true);
405 w.set_tcie(true); 403 });
406 })
407 }
408 } 404 }
409 405
410 pub fn is_running(&mut self) -> bool { 406 pub fn is_running(&mut self) -> bool {
411 let ch = self.channel.regs().st(self.channel.num()); 407 let ch = self.channel.regs().st(self.channel.num());
412 unsafe { ch.cr().read() }.en() 408 ch.cr().read().en()
413 } 409 }
414 410
415 /// Gets the total remaining transfers for the channel 411 /// Gets the total remaining transfers for the channel
416 /// Note: this will be zero for transfers that completed without cancellation. 412 /// Note: this will be zero for transfers that completed without cancellation.
417 pub fn get_remaining_transfers(&self) -> u16 { 413 pub fn get_remaining_transfers(&self) -> u16 {
418 let ch = self.channel.regs().st(self.channel.num()); 414 let ch = self.channel.regs().st(self.channel.num());
419 unsafe { ch.ndtr().read() }.ndt() 415 ch.ndtr().read().ndt()
420 } 416 }
421 417
422 pub fn blocking_wait(mut self) { 418 pub fn blocking_wait(mut self) {
@@ -537,13 +533,11 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
537 let isrn = channel_number / 4; 533 let isrn = channel_number / 4;
538 let isrbit = channel_number % 4; 534 let isrbit = channel_number % 4;
539 535
540 unsafe { 536 dma.ifcr(isrn).write(|w| {
541 dma.ifcr(isrn).write(|w| { 537 w.set_htif(isrbit, true);
542 w.set_htif(isrbit, true); 538 w.set_tcif(isrbit, true);
543 w.set_tcif(isrbit, true); 539 w.set_teif(isrbit, true);
544 w.set_teif(isrbit, true); 540 });
545 })
546 }
547 } 541 }
548 542
549 pub unsafe fn set_buffer0(&mut self, buffer: *mut W) { 543 pub unsafe fn set_buffer0(&mut self, buffer: *mut W) {
@@ -558,7 +552,7 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
558 552
559 pub fn is_buffer0_accessible(&mut self) -> bool { 553 pub fn is_buffer0_accessible(&mut self) -> bool {
560 let ch = self.channel.regs().st(self.channel.num()); 554 let ch = self.channel.regs().st(self.channel.num());
561 unsafe { ch.cr().read() }.ct() == vals::Ct::MEMORY1 555 ch.cr().read().ct() == vals::Ct::MEMORY1
562 } 556 }
563 557
564 pub fn set_waker(&mut self, waker: &Waker) { 558 pub fn set_waker(&mut self, waker: &Waker) {
@@ -569,24 +563,22 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
569 let ch = self.channel.regs().st(self.channel.num()); 563 let ch = self.channel.regs().st(self.channel.num());
570 564
571 // Disable the channel. Keep the IEs enabled so the irqs still fire. 565 // Disable the channel. Keep the IEs enabled so the irqs still fire.
572 unsafe { 566 ch.cr().write(|w| {
573 ch.cr().write(|w| { 567 w.set_teie(true);
574 w.set_teie(true); 568 w.set_tcie(true);
575 w.set_tcie(true); 569 });
576 })
577 }
578 } 570 }
579 571
580 pub fn is_running(&mut self) -> bool { 572 pub fn is_running(&mut self) -> bool {
581 let ch = self.channel.regs().st(self.channel.num()); 573 let ch = self.channel.regs().st(self.channel.num());
582 unsafe { ch.cr().read() }.en() 574 ch.cr().read().en()
583 } 575 }
584 576
585 /// Gets the total remaining transfers for the channel 577 /// Gets the total remaining transfers for the channel
586 /// Note: this will be zero for transfers that completed without cancellation. 578 /// Note: this will be zero for transfers that completed without cancellation.
587 pub fn get_remaining_transfers(&self) -> u16 { 579 pub fn get_remaining_transfers(&self) -> u16 {
588 let ch = self.channel.regs().st(self.channel.num()); 580 let ch = self.channel.regs().st(self.channel.num());
589 unsafe { ch.ndtr().read() }.ndt() 581 ch.ndtr().read().ndt()
590 } 582 }
591} 583}
592 584
@@ -607,7 +599,7 @@ struct DmaCtrlImpl<'a, C: Channel>(PeripheralRef<'a, C>);
607impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { 599impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
608 fn get_remaining_transfers(&self) -> usize { 600 fn get_remaining_transfers(&self) -> usize {
609 let ch = self.0.regs().st(self.0.num()); 601 let ch = self.0.regs().st(self.0.num());
610 unsafe { ch.ndtr().read() }.ndt() as usize 602 ch.ndtr().read().ndt() as usize
611 } 603 }
612 604
613 fn get_complete_count(&self) -> usize { 605 fn get_complete_count(&self) -> usize {
@@ -698,7 +690,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
698 690
699 pub fn start(&mut self) { 691 pub fn start(&mut self) {
700 let ch = self.channel.regs().st(self.channel.num()); 692 let ch = self.channel.regs().st(self.channel.num());
701 unsafe { ch.cr().write_value(self.cr) } 693 ch.cr().write_value(self.cr);
702 } 694 }
703 695
704 pub fn clear(&mut self) { 696 pub fn clear(&mut self) {
@@ -729,31 +721,27 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
729 let isrn = channel_number / 4; 721 let isrn = channel_number / 4;
730 let isrbit = channel_number % 4; 722 let isrbit = channel_number % 4;
731 723
732 unsafe { 724 dma.ifcr(isrn).write(|w| {
733 dma.ifcr(isrn).write(|w| { 725 w.set_htif(isrbit, true);
734 w.set_htif(isrbit, true); 726 w.set_tcif(isrbit, true);
735 w.set_tcif(isrbit, true); 727 w.set_teif(isrbit, true);
736 w.set_teif(isrbit, true); 728 });
737 })
738 }
739 } 729 }
740 730
741 pub fn request_stop(&mut self) { 731 pub fn request_stop(&mut self) {
742 let ch = self.channel.regs().st(self.channel.num()); 732 let ch = self.channel.regs().st(self.channel.num());
743 733
744 // Disable the channel. Keep the IEs enabled so the irqs still fire. 734 // Disable the channel. Keep the IEs enabled so the irqs still fire.
745 unsafe { 735 ch.cr().write(|w| {
746 ch.cr().write(|w| { 736 w.set_teie(true);
747 w.set_teie(true); 737 w.set_htie(true);
748 w.set_htie(true); 738 w.set_tcie(true);
749 w.set_tcie(true); 739 });
750 })
751 }
752 } 740 }
753 741
754 pub fn is_running(&mut self) -> bool { 742 pub fn is_running(&mut self) -> bool {
755 let ch = self.channel.regs().st(self.channel.num()); 743 let ch = self.channel.regs().st(self.channel.num());
756 unsafe { ch.cr().read() }.en() 744 ch.cr().read().en()
757 } 745 }
758} 746}
759 747
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs
index a8c4c5827..36fc03403 100644
--- a/embassy-stm32/src/dma/dmamux.rs
+++ b/embassy-stm32/src/dma/dmamux.rs
@@ -2,7 +2,7 @@
2 2
3use crate::{pac, peripherals}; 3use crate::{pac, peripherals};
4 4
5pub(crate) unsafe fn configure_dmamux<M: MuxChannel>(channel: &mut M, request: u8) { 5pub(crate) fn configure_dmamux<M: MuxChannel>(channel: &mut M, request: u8) {
6 let ch_mux_regs = channel.mux_regs().ccr(channel.mux_num()); 6 let ch_mux_regs = channel.mux_regs().ccr(channel.mux_num());
7 ch_mux_regs.write(|reg| { 7 ch_mux_regs.write(|reg| {
8 reg.set_nbreq(0); 8 reg.set_nbreq(0);
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index 3f0d5e8fa..b7bcf7795 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -92,13 +92,15 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::gpdma::Gpdma, channel_num: usize, in
92 if sr.dtef() { 92 if sr.dtef() {
93 panic!( 93 panic!(
94 "DMA: data transfer error on DMA@{:08x} channel {}", 94 "DMA: data transfer error on DMA@{:08x} channel {}",
95 dma.0 as u32, channel_num 95 dma.as_ptr() as u32,
96 channel_num
96 ); 97 );
97 } 98 }
98 if sr.usef() { 99 if sr.usef() {
99 panic!( 100 panic!(
100 "DMA: user settings error on DMA@{:08x} channel {}", 101 "DMA: user settings error on DMA@{:08x} channel {}",
101 dma.0 as u32, channel_num 102 dma.as_ptr() as u32,
103 channel_num
102 ); 104 );
103 } 105 }
104 106
@@ -250,6 +252,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
250 super::dmamux::configure_dmamux(&mut *this.channel, request); 252 super::dmamux::configure_dmamux(&mut *this.channel, request);
251 253
252 ch.cr().write(|w| w.set_reset(true)); 254 ch.cr().write(|w| w.set_reset(true));
255 ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs
253 ch.llr().write(|_| {}); // no linked list 256 ch.llr().write(|_| {}); // no linked list
254 ch.tr1().write(|w| { 257 ch.tr1().write(|w| {
255 w.set_sdw(data_size.into()); 258 w.set_sdw(data_size.into());
@@ -298,26 +301,24 @@ impl<'a, C: Channel> Transfer<'a, C> {
298 let ch = self.channel.regs().ch(self.channel.num()); 301 let ch = self.channel.regs().ch(self.channel.num());
299 302
300 // Disable the channel. Keep the IEs enabled so the irqs still fire. 303 // Disable the channel. Keep the IEs enabled so the irqs still fire.
301 unsafe { 304 ch.cr().write(|w| {
302 ch.cr().write(|w| { 305 w.set_tcie(true);
303 w.set_tcie(true); 306 w.set_useie(true);
304 w.set_useie(true); 307 w.set_dteie(true);
305 w.set_dteie(true); 308 w.set_suspie(true);
306 w.set_suspie(true); 309 })
307 })
308 }
309 } 310 }
310 311
311 pub fn is_running(&mut self) -> bool { 312 pub fn is_running(&mut self) -> bool {
312 let ch = self.channel.regs().ch(self.channel.num()); 313 let ch = self.channel.regs().ch(self.channel.num());
313 !unsafe { ch.sr().read() }.tcf() 314 !ch.sr().read().tcf()
314 } 315 }
315 316
316 /// Gets the total remaining transfers for the channel 317 /// Gets the total remaining transfers for the channel
317 /// Note: this will be zero for transfers that completed without cancellation. 318 /// Note: this will be zero for transfers that completed without cancellation.
318 pub fn get_remaining_transfers(&self) -> u16 { 319 pub fn get_remaining_transfers(&self) -> u16 {
319 let ch = self.channel.regs().ch(self.channel.num()); 320 let ch = self.channel.regs().ch(self.channel.num());
320 unsafe { ch.br1().read() }.bndt() 321 ch.br1().read().bndt()
321 } 322 }
322 323
323 pub fn blocking_wait(mut self) { 324 pub fn blocking_wait(mut self) {
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 540cdd027..b53c2d0fa 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -29,18 +29,16 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl
29 WAKER.wake(); 29 WAKER.wake();
30 30
31 // TODO: Check and clear more flags 31 // TODO: Check and clear more flags
32 unsafe { 32 let dma = ETH.ethernet_dma();
33 let dma = ETH.ethernet_dma(); 33
34 34 dma.dmasr().modify(|w| {
35 dma.dmasr().modify(|w| { 35 w.set_ts(true);
36 w.set_ts(true); 36 w.set_rs(true);
37 w.set_rs(true); 37 w.set_nis(true);
38 w.set_nis(true); 38 });
39 }); 39 // Delay two peripheral's clock
40 // Delay two peripheral's clock 40 dma.dmasr().read();
41 dma.dmasr().read(); 41 dma.dmasr().read();
42 dma.dmasr().read();
43 }
44 } 42 }
45} 43}
46 44
@@ -59,7 +57,6 @@ pub struct Ethernet<'d, T: Instance, P: PHY> {
59#[cfg(eth_v1a)] 57#[cfg(eth_v1a)]
60macro_rules! config_in_pins { 58macro_rules! config_in_pins {
61 ($($pin:ident),*) => { 59 ($($pin:ident),*) => {
62 // NOTE(unsafe) Exclusive access to the registers
63 critical_section::with(|_| { 60 critical_section::with(|_| {
64 $( 61 $(
65 // TODO properly create a set_as_input function 62 // TODO properly create a set_as_input function
@@ -72,7 +69,6 @@ macro_rules! config_in_pins {
72#[cfg(eth_v1a)] 69#[cfg(eth_v1a)]
73macro_rules! config_af_pins { 70macro_rules! config_af_pins {
74 ($($pin:ident),*) => { 71 ($($pin:ident),*) => {
75 // NOTE(unsafe) Exclusive access to the registers
76 critical_section::with(|_| { 72 critical_section::with(|_| {
77 $( 73 $(
78 // We are lucky here, this configures to max speed (50MHz) 74 // We are lucky here, this configures to max speed (50MHz)
@@ -85,7 +81,6 @@ macro_rules! config_af_pins {
85#[cfg(any(eth_v1b, eth_v1c))] 81#[cfg(any(eth_v1b, eth_v1c))]
86macro_rules! config_pins { 82macro_rules! config_pins {
87 ($($pin:ident),*) => { 83 ($($pin:ident),*) => {
88 // NOTE(unsafe) Exclusive access to the registers
89 critical_section::with(|_| { 84 critical_section::with(|_| {
90 $( 85 $(
91 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); 86 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
@@ -116,222 +111,208 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
116 ) -> Self { 111 ) -> Self {
117 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 112 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
118 113
119 unsafe { 114 // Enable the necessary Clocks
120 // Enable the necessary Clocks 115 #[cfg(eth_v1a)]
121 // NOTE(unsafe) We have exclusive access to the registers 116 critical_section::with(|_| {
122 #[cfg(eth_v1a)] 117 RCC.apb2enr().modify(|w| w.set_afioen(true));
123 critical_section::with(|_| {
124 RCC.apb2enr().modify(|w| w.set_afioen(true));
125
126 // Select RMII (Reduced Media Independent Interface)
127 // Must be done prior to enabling peripheral clock
128 AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true));
129
130 RCC.ahbenr().modify(|w| {
131 w.set_ethen(true);
132 w.set_ethtxen(true);
133 w.set_ethrxen(true);
134 });
135 });
136
137 #[cfg(any(eth_v1b, eth_v1c))]
138 critical_section::with(|_| {
139 RCC.apb2enr().modify(|w| w.set_syscfgen(true));
140 RCC.ahb1enr().modify(|w| {
141 w.set_ethen(true);
142 w.set_ethtxen(true);
143 w.set_ethrxen(true);
144 });
145
146 // RMII (Reduced Media Independent Interface)
147 SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true));
148 });
149
150 #[cfg(eth_v1a)]
151 {
152 config_in_pins!(ref_clk, rx_d0, rx_d1);
153 config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en);
154 }
155
156 #[cfg(any(eth_v1b, eth_v1c))]
157 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
158
159 // NOTE(unsafe) We have exclusive access to the registers
160 let dma = ETH.ethernet_dma();
161 let mac = ETH.ethernet_mac();
162
163 // Reset and wait
164 dma.dmabmr().modify(|w| w.set_sr(true));
165 while dma.dmabmr().read().sr() {}
166
167 mac.maccr().modify(|w| {
168 w.set_ifg(Ifg::IFG96); // inter frame gap 96 bit times
169 w.set_apcs(Apcs::STRIP); // automatic padding and crc stripping
170 w.set_fes(Fes::FES100); // fast ethernet speed
171 w.set_dm(Dm::FULLDUPLEX); // full duplex
172 // TODO: Carrier sense ? ECRSFD
173 });
174
175 // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core,
176 // so the LR write must happen after the HR write.
177 mac.maca0hr()
178 .modify(|w| w.set_maca0h(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8)));
179 mac.maca0lr().write(|w| {
180 w.set_maca0l(
181 u32::from(mac_addr[0])
182 | (u32::from(mac_addr[1]) << 8)
183 | (u32::from(mac_addr[2]) << 16)
184 | (u32::from(mac_addr[3]) << 24),
185 )
186 });
187
188 // pause time
189 mac.macfcr().modify(|w| w.set_pt(0x100));
190
191 // Transfer and Forward, Receive and Forward
192 dma.dmaomr().modify(|w| {
193 w.set_tsf(Tsf::STOREFORWARD);
194 w.set_rsf(Rsf::STOREFORWARD);
195 });
196 118
197 dma.dmabmr().modify(|w| { 119 // Select RMII (Reduced Media Independent Interface)
198 w.set_pbl(Pbl::PBL32) // programmable burst length - 32 ? 120 // Must be done prior to enabling peripheral clock
199 }); 121 AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true));
200 122
201 // TODO MTU size setting not found for v1 ethernet, check if correct 123 RCC.ahbenr().modify(|w| {
202 124 w.set_ethen(true);
203 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called 125 w.set_ethtxen(true);
204 let hclk = crate::rcc::get_freqs().ahb1; 126 w.set_ethrxen(true);
205 let hclk_mhz = hclk.0 / 1_000_000;
206
207 // Set the MDC clock frequency in the range 1MHz - 2.5MHz
208 let clock_range = match hclk_mhz {
209 0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."),
210 25..=34 => Cr::CR_20_35, // Divide by 16
211 35..=59 => Cr::CR_35_60, // Divide by 26
212 60..=99 => Cr::CR_60_100, // Divide by 42
213 100..=149 => Cr::CR_100_150, // Divide by 62
214 150..=216 => Cr::CR_150_168, // Divide by 102
215 _ => {
216 panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider")
217 }
218 };
219
220 let pins = [
221 ref_clk.map_into(),
222 mdio.map_into(),
223 mdc.map_into(),
224 crs.map_into(),
225 rx_d0.map_into(),
226 rx_d1.map_into(),
227 tx_d0.map_into(),
228 tx_d1.map_into(),
229 tx_en.map_into(),
230 ];
231
232 let mut this = Self {
233 _peri: peri,
234 pins,
235 _phy: phy,
236 clock_range,
237 phy_addr,
238 mac_addr,
239 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
240 rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf),
241 };
242
243 fence(Ordering::SeqCst);
244
245 let mac = ETH.ethernet_mac();
246 let dma = ETH.ethernet_dma();
247
248 mac.maccr().modify(|w| {
249 w.set_re(true);
250 w.set_te(true);
251 });
252 dma.dmaomr().modify(|w| {
253 w.set_ftf(Ftf::FLUSH); // flush transmit fifo (queue)
254 w.set_st(St::STARTED); // start transmitting channel
255 w.set_sr(DmaomrSr::STARTED); // start receiving channel
256 }); 127 });
128 });
257 129
258 this.rx.demand_poll(); 130 #[cfg(any(eth_v1b, eth_v1c))]
259 131 critical_section::with(|_| {
260 // Enable interrupts 132 RCC.apb2enr().modify(|w| w.set_syscfgen(true));
261 dma.dmaier().modify(|w| { 133 RCC.ahb1enr().modify(|w| {
262 w.set_nise(true); 134 w.set_ethen(true);
263 w.set_rie(true); 135 w.set_ethtxen(true);
264 w.set_tie(true); 136 w.set_ethrxen(true);
265 }); 137 });
266 138
267 P::phy_reset(&mut this); 139 // RMII (Reduced Media Independent Interface)
268 P::phy_init(&mut this); 140 SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true));
141 });
269 142
270 interrupt::ETH.unpend(); 143 #[cfg(eth_v1a)]
271 interrupt::ETH.enable(); 144 {
272 145 config_in_pins!(ref_clk, rx_d0, rx_d1);
273 this 146 config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en);
274 } 147 }
148
149 #[cfg(any(eth_v1b, eth_v1c))]
150 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
151
152 let dma = ETH.ethernet_dma();
153 let mac = ETH.ethernet_mac();
154
155 // Reset and wait
156 dma.dmabmr().modify(|w| w.set_sr(true));
157 while dma.dmabmr().read().sr() {}
158
159 mac.maccr().modify(|w| {
160 w.set_ifg(Ifg::IFG96); // inter frame gap 96 bit times
161 w.set_apcs(Apcs::STRIP); // automatic padding and crc stripping
162 w.set_fes(Fes::FES100); // fast ethernet speed
163 w.set_dm(Dm::FULLDUPLEX); // full duplex
164 // TODO: Carrier sense ? ECRSFD
165 });
166
167 // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core,
168 // so the LR write must happen after the HR write.
169 mac.maca0hr()
170 .modify(|w| w.set_maca0h(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8)));
171 mac.maca0lr().write(|w| {
172 w.set_maca0l(
173 u32::from(mac_addr[0])
174 | (u32::from(mac_addr[1]) << 8)
175 | (u32::from(mac_addr[2]) << 16)
176 | (u32::from(mac_addr[3]) << 24),
177 )
178 });
179
180 // pause time
181 mac.macfcr().modify(|w| w.set_pt(0x100));
182
183 // Transfer and Forward, Receive and Forward
184 dma.dmaomr().modify(|w| {
185 w.set_tsf(Tsf::STOREFORWARD);
186 w.set_rsf(Rsf::STOREFORWARD);
187 });
188
189 dma.dmabmr().modify(|w| {
190 w.set_pbl(Pbl::PBL32) // programmable burst length - 32 ?
191 });
192
193 // TODO MTU size setting not found for v1 ethernet, check if correct
194
195 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
196 let hclk = unsafe { crate::rcc::get_freqs() }.ahb1;
197 let hclk_mhz = hclk.0 / 1_000_000;
198
199 // Set the MDC clock frequency in the range 1MHz - 2.5MHz
200 let clock_range = match hclk_mhz {
201 0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."),
202 25..=34 => Cr::CR_20_35, // Divide by 16
203 35..=59 => Cr::CR_35_60, // Divide by 26
204 60..=99 => Cr::CR_60_100, // Divide by 42
205 100..=149 => Cr::CR_100_150, // Divide by 62
206 150..=216 => Cr::CR_150_168, // Divide by 102
207 _ => {
208 panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider")
209 }
210 };
211
212 let pins = [
213 ref_clk.map_into(),
214 mdio.map_into(),
215 mdc.map_into(),
216 crs.map_into(),
217 rx_d0.map_into(),
218 rx_d1.map_into(),
219 tx_d0.map_into(),
220 tx_d1.map_into(),
221 tx_en.map_into(),
222 ];
223
224 let mut this = Self {
225 _peri: peri,
226 pins,
227 _phy: phy,
228 clock_range,
229 phy_addr,
230 mac_addr,
231 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
232 rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf),
233 };
234
235 fence(Ordering::SeqCst);
236
237 let mac = ETH.ethernet_mac();
238 let dma = ETH.ethernet_dma();
239
240 mac.maccr().modify(|w| {
241 w.set_re(true);
242 w.set_te(true);
243 });
244 dma.dmaomr().modify(|w| {
245 w.set_ftf(Ftf::FLUSH); // flush transmit fifo (queue)
246 w.set_st(St::STARTED); // start transmitting channel
247 w.set_sr(DmaomrSr::STARTED); // start receiving channel
248 });
249
250 this.rx.demand_poll();
251
252 // Enable interrupts
253 dma.dmaier().modify(|w| {
254 w.set_nise(true);
255 w.set_rie(true);
256 w.set_tie(true);
257 });
258
259 P::phy_reset(&mut this);
260 P::phy_init(&mut this);
261
262 interrupt::ETH.unpend();
263 unsafe { interrupt::ETH.enable() };
264
265 this
275 } 266 }
276} 267}
277 268
278unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { 269unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> {
279 fn smi_read(&mut self, reg: u8) -> u16 { 270 fn smi_read(&mut self, reg: u8) -> u16 {
280 // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` 271 let mac = ETH.ethernet_mac();
281 unsafe { 272
282 let mac = ETH.ethernet_mac(); 273 mac.macmiiar().modify(|w| {
283 274 w.set_pa(self.phy_addr);
284 mac.macmiiar().modify(|w| { 275 w.set_mr(reg);
285 w.set_pa(self.phy_addr); 276 w.set_mw(Mw::READ); // read operation
286 w.set_mr(reg); 277 w.set_cr(self.clock_range);
287 w.set_mw(Mw::READ); // read operation 278 w.set_mb(MbProgress::BUSY); // indicate that operation is in progress
288 w.set_cr(self.clock_range); 279 });
289 w.set_mb(MbProgress::BUSY); // indicate that operation is in progress 280 while mac.macmiiar().read().mb() == MbProgress::BUSY {}
290 }); 281 mac.macmiidr().read().md()
291 while mac.macmiiar().read().mb() == MbProgress::BUSY {}
292 mac.macmiidr().read().md()
293 }
294 } 282 }
295 283
296 fn smi_write(&mut self, reg: u8, val: u16) { 284 fn smi_write(&mut self, reg: u8, val: u16) {
297 // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` 285 let mac = ETH.ethernet_mac();
298 unsafe { 286
299 let mac = ETH.ethernet_mac(); 287 mac.macmiidr().write(|w| w.set_md(val));
300 288 mac.macmiiar().modify(|w| {
301 mac.macmiidr().write(|w| w.set_md(val)); 289 w.set_pa(self.phy_addr);
302 mac.macmiiar().modify(|w| { 290 w.set_mr(reg);
303 w.set_pa(self.phy_addr); 291 w.set_mw(Mw::WRITE); // write
304 w.set_mr(reg); 292 w.set_cr(self.clock_range);
305 w.set_mw(Mw::WRITE); // write 293 w.set_mb(MbProgress::BUSY);
306 w.set_cr(self.clock_range); 294 });
307 w.set_mb(MbProgress::BUSY); 295 while mac.macmiiar().read().mb() == MbProgress::BUSY {}
308 });
309 while mac.macmiiar().read().mb() == MbProgress::BUSY {}
310 }
311 } 296 }
312} 297}
313 298
314impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { 299impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> {
315 fn drop(&mut self) { 300 fn drop(&mut self) {
316 // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers 301 let dma = ETH.ethernet_dma();
317 unsafe { 302 let mac = ETH.ethernet_mac();
318 let dma = ETH.ethernet_dma();
319 let mac = ETH.ethernet_mac();
320
321 // Disable the TX DMA and wait for any previous transmissions to be completed
322 dma.dmaomr().modify(|w| w.set_st(St::STOPPED));
323
324 // Disable MAC transmitter and receiver
325 mac.maccr().modify(|w| {
326 w.set_re(false);
327 w.set_te(false);
328 });
329 303
330 dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED)); 304 // Disable the TX DMA and wait for any previous transmissions to be completed
331 } 305 dma.dmaomr().modify(|w| w.set_st(St::STOPPED));
306
307 // Disable MAC transmitter and receiver
308 mac.maccr().modify(|w| {
309 w.set_re(false);
310 w.set_te(false);
311 });
332 312
333 // NOTE(unsafe) Exclusive access to the regs 313 dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED));
334 critical_section::with(|_| unsafe { 314
315 critical_section::with(|_| {
335 for pin in self.pins.iter_mut() { 316 for pin in self.pins.iter_mut() {
336 pin.set_as_disconnected(); 317 pin.set_as_disconnected();
337 } 318 }
diff --git a/embassy-stm32/src/eth/v1/rx_desc.rs b/embassy-stm32/src/eth/v1/rx_desc.rs
index 8b8566d92..01a073bb9 100644
--- a/embassy-stm32/src/eth/v1/rx_desc.rs
+++ b/embassy-stm32/src/eth/v1/rx_desc.rs
@@ -146,12 +146,9 @@ impl<'a> RDesRing<'a> {
146 } 146 }
147 147
148 // Register rx descriptor start 148 // Register rx descriptor start
149 // NOTE (unsafe) Used for atomic writes 149 ETH.ethernet_dma()
150 unsafe { 150 .dmardlar()
151 ETH.ethernet_dma() 151 .write(|w| w.0 = descriptors.as_ptr() as u32);
152 .dmardlar()
153 .write(|w| w.0 = descriptors.as_ptr() as u32);
154 };
155 // We already have fences in `set_owned`, which is called in `setup` 152 // We already have fences in `set_owned`, which is called in `setup`
156 153
157 Self { 154 Self {
@@ -162,12 +159,12 @@ impl<'a> RDesRing<'a> {
162 } 159 }
163 160
164 pub(crate) fn demand_poll(&self) { 161 pub(crate) fn demand_poll(&self) {
165 unsafe { ETH.ethernet_dma().dmarpdr().write(|w| w.set_rpd(Rpd::POLL)) }; 162 ETH.ethernet_dma().dmarpdr().write(|w| w.set_rpd(Rpd::POLL));
166 } 163 }
167 164
168 /// Get current `RunningState` 165 /// Get current `RunningState`
169 fn running_state(&self) -> RunningState { 166 fn running_state(&self) -> RunningState {
170 match unsafe { ETH.ethernet_dma().dmasr().read().rps() } { 167 match ETH.ethernet_dma().dmasr().read().rps() {
171 // Reset or Stop Receive Command issued 168 // Reset or Stop Receive Command issued
172 Rps::STOPPED => RunningState::Stopped, 169 Rps::STOPPED => RunningState::Stopped,
173 // Fetching receive transfer descriptor 170 // Fetching receive transfer descriptor
diff --git a/embassy-stm32/src/eth/v1/tx_desc.rs b/embassy-stm32/src/eth/v1/tx_desc.rs
index 0e63c5443..1317d20f4 100644
--- a/embassy-stm32/src/eth/v1/tx_desc.rs
+++ b/embassy-stm32/src/eth/v1/tx_desc.rs
@@ -120,12 +120,9 @@ impl<'a> TDesRing<'a> {
120 } 120 }
121 121
122 // Register txdescriptor start 122 // Register txdescriptor start
123 // NOTE (unsafe) Used for atomic writes 123 ETH.ethernet_dma()
124 unsafe { 124 .dmatdlar()
125 ETH.ethernet_dma() 125 .write(|w| w.0 = descriptors.as_ptr() as u32);
126 .dmatdlar()
127 .write(|w| w.0 = descriptors.as_ptr() as u32);
128 }
129 126
130 Self { 127 Self {
131 descriptors, 128 descriptors,
@@ -169,6 +166,6 @@ impl<'a> TDesRing<'a> {
169 self.index = 0 166 self.index = 0
170 } 167 }
171 // Request the DMA engine to poll the latest tx descriptor 168 // Request the DMA engine to poll the latest tx descriptor
172 unsafe { ETH.ethernet_dma().dmatpdr().modify(|w| w.0 = 1) } 169 ETH.ethernet_dma().dmatpdr().modify(|w| w.0 = 1)
173 } 170 }
174} 171}
diff --git a/embassy-stm32/src/eth/v2/descriptors.rs b/embassy-stm32/src/eth/v2/descriptors.rs
index 2426596fb..e9799adf1 100644
--- a/embassy-stm32/src/eth/v2/descriptors.rs
+++ b/embassy-stm32/src/eth/v2/descriptors.rs
@@ -73,14 +73,10 @@ impl<'a> TDesRing<'a> {
73 73
74 // Initialize the pointers in the DMA engine. (There will be a memory barrier later 74 // Initialize the pointers in the DMA engine. (There will be a memory barrier later
75 // before the DMA engine is enabled.) 75 // before the DMA engine is enabled.)
76 // NOTE (unsafe) Used for atomic writes 76 let dma = ETH.ethernet_dma();
77 unsafe { 77 dma.dmactx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32);
78 let dma = ETH.ethernet_dma(); 78 dma.dmactx_rlr().write(|w| w.set_tdrl((descriptors.len() as u16) - 1));
79 79 dma.dmactx_dtpr().write(|w| w.0 = 0);
80 dma.dmactx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32);
81 dma.dmactx_rlr().write(|w| w.set_tdrl((descriptors.len() as u16) - 1));
82 dma.dmactx_dtpr().write(|w| w.0 = 0);
83 }
84 80
85 Self { 81 Self {
86 descriptors, 82 descriptors,
@@ -129,8 +125,7 @@ impl<'a> TDesRing<'a> {
129 } 125 }
130 126
131 // signal DMA it can try again. 127 // signal DMA it can try again.
132 // NOTE(unsafe) Atomic write 128 ETH.ethernet_dma().dmactx_dtpr().write(|w| w.0 = 0)
133 unsafe { ETH.ethernet_dma().dmactx_dtpr().write(|w| w.0 = 0) }
134 } 129 }
135} 130}
136 131
@@ -199,13 +194,10 @@ impl<'a> RDesRing<'a> {
199 desc.set_ready(buffers[i].0.as_mut_ptr()); 194 desc.set_ready(buffers[i].0.as_mut_ptr());
200 } 195 }
201 196
202 unsafe { 197 let dma = ETH.ethernet_dma();
203 let dma = ETH.ethernet_dma(); 198 dma.dmacrx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32);
204 199 dma.dmacrx_rlr().write(|w| w.set_rdrl((descriptors.len() as u16) - 1));
205 dma.dmacrx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); 200 dma.dmacrx_dtpr().write(|w| w.0 = 0);
206 dma.dmacrx_rlr().write(|w| w.set_rdrl((descriptors.len() as u16) - 1));
207 dma.dmacrx_dtpr().write(|w| w.0 = 0);
208 }
209 201
210 Self { 202 Self {
211 descriptors, 203 descriptors,
@@ -254,8 +246,7 @@ impl<'a> RDesRing<'a> {
254 fence(Ordering::Release); 246 fence(Ordering::Release);
255 247
256 // signal DMA it can try again. 248 // signal DMA it can try again.
257 // NOTE(unsafe) Atomic write 249 ETH.ethernet_dma().dmacrx_dtpr().write(|w| w.0 = 0);
258 unsafe { ETH.ethernet_dma().dmacrx_dtpr().write(|w| w.0 = 0) }
259 250
260 // Increment index. 251 // Increment index.
261 self.index += 1; 252 self.index += 1;
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 3e45eafd5..600e1d3bc 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -20,18 +20,16 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl
20 WAKER.wake(); 20 WAKER.wake();
21 21
22 // TODO: Check and clear more flags 22 // TODO: Check and clear more flags
23 unsafe { 23 let dma = ETH.ethernet_dma();
24 let dma = ETH.ethernet_dma(); 24
25 25 dma.dmacsr().modify(|w| {
26 dma.dmacsr().modify(|w| { 26 w.set_ti(true);
27 w.set_ti(true); 27 w.set_ri(true);
28 w.set_ri(true); 28 w.set_nis(true);
29 w.set_nis(true); 29 });
30 }); 30 // Delay two peripheral's clock
31 // Delay two peripheral's clock 31 dma.dmacsr().read();
32 dma.dmacsr().read(); 32 dma.dmacsr().read();
33 dma.dmacsr().read();
34 }
35 } 33 }
36} 34}
37 35
@@ -50,7 +48,6 @@ pub struct Ethernet<'d, T: Instance, P: PHY> {
50 48
51macro_rules! config_pins { 49macro_rules! config_pins {
52 ($($pin:ident),*) => { 50 ($($pin:ident),*) => {
53 // NOTE(unsafe) Exclusive access to the registers
54 critical_section::with(|_| { 51 critical_section::with(|_| {
55 $( 52 $(
56 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); 53 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
@@ -80,239 +77,225 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
80 ) -> Self { 77 ) -> Self {
81 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 78 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
82 79
83 unsafe { 80 // Enable the necessary Clocks
84 // Enable the necessary Clocks 81 #[cfg(not(rcc_h5))]
85 // NOTE(unsafe) We have exclusive access to the registers 82 critical_section::with(|_| {
86 #[cfg(not(rcc_h5))] 83 crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true));
87 critical_section::with(|_| { 84 crate::pac::RCC.ahb1enr().modify(|w| {
88 crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true)); 85 w.set_eth1macen(true);
89 crate::pac::RCC.ahb1enr().modify(|w| { 86 w.set_eth1txen(true);
90 w.set_eth1macen(true); 87 w.set_eth1rxen(true);
91 w.set_eth1txen(true);
92 w.set_eth1rxen(true);
93 });
94
95 // RMII
96 crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100));
97 });
98
99 #[cfg(rcc_h5)]
100 critical_section::with(|_| {
101 crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true));
102
103 crate::pac::RCC.ahb1enr().modify(|w| {
104 w.set_ethen(true);
105 w.set_ethtxen(true);
106 w.set_ethrxen(true);
107 });
108
109 // RMII
110 crate::pac::SBS
111 .pmcr()
112 .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4));
113 });
114
115 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
116
117 // NOTE(unsafe) We have exclusive access to the registers
118 let dma = ETH.ethernet_dma();
119 let mac = ETH.ethernet_mac();
120 let mtl = ETH.ethernet_mtl();
121
122 // Reset and wait
123 dma.dmamr().modify(|w| w.set_swr(true));
124 while dma.dmamr().read().swr() {}
125
126 mac.maccr().modify(|w| {
127 w.set_ipg(0b000); // 96 bit times
128 w.set_acs(true);
129 w.set_fes(true);
130 w.set_dm(true);
131 // TODO: Carrier sense ? ECRSFD
132 });
133
134 // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core,
135 // so the LR write must happen after the HR write.
136 mac.maca0hr()
137 .modify(|w| w.set_addrhi(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8)));
138 mac.maca0lr().write(|w| {
139 w.set_addrlo(
140 u32::from(mac_addr[0])
141 | (u32::from(mac_addr[1]) << 8)
142 | (u32::from(mac_addr[2]) << 16)
143 | (u32::from(mac_addr[3]) << 24),
144 )
145 });
146
147 mac.macqtx_fcr().modify(|w| w.set_pt(0x100));
148
149 // disable all MMC RX interrupts
150 mac.mmc_rx_interrupt_mask().write(|w| {
151 w.set_rxcrcerpim(true);
152 w.set_rxalgnerpim(true);
153 w.set_rxucgpim(true);
154 w.set_rxlpiuscim(true);
155 w.set_rxlpitrcim(true)
156 });
157
158 // disable all MMC TX interrupts
159 mac.mmc_tx_interrupt_mask().write(|w| {
160 w.set_txscolgpim(true);
161 w.set_txmcolgpim(true);
162 w.set_txgpktim(true);
163 w.set_txlpiuscim(true);
164 w.set_txlpitrcim(true);
165 });
166
167 mtl.mtlrx_qomr().modify(|w| w.set_rsf(true));
168 mtl.mtltx_qomr().modify(|w| w.set_tsf(true));
169
170 dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ?
171 dma.dmacrx_cr().modify(|w| {
172 w.set_rxpbl(1); // 32 ?
173 w.set_rbsz(MTU as u16);
174 }); 88 });
175 89
176 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called 90 // RMII
177 let hclk = crate::rcc::get_freqs().ahb1; 91 crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100));
178 let hclk_mhz = hclk.0 / 1_000_000; 92 });
179
180 // Set the MDC clock frequency in the range 1MHz - 2.5MHz
181 let clock_range = match hclk_mhz {
182 0..=34 => 2, // Divide by 16
183 35..=59 => 3, // Divide by 26
184 60..=99 => 0, // Divide by 42
185 100..=149 => 1, // Divide by 62
186 150..=249 => 4, // Divide by 102
187 250..=310 => 5, // Divide by 124
188 _ => {
189 panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider")
190 }
191 };
192
193 let pins = [
194 ref_clk.map_into(),
195 mdio.map_into(),
196 mdc.map_into(),
197 crs.map_into(),
198 rx_d0.map_into(),
199 rx_d1.map_into(),
200 tx_d0.map_into(),
201 tx_d1.map_into(),
202 tx_en.map_into(),
203 ];
204
205 let mut this = Self {
206 _peri: peri,
207 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
208 rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf),
209 pins,
210 _phy: phy,
211 clock_range,
212 phy_addr,
213 mac_addr,
214 };
215
216 fence(Ordering::SeqCst);
217
218 let mac = ETH.ethernet_mac();
219 let mtl = ETH.ethernet_mtl();
220 let dma = ETH.ethernet_dma();
221
222 mac.maccr().modify(|w| {
223 w.set_re(true);
224 w.set_te(true);
225 });
226 mtl.mtltx_qomr().modify(|w| w.set_ftq(true));
227 93
228 dma.dmactx_cr().modify(|w| w.set_st(true)); 94 #[cfg(rcc_h5)]
229 dma.dmacrx_cr().modify(|w| w.set_sr(true)); 95 critical_section::with(|_| {
96 crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true));
230 97
231 // Enable interrupts 98 crate::pac::RCC.ahb1enr().modify(|w| {
232 dma.dmacier().modify(|w| { 99 w.set_ethen(true);
233 w.set_nie(true); 100 w.set_ethtxen(true);
234 w.set_rie(true); 101 w.set_ethrxen(true);
235 w.set_tie(true);
236 }); 102 });
237 103
238 P::phy_reset(&mut this); 104 // RMII
239 P::phy_init(&mut this); 105 crate::pac::SBS
240 106 .pmcr()
241 interrupt::ETH.unpend(); 107 .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4));
242 interrupt::ETH.enable(); 108 });
243 109
244 this 110 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
245 } 111
112 let dma = ETH.ethernet_dma();
113 let mac = ETH.ethernet_mac();
114 let mtl = ETH.ethernet_mtl();
115
116 // Reset and wait
117 dma.dmamr().modify(|w| w.set_swr(true));
118 while dma.dmamr().read().swr() {}
119
120 mac.maccr().modify(|w| {
121 w.set_ipg(0b000); // 96 bit times
122 w.set_acs(true);
123 w.set_fes(true);
124 w.set_dm(true);
125 // TODO: Carrier sense ? ECRSFD
126 });
127
128 // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core,
129 // so the LR write must happen after the HR write.
130 mac.maca0hr()
131 .modify(|w| w.set_addrhi(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8)));
132 mac.maca0lr().write(|w| {
133 w.set_addrlo(
134 u32::from(mac_addr[0])
135 | (u32::from(mac_addr[1]) << 8)
136 | (u32::from(mac_addr[2]) << 16)
137 | (u32::from(mac_addr[3]) << 24),
138 )
139 });
140
141 mac.macqtx_fcr().modify(|w| w.set_pt(0x100));
142
143 // disable all MMC RX interrupts
144 mac.mmc_rx_interrupt_mask().write(|w| {
145 w.set_rxcrcerpim(true);
146 w.set_rxalgnerpim(true);
147 w.set_rxucgpim(true);
148 w.set_rxlpiuscim(true);
149 w.set_rxlpitrcim(true)
150 });
151
152 // disable all MMC TX interrupts
153 mac.mmc_tx_interrupt_mask().write(|w| {
154 w.set_txscolgpim(true);
155 w.set_txmcolgpim(true);
156 w.set_txgpktim(true);
157 w.set_txlpiuscim(true);
158 w.set_txlpitrcim(true);
159 });
160
161 mtl.mtlrx_qomr().modify(|w| w.set_rsf(true));
162 mtl.mtltx_qomr().modify(|w| w.set_tsf(true));
163
164 dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ?
165 dma.dmacrx_cr().modify(|w| {
166 w.set_rxpbl(1); // 32 ?
167 w.set_rbsz(MTU as u16);
168 });
169
170 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
171 let hclk = unsafe { crate::rcc::get_freqs() }.ahb1;
172 let hclk_mhz = hclk.0 / 1_000_000;
173
174 // Set the MDC clock frequency in the range 1MHz - 2.5MHz
175 let clock_range = match hclk_mhz {
176 0..=34 => 2, // Divide by 16
177 35..=59 => 3, // Divide by 26
178 60..=99 => 0, // Divide by 42
179 100..=149 => 1, // Divide by 62
180 150..=249 => 4, // Divide by 102
181 250..=310 => 5, // Divide by 124
182 _ => {
183 panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider")
184 }
185 };
186
187 let pins = [
188 ref_clk.map_into(),
189 mdio.map_into(),
190 mdc.map_into(),
191 crs.map_into(),
192 rx_d0.map_into(),
193 rx_d1.map_into(),
194 tx_d0.map_into(),
195 tx_d1.map_into(),
196 tx_en.map_into(),
197 ];
198
199 let mut this = Self {
200 _peri: peri,
201 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
202 rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf),
203 pins,
204 _phy: phy,
205 clock_range,
206 phy_addr,
207 mac_addr,
208 };
209
210 fence(Ordering::SeqCst);
211
212 let mac = ETH.ethernet_mac();
213 let mtl = ETH.ethernet_mtl();
214 let dma = ETH.ethernet_dma();
215
216 mac.maccr().modify(|w| {
217 w.set_re(true);
218 w.set_te(true);
219 });
220 mtl.mtltx_qomr().modify(|w| w.set_ftq(true));
221
222 dma.dmactx_cr().modify(|w| w.set_st(true));
223 dma.dmacrx_cr().modify(|w| w.set_sr(true));
224
225 // Enable interrupts
226 dma.dmacier().modify(|w| {
227 w.set_nie(true);
228 w.set_rie(true);
229 w.set_tie(true);
230 });
231
232 P::phy_reset(&mut this);
233 P::phy_init(&mut this);
234
235 interrupt::ETH.unpend();
236 unsafe { interrupt::ETH.enable() };
237
238 this
246 } 239 }
247} 240}
248 241
249unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { 242unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> {
250 fn smi_read(&mut self, reg: u8) -> u16 { 243 fn smi_read(&mut self, reg: u8) -> u16 {
251 // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` 244 let mac = ETH.ethernet_mac();
252 unsafe { 245
253 let mac = ETH.ethernet_mac(); 246 mac.macmdioar().modify(|w| {
254 247 w.set_pa(self.phy_addr);
255 mac.macmdioar().modify(|w| { 248 w.set_rda(reg);
256 w.set_pa(self.phy_addr); 249 w.set_goc(0b11); // read
257 w.set_rda(reg); 250 w.set_cr(self.clock_range);
258 w.set_goc(0b11); // read 251 w.set_mb(true);
259 w.set_cr(self.clock_range); 252 });
260 w.set_mb(true); 253 while mac.macmdioar().read().mb() {}
261 }); 254 mac.macmdiodr().read().md()
262 while mac.macmdioar().read().mb() {}
263 mac.macmdiodr().read().md()
264 }
265 } 255 }
266 256
267 fn smi_write(&mut self, reg: u8, val: u16) { 257 fn smi_write(&mut self, reg: u8, val: u16) {
268 // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` 258 let mac = ETH.ethernet_mac();
269 unsafe { 259
270 let mac = ETH.ethernet_mac(); 260 mac.macmdiodr().write(|w| w.set_md(val));
271 261 mac.macmdioar().modify(|w| {
272 mac.macmdiodr().write(|w| w.set_md(val)); 262 w.set_pa(self.phy_addr);
273 mac.macmdioar().modify(|w| { 263 w.set_rda(reg);
274 w.set_pa(self.phy_addr); 264 w.set_goc(0b01); // write
275 w.set_rda(reg); 265 w.set_cr(self.clock_range);
276 w.set_goc(0b01); // write 266 w.set_mb(true);
277 w.set_cr(self.clock_range); 267 });
278 w.set_mb(true); 268 while mac.macmdioar().read().mb() {}
279 });
280 while mac.macmdioar().read().mb() {}
281 }
282 } 269 }
283} 270}
284 271
285impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { 272impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> {
286 fn drop(&mut self) { 273 fn drop(&mut self) {
287 // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers 274 let dma = ETH.ethernet_dma();
288 unsafe { 275 let mac = ETH.ethernet_mac();
289 let dma = ETH.ethernet_dma(); 276 let mtl = ETH.ethernet_mtl();
290 let mac = ETH.ethernet_mac(); 277
291 let mtl = ETH.ethernet_mtl(); 278 // Disable the TX DMA and wait for any previous transmissions to be completed
292 279 dma.dmactx_cr().modify(|w| w.set_st(false));
293 // Disable the TX DMA and wait for any previous transmissions to be completed 280 while {
294 dma.dmactx_cr().modify(|w| w.set_st(false)); 281 let txqueue = mtl.mtltx_qdr().read();
295 while { 282 txqueue.trcsts() == 0b01 || txqueue.txqsts()
296 let txqueue = mtl.mtltx_qdr().read(); 283 } {}
297 txqueue.trcsts() == 0b01 || txqueue.txqsts() 284
298 } {} 285 // Disable MAC transmitter and receiver
299 286 mac.maccr().modify(|w| {
300 // Disable MAC transmitter and receiver 287 w.set_re(false);
301 mac.maccr().modify(|w| { 288 w.set_te(false);
302 w.set_re(false); 289 });
303 w.set_te(false); 290
304 }); 291 // Wait for previous receiver transfers to be completed and then disable the RX DMA
292 while {
293 let rxqueue = mtl.mtlrx_qdr().read();
294 rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0
295 } {}
296 dma.dmacrx_cr().modify(|w| w.set_sr(false));
305 297
306 // Wait for previous receiver transfers to be completed and then disable the RX DMA 298 critical_section::with(|_| {
307 while {
308 let rxqueue = mtl.mtlrx_qdr().read();
309 rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0
310 } {}
311 dma.dmacrx_cr().modify(|w| w.set_sr(false));
312 }
313
314 // NOTE(unsafe) Exclusive access to the regs
315 critical_section::with(|_| unsafe {
316 for pin in self.pins.iter_mut() { 299 for pin in self.pins.iter_mut() {
317 pin.set_as_disconnected(); 300 pin.set_as_disconnected();
318 } 301 }
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 0631ae473..3ff92c9e6 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -206,7 +206,7 @@ struct ExtiInputFuture<'a> {
206 206
207impl<'a> ExtiInputFuture<'a> { 207impl<'a> ExtiInputFuture<'a> {
208 fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { 208 fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self {
209 critical_section::with(|_| unsafe { 209 critical_section::with(|_| {
210 let pin = pin as usize; 210 let pin = pin as usize;
211 exticr_regs().exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); 211 exticr_regs().exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port));
212 EXTI.rtsr(0).modify(|w| w.set_line(pin, rising)); 212 EXTI.rtsr(0).modify(|w| w.set_line(pin, rising));
@@ -233,7 +233,7 @@ impl<'a> ExtiInputFuture<'a> {
233 233
234impl<'a> Drop for ExtiInputFuture<'a> { 234impl<'a> Drop for ExtiInputFuture<'a> {
235 fn drop(&mut self) { 235 fn drop(&mut self) {
236 critical_section::with(|_| unsafe { 236 critical_section::with(|_| {
237 let pin = self.pin as _; 237 let pin = self.pin as _;
238 cpu_regs().imr(0).modify(|w| w.set_line(pin, false)); 238 cpu_regs().imr(0).modify(|w| w.set_line(pin, false));
239 }); 239 });
@@ -246,7 +246,7 @@ impl<'a> Future for ExtiInputFuture<'a> {
246 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 246 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
247 EXTI_WAKERS[self.pin as usize].register(cx.waker()); 247 EXTI_WAKERS[self.pin as usize].register(cx.waker());
248 248
249 let imr = unsafe { cpu_regs().imr(0).read() }; 249 let imr = cpu_regs().imr(0).read();
250 if !imr.line(self.pin as _) { 250 if !imr.line(self.pin as _) {
251 Poll::Ready(()) 251 Poll::Ready(())
252 } else { 252 } else {
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index 5e1fc696f..242d99278 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -192,7 +192,7 @@ impl FlashSector {
192 192
193#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] 193#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))]
194pub(crate) fn is_default_layout() -> bool { 194pub(crate) fn is_default_layout() -> bool {
195 unsafe { !pac::FLASH.optcr().read().db1m() } 195 !pac::FLASH.optcr().read().db1m()
196} 196}
197 197
198#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] 198#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))]
@@ -336,7 +336,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E
336 ret 336 ret
337} 337}
338 338
339pub(crate) unsafe fn clear_all_err() { 339pub(crate) fn clear_all_err() {
340 pac::FLASH.sr().write(|w| { 340 pac::FLASH.sr().write(|w| {
341 w.set_pgserr(true); 341 w.set_pgserr(true);
342 w.set_pgperr(true); 342 w.set_pgperr(true);
@@ -345,7 +345,7 @@ pub(crate) unsafe fn clear_all_err() {
345 }); 345 });
346} 346}
347 347
348pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { 348pub(crate) async fn wait_ready() -> Result<(), Error> {
349 use core::task::Poll; 349 use core::task::Poll;
350 350
351 use futures::future::poll_fn; 351 use futures::future::poll_fn;
@@ -391,10 +391,10 @@ fn save_data_cache_state() {
391 let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; 391 let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2;
392 if dual_bank { 392 if dual_bank {
393 // Disable data cache during write/erase if there are two banks, see errata 2.2.12 393 // Disable data cache during write/erase if there are two banks, see errata 2.2.12
394 let dcen = unsafe { pac::FLASH.acr().read().dcen() }; 394 let dcen = pac::FLASH.acr().read().dcen();
395 DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed); 395 DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed);
396 if dcen { 396 if dcen {
397 unsafe { pac::FLASH.acr().modify(|w| w.set_dcen(false)) }; 397 pac::FLASH.acr().modify(|w| w.set_dcen(false));
398 } 398 }
399 } 399 }
400} 400}
@@ -405,12 +405,10 @@ fn restore_data_cache_state() {
405 // Restore data cache if it was enabled 405 // Restore data cache if it was enabled
406 let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed); 406 let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed);
407 if dcen { 407 if dcen {
408 unsafe { 408 // Reset data cache before we enable it again
409 // Reset data cache before we enable it again 409 pac::FLASH.acr().modify(|w| w.set_dcrst(true));
410 pac::FLASH.acr().modify(|w| w.set_dcrst(true)); 410 pac::FLASH.acr().modify(|w| w.set_dcrst(false));
411 pac::FLASH.acr().modify(|w| w.set_dcrst(false)); 411 pac::FLASH.acr().modify(|w| w.set_dcen(true))
412 pac::FLASH.acr().modify(|w| w.set_dcen(true))
413 };
414 } 412 }
415 } 413 }
416} 414}
@@ -445,7 +443,7 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) {
445 feature = "stm32f439vi", 443 feature = "stm32f439vi",
446 feature = "stm32f439zi", 444 feature = "stm32f439zi",
447 ))] 445 ))]
448 if second_bank_read && unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { 446 if second_bank_read && pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() {
449 panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11"); 447 panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11");
450 } 448 }
451 449
@@ -479,11 +477,9 @@ fn pa12_is_output_pull_low() -> bool {
479 use pac::gpio::vals; 477 use pac::gpio::vals;
480 use pac::GPIOA; 478 use pac::GPIOA;
481 const PIN: usize = 12; 479 const PIN: usize = 12;
482 unsafe { 480 GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT
483 GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT 481 && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN
484 && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN 482 && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW
485 && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW
486 }
487} 483}
488 484
489#[cfg(test)] 485#[cfg(test)]
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs
index b9129cb51..a4f3b9686 100644
--- a/embassy-stm32/src/fmc.rs
+++ b/embassy-stm32/src/fmc.rs
@@ -16,7 +16,7 @@ unsafe impl<'d, T> stm32_fmc::FmcPeripheral for Fmc<'d, T>
16where 16where
17 T: Instance, 17 T: Instance,
18{ 18{
19 const REGISTERS: *const () = T::REGS.0 as *const _; 19 const REGISTERS: *const () = T::REGS.as_ptr() as *const _;
20 20
21 fn enable(&mut self) { 21 fn enable(&mut self) {
22 <T as crate::rcc::sealed::RccPeripheral>::enable(); 22 <T as crate::rcc::sealed::RccPeripheral>::enable();
@@ -28,9 +28,7 @@ where
28 // fsmc v1, v2 and v3 does not have the fmcen bit 28 // fsmc v1, v2 and v3 does not have the fmcen bit
29 // This is a "not" because it is expected that all future versions have this bit 29 // This is a "not" because it is expected that all future versions have this bit
30 #[cfg(not(any(fmc_v1x3, fmc_v2x1, fsmc_v1x0, fsmc_v1x3, fsmc_v2x3, fsmc_v3x1)))] 30 #[cfg(not(any(fmc_v1x3, fmc_v2x1, fsmc_v1x0, fsmc_v1x3, fsmc_v2x3, fsmc_v3x1)))]
31 unsafe { 31 T::REGS.bcr1().modify(|r| r.set_fmcen(true));
32 T::REGS.bcr1().modify(|r| r.set_fmcen(true))
33 };
34 } 32 }
35 33
36 fn source_clock_hz(&self) -> u32 { 34 fn source_clock_hz(&self) -> u32 {
@@ -67,7 +65,7 @@ macro_rules! fmc_sdram_constructor {
67 chip: CHIP 65 chip: CHIP
68 ) -> stm32_fmc::Sdram<Fmc<'d, T>, CHIP> { 66 ) -> stm32_fmc::Sdram<Fmc<'d, T>, CHIP> {
69 67
70 critical_section::with(|_| unsafe { 68 critical_section::with(|_| {
71 config_pins!( 69 config_pins!(
72 $($addr_pin_name),*, 70 $($addr_pin_name),*,
73 $($ba_pin_name),*, 71 $($ba_pin_name),*,
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 7a066a4ca..af3a8eaca 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -46,7 +46,7 @@ impl<'d, T: Pin> Flex<'d, T> {
46 /// Put the pin into input mode. 46 /// Put the pin into input mode.
47 #[inline] 47 #[inline]
48 pub fn set_as_input(&mut self, pull: Pull) { 48 pub fn set_as_input(&mut self, pull: Pull) {
49 critical_section::with(|_| unsafe { 49 critical_section::with(|_| {
50 let r = self.pin.block(); 50 let r = self.pin.block();
51 let n = self.pin.pin() as usize; 51 let n = self.pin.pin() as usize;
52 #[cfg(gpio_v1)] 52 #[cfg(gpio_v1)]
@@ -84,7 +84,7 @@ impl<'d, T: Pin> Flex<'d, T> {
84 /// at a specific level, call `set_high`/`set_low` on the pin first. 84 /// at a specific level, call `set_high`/`set_low` on the pin first.
85 #[inline] 85 #[inline]
86 pub fn set_as_output(&mut self, speed: Speed) { 86 pub fn set_as_output(&mut self, speed: Speed) {
87 critical_section::with(|_| unsafe { 87 critical_section::with(|_| {
88 let r = self.pin.block(); 88 let r = self.pin.block();
89 let n = self.pin.pin() as usize; 89 let n = self.pin.pin() as usize;
90 #[cfg(gpio_v1)] 90 #[cfg(gpio_v1)]
@@ -116,7 +116,7 @@ impl<'d, T: Pin> Flex<'d, T> {
116 /// at a specific level, call `set_high`/`set_low` on the pin first. 116 /// at a specific level, call `set_high`/`set_low` on the pin first.
117 #[inline] 117 #[inline]
118 pub fn set_as_input_output(&mut self, speed: Speed, pull: Pull) { 118 pub fn set_as_input_output(&mut self, speed: Speed, pull: Pull) {
119 critical_section::with(|_| unsafe { 119 critical_section::with(|_| {
120 let r = self.pin.block(); 120 let r = self.pin.block();
121 let n = self.pin.pin() as usize; 121 let n = self.pin.pin() as usize;
122 #[cfg(gpio_v1)] 122 #[cfg(gpio_v1)]
@@ -147,7 +147,7 @@ impl<'d, T: Pin> Flex<'d, T> {
147 147
148 #[inline] 148 #[inline]
149 pub fn is_low(&self) -> bool { 149 pub fn is_low(&self) -> bool {
150 let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) }; 150 let state = self.pin.block().idr().read().idr(self.pin.pin() as _);
151 state == vals::Idr::LOW 151 state == vals::Idr::LOW
152 } 152 }
153 153
@@ -164,7 +164,7 @@ impl<'d, T: Pin> Flex<'d, T> {
164 /// Is the output pin set as low? 164 /// Is the output pin set as low?
165 #[inline] 165 #[inline]
166 pub fn is_set_low(&self) -> bool { 166 pub fn is_set_low(&self) -> bool {
167 let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) }; 167 let state = self.pin.block().odr().read().odr(self.pin.pin() as _);
168 state == vals::Odr::LOW 168 state == vals::Odr::LOW
169 } 169 }
170 170
@@ -207,7 +207,7 @@ impl<'d, T: Pin> Flex<'d, T> {
207impl<'d, T: Pin> Drop for Flex<'d, T> { 207impl<'d, T: Pin> Drop for Flex<'d, T> {
208 #[inline] 208 #[inline]
209 fn drop(&mut self) { 209 fn drop(&mut self) {
210 critical_section::with(|_| unsafe { 210 critical_section::with(|_| {
211 let r = self.pin.block(); 211 let r = self.pin.block();
212 let n = self.pin.pin() as usize; 212 let n = self.pin.pin() as usize;
213 #[cfg(gpio_v1)] 213 #[cfg(gpio_v1)]
@@ -534,29 +534,25 @@ pub(crate) mod sealed {
534 /// Set the output as high. 534 /// Set the output as high.
535 #[inline] 535 #[inline]
536 fn set_high(&self) { 536 fn set_high(&self) {
537 unsafe { 537 let n = self._pin() as _;
538 let n = self._pin() as _; 538 self.block().bsrr().write(|w| w.set_bs(n, true));
539 self.block().bsrr().write(|w| w.set_bs(n, true));
540 }
541 } 539 }
542 540
543 /// Set the output as low. 541 /// Set the output as low.
544 #[inline] 542 #[inline]
545 fn set_low(&self) { 543 fn set_low(&self) {
546 unsafe { 544 let n = self._pin() as _;
547 let n = self._pin() as _; 545 self.block().bsrr().write(|w| w.set_br(n, true));
548 self.block().bsrr().write(|w| w.set_br(n, true));
549 }
550 } 546 }
551 547
552 #[inline] 548 #[inline]
553 unsafe fn set_as_af(&self, af_num: u8, af_type: AFType) { 549 fn set_as_af(&self, af_num: u8, af_type: AFType) {
554 self.set_as_af_pull(af_num, af_type, Pull::None); 550 self.set_as_af_pull(af_num, af_type, Pull::None);
555 } 551 }
556 552
557 #[cfg(gpio_v1)] 553 #[cfg(gpio_v1)]
558 #[inline] 554 #[inline]
559 unsafe fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { 555 fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) {
560 // F1 uses the AFIO register for remapping. 556 // F1 uses the AFIO register for remapping.
561 // For now, this is not implemented, so af_num is ignored 557 // For now, this is not implemented, so af_num is ignored
562 // _af_num should be zero here, since it is not set by stm32-data 558 // _af_num should be zero here, since it is not set by stm32-data
@@ -599,7 +595,7 @@ pub(crate) mod sealed {
599 595
600 #[cfg(gpio_v2)] 596 #[cfg(gpio_v2)]
601 #[inline] 597 #[inline]
602 unsafe fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { 598 fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) {
603 let pin = self._pin() as usize; 599 let pin = self._pin() as usize;
604 let block = self.block(); 600 let block = self.block();
605 block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); 601 block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num));
@@ -614,7 +610,7 @@ pub(crate) mod sealed {
614 } 610 }
615 611
616 #[inline] 612 #[inline]
617 unsafe fn set_as_analog(&self) { 613 fn set_as_analog(&self) {
618 let pin = self._pin() as usize; 614 let pin = self._pin() as usize;
619 let block = self.block(); 615 let block = self.block();
620 #[cfg(gpio_v1)] 616 #[cfg(gpio_v1)]
@@ -635,12 +631,12 @@ pub(crate) mod sealed {
635 /// This is currently the same as set_as_analog but is semantically different really. 631 /// This is currently the same as set_as_analog but is semantically different really.
636 /// Drivers should set_as_disconnected pins when dropped. 632 /// Drivers should set_as_disconnected pins when dropped.
637 #[inline] 633 #[inline]
638 unsafe fn set_as_disconnected(&self) { 634 fn set_as_disconnected(&self) {
639 self.set_as_analog(); 635 self.set_as_analog();
640 } 636 }
641 637
642 #[inline] 638 #[inline]
643 unsafe fn set_speed(&self, speed: Speed) { 639 fn set_speed(&self, speed: Speed) {
644 let pin = self._pin() as usize; 640 let pin = self._pin() as usize;
645 641
646 #[cfg(gpio_v1)] 642 #[cfg(gpio_v1)]
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index e04038886..aa485cd86 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -68,53 +68,45 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
68 T::enable(); 68 T::enable();
69 T::reset(); 69 T::reset();
70 70
71 unsafe { 71 scl.set_as_af_pull(
72 scl.set_as_af_pull( 72 scl.af_num(),
73 scl.af_num(), 73 AFType::OutputOpenDrain,
74 AFType::OutputOpenDrain, 74 match config.scl_pullup {
75 match config.scl_pullup { 75 true => Pull::Up,
76 true => Pull::Up, 76 false => Pull::None,
77 false => Pull::None, 77 },
78 }, 78 );
79 ); 79 sda.set_as_af_pull(
80 sda.set_as_af_pull( 80 sda.af_num(),
81 sda.af_num(), 81 AFType::OutputOpenDrain,
82 AFType::OutputOpenDrain, 82 match config.sda_pullup {
83 match config.sda_pullup { 83 true => Pull::Up,
84 true => Pull::Up, 84 false => Pull::None,
85 false => Pull::None, 85 },
86 }, 86 );
87 );
88 }
89 87
90 unsafe { 88 T::regs().cr1().modify(|reg| {
91 T::regs().cr1().modify(|reg| { 89 reg.set_pe(false);
92 reg.set_pe(false); 90 //reg.set_anfoff(false);
93 //reg.set_anfoff(false); 91 });
94 });
95 }
96 92
97 let timings = Timings::new(T::frequency(), freq.into()); 93 let timings = Timings::new(T::frequency(), freq.into());
98 94
99 unsafe { 95 T::regs().cr2().modify(|reg| {
100 T::regs().cr2().modify(|reg| { 96 reg.set_freq(timings.freq);
101 reg.set_freq(timings.freq); 97 });
102 }); 98 T::regs().ccr().modify(|reg| {
103 T::regs().ccr().modify(|reg| { 99 reg.set_f_s(timings.mode.f_s());
104 reg.set_f_s(timings.mode.f_s()); 100 reg.set_duty(timings.duty.duty());
105 reg.set_duty(timings.duty.duty()); 101 reg.set_ccr(timings.ccr);
106 reg.set_ccr(timings.ccr); 102 });
107 }); 103 T::regs().trise().modify(|reg| {
108 T::regs().trise().modify(|reg| { 104 reg.set_trise(timings.trise);
109 reg.set_trise(timings.trise); 105 });
110 });
111 }
112 106
113 unsafe { 107 T::regs().cr1().modify(|reg| {
114 T::regs().cr1().modify(|reg| { 108 reg.set_pe(true);
115 reg.set_pe(true); 109 });
116 });
117 }
118 110
119 Self { 111 Self {
120 phantom: PhantomData, 112 phantom: PhantomData,
@@ -123,7 +115,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
123 } 115 }
124 } 116 }
125 117
126 unsafe fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> { 118 fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> {
127 // Note that flags should only be cleared once they have been registered. If flags are 119 // Note that flags should only be cleared once they have been registered. If flags are
128 // cleared otherwise, there may be an inherent race condition and flags may be missed. 120 // cleared otherwise, there may be an inherent race condition and flags may be missed.
129 let sr1 = T::regs().sr1().read(); 121 let sr1 = T::regs().sr1().read();
@@ -162,7 +154,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
162 Ok(sr1) 154 Ok(sr1)
163 } 155 }
164 156
165 unsafe fn write_bytes( 157 fn write_bytes(
166 &mut self, 158 &mut self,
167 addr: u8, 159 addr: u8,
168 bytes: &[u8], 160 bytes: &[u8],
@@ -211,7 +203,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
211 Ok(()) 203 Ok(())
212 } 204 }
213 205
214 unsafe fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 206 fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
215 // Wait until we're ready for sending 207 // Wait until we're ready for sending
216 while { 208 while {
217 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. 209 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
@@ -234,7 +226,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
234 Ok(()) 226 Ok(())
235 } 227 }
236 228
237 unsafe fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> { 229 fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> {
238 while { 230 while {
239 // Check for any potential error conditions. 231 // Check for any potential error conditions.
240 self.check_and_clear_error_flags()?; 232 self.check_and_clear_error_flags()?;
@@ -256,56 +248,52 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
256 ) -> Result<(), Error> { 248 ) -> Result<(), Error> {
257 if let Some((last, buffer)) = buffer.split_last_mut() { 249 if let Some((last, buffer)) = buffer.split_last_mut() {
258 // Send a START condition and set ACK bit 250 // Send a START condition and set ACK bit
259 unsafe { 251 T::regs().cr1().modify(|reg| {
260 T::regs().cr1().modify(|reg| { 252 reg.set_start(true);
261 reg.set_start(true); 253 reg.set_ack(true);
262 reg.set_ack(true); 254 });
263 });
264 }
265 255
266 // Wait until START condition was generated 256 // Wait until START condition was generated
267 while unsafe { !self.check_and_clear_error_flags()?.start() } { 257 while !self.check_and_clear_error_flags()?.start() {
268 check_timeout()?; 258 check_timeout()?;
269 } 259 }
270 260
271 // Also wait until signalled we're master and everything is waiting for us 261 // Also wait until signalled we're master and everything is waiting for us
272 while { 262 while {
273 let sr2 = unsafe { T::regs().sr2().read() }; 263 let sr2 = T::regs().sr2().read();
274 !sr2.msl() && !sr2.busy() 264 !sr2.msl() && !sr2.busy()
275 } { 265 } {
276 check_timeout()?; 266 check_timeout()?;
277 } 267 }
278 268
279 // Set up current address, we're trying to talk to 269 // Set up current address, we're trying to talk to
280 unsafe { T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)) } 270 T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1));
281 271
282 // Wait until address was sent 272 // Wait until address was sent
283 // Wait for the address to be acknowledged 273 // Wait for the address to be acknowledged
284 while unsafe { !self.check_and_clear_error_flags()?.addr() } { 274 while !self.check_and_clear_error_flags()?.addr() {
285 check_timeout()?; 275 check_timeout()?;
286 } 276 }
287 277
288 // Clear condition by reading SR2 278 // Clear condition by reading SR2
289 let _ = unsafe { T::regs().sr2().read() }; 279 let _ = T::regs().sr2().read();
290 280
291 // Receive bytes into buffer 281 // Receive bytes into buffer
292 for c in buffer { 282 for c in buffer {
293 *c = unsafe { self.recv_byte(&check_timeout)? }; 283 *c = self.recv_byte(&check_timeout)?;
294 } 284 }
295 285
296 // Prepare to send NACK then STOP after next byte 286 // Prepare to send NACK then STOP after next byte
297 unsafe { 287 T::regs().cr1().modify(|reg| {
298 T::regs().cr1().modify(|reg| { 288 reg.set_ack(false);
299 reg.set_ack(false); 289 reg.set_stop(true);
300 reg.set_stop(true); 290 });
301 })
302 }
303 291
304 // Receive last byte 292 // Receive last byte
305 *last = unsafe { self.recv_byte(&check_timeout)? }; 293 *last = self.recv_byte(&check_timeout)?;
306 294
307 // Wait for the STOP to be sent. 295 // Wait for the STOP to be sent.
308 while unsafe { T::regs().cr1().read().stop() } { 296 while T::regs().cr1().read().stop() {
309 check_timeout()?; 297 check_timeout()?;
310 } 298 }
311 299
@@ -326,15 +314,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
326 write: &[u8], 314 write: &[u8],
327 check_timeout: impl Fn() -> Result<(), Error>, 315 check_timeout: impl Fn() -> Result<(), Error>,
328 ) -> Result<(), Error> { 316 ) -> Result<(), Error> {
329 unsafe { 317 self.write_bytes(addr, write, &check_timeout)?;
330 self.write_bytes(addr, write, &check_timeout)?; 318 // Send a STOP condition
331 // Send a STOP condition 319 T::regs().cr1().modify(|reg| reg.set_stop(true));
332 T::regs().cr1().modify(|reg| reg.set_stop(true)); 320 // Wait for STOP condition to transmit.
333 // Wait for STOP condition to transmit. 321 while T::regs().cr1().read().stop() {
334 while T::regs().cr1().read().stop() { 322 check_timeout()?;
335 check_timeout()?; 323 }
336 }
337 };
338 324
339 // Fallthrough is success 325 // Fallthrough is success
340 Ok(()) 326 Ok(())
@@ -351,7 +337,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
351 read: &mut [u8], 337 read: &mut [u8],
352 check_timeout: impl Fn() -> Result<(), Error>, 338 check_timeout: impl Fn() -> Result<(), Error>,
353 ) -> Result<(), Error> { 339 ) -> Result<(), Error> {
354 unsafe { self.write_bytes(addr, write, &check_timeout)? }; 340 self.write_bytes(addr, write, &check_timeout)?;
355 self.blocking_read_timeout(addr, read, &check_timeout)?; 341 self.blocking_read_timeout(addr, read, &check_timeout)?;
356 342
357 Ok(()) 343 Ok(())
@@ -478,8 +464,6 @@ impl Timings {
478 assert!(freq >= 2 && freq <= 50); 464 assert!(freq >= 2 && freq <= 50);
479 465
480 // Configure bus frequency into I2C peripheral 466 // Configure bus frequency into I2C peripheral
481 //self.i2c.cr2.write(|w| unsafe { w.freq().bits(freq as u8) });
482
483 let trise = if speed <= 100_000 { 467 let trise = if speed <= 100_000 {
484 freq + 1 468 freq + 1
485 } else { 469 } else {
@@ -539,18 +523,16 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> {
539 type Config = Hertz; 523 type Config = Hertz;
540 fn set_config(&mut self, config: &Self::Config) { 524 fn set_config(&mut self, config: &Self::Config) {
541 let timings = Timings::new(T::frequency(), *config); 525 let timings = Timings::new(T::frequency(), *config);
542 unsafe { 526 T::regs().cr2().modify(|reg| {
543 T::regs().cr2().modify(|reg| { 527 reg.set_freq(timings.freq);
544 reg.set_freq(timings.freq); 528 });
545 }); 529 T::regs().ccr().modify(|reg| {
546 T::regs().ccr().modify(|reg| { 530 reg.set_f_s(timings.mode.f_s());
547 reg.set_f_s(timings.mode.f_s()); 531 reg.set_duty(timings.duty.duty());
548 reg.set_duty(timings.duty.duty()); 532 reg.set_ccr(timings.ccr);
549 reg.set_ccr(timings.ccr); 533 });
550 }); 534 T::regs().trise().modify(|reg| {
551 T::regs().trise().modify(|reg| { 535 reg.set_trise(timings.trise);
552 reg.set_trise(timings.trise); 536 });
553 });
554 }
555 } 537 }
556} 538}
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 1aaf2b46b..1f036d55c 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -89,49 +89,41 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
89 T::enable(); 89 T::enable();
90 T::reset(); 90 T::reset();
91 91
92 unsafe { 92 scl.set_as_af_pull(
93 scl.set_as_af_pull( 93 scl.af_num(),
94 scl.af_num(), 94 AFType::OutputOpenDrain,
95 AFType::OutputOpenDrain, 95 match config.scl_pullup {
96 match config.scl_pullup { 96 true => Pull::Up,
97 true => Pull::Up, 97 false => Pull::None,
98 false => Pull::None, 98 },
99 }, 99 );
100 ); 100 sda.set_as_af_pull(
101 sda.set_as_af_pull( 101 sda.af_num(),
102 sda.af_num(), 102 AFType::OutputOpenDrain,
103 AFType::OutputOpenDrain, 103 match config.sda_pullup {
104 match config.sda_pullup { 104 true => Pull::Up,
105 true => Pull::Up, 105 false => Pull::None,
106 false => Pull::None, 106 },
107 }, 107 );
108 ); 108
109 } 109 T::regs().cr1().modify(|reg| {
110 110 reg.set_pe(false);
111 unsafe { 111 reg.set_anfoff(false);
112 T::regs().cr1().modify(|reg| { 112 });
113 reg.set_pe(false);
114 reg.set_anfoff(false);
115 });
116 }
117 113
118 let timings = Timings::new(T::frequency(), freq.into()); 114 let timings = Timings::new(T::frequency(), freq.into());
119 115
120 unsafe { 116 T::regs().timingr().write(|reg| {
121 T::regs().timingr().write(|reg| { 117 reg.set_presc(timings.prescale);
122 reg.set_presc(timings.prescale); 118 reg.set_scll(timings.scll);
123 reg.set_scll(timings.scll); 119 reg.set_sclh(timings.sclh);
124 reg.set_sclh(timings.sclh); 120 reg.set_sdadel(timings.sdadel);
125 reg.set_sdadel(timings.sdadel); 121 reg.set_scldel(timings.scldel);
126 reg.set_scldel(timings.scldel); 122 });
127 });
128 }
129 123
130 unsafe { 124 T::regs().cr1().modify(|reg| {
131 T::regs().cr1().modify(|reg| { 125 reg.set_pe(true);
132 reg.set_pe(true); 126 });
133 });
134 }
135 127
136 T::Interrupt::unpend(); 128 T::Interrupt::unpend();
137 unsafe { T::Interrupt::enable() }; 129 unsafe { T::Interrupt::enable() };
@@ -144,12 +136,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
144 } 136 }
145 137
146 fn master_stop(&mut self) { 138 fn master_stop(&mut self) {
147 unsafe { 139 T::regs().cr2().write(|w| w.set_stop(true));
148 T::regs().cr2().write(|w| w.set_stop(true));
149 }
150 } 140 }
151 141
152 unsafe fn master_read( 142 fn master_read(
153 address: u8, 143 address: u8,
154 length: usize, 144 length: usize,
155 stop: Stop, 145 stop: Stop,
@@ -191,7 +181,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
191 Ok(()) 181 Ok(())
192 } 182 }
193 183
194 unsafe fn master_write( 184 fn master_write(
195 address: u8, 185 address: u8,
196 length: usize, 186 length: usize,
197 stop: Stop, 187 stop: Stop,
@@ -229,7 +219,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
229 Ok(()) 219 Ok(())
230 } 220 }
231 221
232 unsafe fn master_continue( 222 fn master_continue(
233 length: usize, 223 length: usize,
234 reload: bool, 224 reload: bool,
235 check_timeout: impl Fn() -> Result<(), Error>, 225 check_timeout: impl Fn() -> Result<(), Error>,
@@ -259,13 +249,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
259 //$i2c.txdr.write(|w| w.txdata().bits(0)); 249 //$i2c.txdr.write(|w| w.txdata().bits(0));
260 //} 250 //}
261 251
262 unsafe { 252 if T::regs().isr().read().txis() {
263 if T::regs().isr().read().txis() { 253 T::regs().txdr().write(|w| w.set_txdata(0));
264 T::regs().txdr().write(|w| w.set_txdata(0)); 254 }
265 } 255 if !T::regs().isr().read().txe() {
266 if !T::regs().isr().read().txe() { 256 T::regs().isr().modify(|w| w.set_txe(true))
267 T::regs().isr().modify(|w| w.set_txe(true))
268 }
269 } 257 }
270 258
271 // If TXDR is not flagged as empty, write 1 to flush it 259 // If TXDR is not flagged as empty, write 1 to flush it
@@ -276,21 +264,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
276 264
277 fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 265 fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
278 loop { 266 loop {
279 unsafe { 267 let isr = T::regs().isr().read();
280 let isr = T::regs().isr().read(); 268 if isr.txe() {
281 if isr.txe() { 269 return Ok(());
282 return Ok(()); 270 } else if isr.berr() {
283 } else if isr.berr() { 271 T::regs().icr().write(|reg| reg.set_berrcf(true));
284 T::regs().icr().write(|reg| reg.set_berrcf(true)); 272 return Err(Error::Bus);
285 return Err(Error::Bus); 273 } else if isr.arlo() {
286 } else if isr.arlo() { 274 T::regs().icr().write(|reg| reg.set_arlocf(true));
287 T::regs().icr().write(|reg| reg.set_arlocf(true)); 275 return Err(Error::Arbitration);
288 return Err(Error::Arbitration); 276 } else if isr.nackf() {
289 } else if isr.nackf() { 277 T::regs().icr().write(|reg| reg.set_nackcf(true));
290 T::regs().icr().write(|reg| reg.set_nackcf(true)); 278 self.flush_txdr();
291 self.flush_txdr(); 279 return Err(Error::Nack);
292 return Err(Error::Nack);
293 }
294 } 280 }
295 281
296 check_timeout()?; 282 check_timeout()?;
@@ -299,21 +285,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
299 285
300 fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 286 fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
301 loop { 287 loop {
302 unsafe { 288 let isr = T::regs().isr().read();
303 let isr = T::regs().isr().read(); 289 if isr.rxne() {
304 if isr.rxne() { 290 return Ok(());
305 return Ok(()); 291 } else if isr.berr() {
306 } else if isr.berr() { 292 T::regs().icr().write(|reg| reg.set_berrcf(true));
307 T::regs().icr().write(|reg| reg.set_berrcf(true)); 293 return Err(Error::Bus);
308 return Err(Error::Bus); 294 } else if isr.arlo() {
309 } else if isr.arlo() { 295 T::regs().icr().write(|reg| reg.set_arlocf(true));
310 T::regs().icr().write(|reg| reg.set_arlocf(true)); 296 return Err(Error::Arbitration);
311 return Err(Error::Arbitration); 297 } else if isr.nackf() {
312 } else if isr.nackf() { 298 T::regs().icr().write(|reg| reg.set_nackcf(true));
313 T::regs().icr().write(|reg| reg.set_nackcf(true)); 299 self.flush_txdr();
314 self.flush_txdr(); 300 return Err(Error::Nack);
315 return Err(Error::Nack);
316 }
317 } 301 }
318 302
319 check_timeout()?; 303 check_timeout()?;
@@ -322,21 +306,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
322 306
323 fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 307 fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
324 loop { 308 loop {
325 unsafe { 309 let isr = T::regs().isr().read();
326 let isr = T::regs().isr().read(); 310 if isr.tc() {
327 if isr.tc() { 311 return Ok(());
328 return Ok(()); 312 } else if isr.berr() {
329 } else if isr.berr() { 313 T::regs().icr().write(|reg| reg.set_berrcf(true));
330 T::regs().icr().write(|reg| reg.set_berrcf(true)); 314 return Err(Error::Bus);
331 return Err(Error::Bus); 315 } else if isr.arlo() {
332 } else if isr.arlo() { 316 T::regs().icr().write(|reg| reg.set_arlocf(true));
333 T::regs().icr().write(|reg| reg.set_arlocf(true)); 317 return Err(Error::Arbitration);
334 return Err(Error::Arbitration); 318 } else if isr.nackf() {
335 } else if isr.nackf() { 319 T::regs().icr().write(|reg| reg.set_nackcf(true));
336 T::regs().icr().write(|reg| reg.set_nackcf(true)); 320 self.flush_txdr();
337 self.flush_txdr(); 321 return Err(Error::Nack);
338 return Err(Error::Nack);
339 }
340 } 322 }
341 323
342 check_timeout()?; 324 check_timeout()?;
@@ -358,32 +340,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
358 }; 340 };
359 let last_chunk_idx = total_chunks.saturating_sub(1); 341 let last_chunk_idx = total_chunks.saturating_sub(1);
360 342
361 unsafe { 343 Self::master_read(
362 Self::master_read( 344 address,
363 address, 345 read.len().min(255),
364 read.len().min(255), 346 Stop::Automatic,
365 Stop::Automatic, 347 last_chunk_idx != 0,
366 last_chunk_idx != 0, 348 restart,
367 restart, 349 &check_timeout,
368 &check_timeout, 350 )?;
369 )?;
370 }
371 351
372 for (number, chunk) in read.chunks_mut(255).enumerate() { 352 for (number, chunk) in read.chunks_mut(255).enumerate() {
373 if number != 0 { 353 if number != 0 {
374 // NOTE(unsafe) We have &mut self 354 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
375 unsafe {
376 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
377 }
378 } 355 }
379 356
380 for byte in chunk { 357 for byte in chunk {
381 // Wait until we have received something 358 // Wait until we have received something
382 self.wait_rxne(&check_timeout)?; 359 self.wait_rxne(&check_timeout)?;
383 360
384 unsafe { 361 *byte = T::regs().rxdr().read().rxdata();
385 *byte = T::regs().rxdr().read().rxdata();
386 }
387 } 362 }
388 } 363 }
389 Ok(()) 364 Ok(())
@@ -407,23 +382,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
407 // I2C start 382 // I2C start
408 // 383 //
409 // ST SAD+W 384 // ST SAD+W
410 // NOTE(unsafe) We have &mut self 385 Self::master_write(
411 unsafe { 386 address,
412 Self::master_write( 387 write.len().min(255),
413 address, 388 Stop::Software,
414 write.len().min(255), 389 last_chunk_idx != 0,
415 Stop::Software, 390 &check_timeout,
416 last_chunk_idx != 0, 391 )?;
417 &check_timeout,
418 )?;
419 }
420 392
421 for (number, chunk) in write.chunks(255).enumerate() { 393 for (number, chunk) in write.chunks(255).enumerate() {
422 if number != 0 { 394 if number != 0 {
423 // NOTE(unsafe) We have &mut self 395 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
424 unsafe {
425 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
426 }
427 } 396 }
428 397
429 for byte in chunk { 398 for byte in chunk {
@@ -432,9 +401,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
432 // through) 401 // through)
433 self.wait_txe(&check_timeout)?; 402 self.wait_txe(&check_timeout)?;
434 403
435 unsafe { 404 T::regs().txdr().write(|w| w.set_txdata(*byte));
436 T::regs().txdr().write(|w| w.set_txdata(*byte));
437 }
438 } 405 }
439 } 406 }
440 // Wait until the write finishes 407 // Wait until the write finishes
@@ -467,7 +434,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
467 w.set_tcie(true); 434 w.set_tcie(true);
468 } 435 }
469 }); 436 });
470 let dst = regs.txdr().ptr() as *mut u8; 437 let dst = regs.txdr().as_ptr() as *mut u8;
471 438
472 let ch = &mut self.tx_dma; 439 let ch = &mut self.tx_dma;
473 let request = ch.request(); 440 let request = ch.request();
@@ -479,37 +446,30 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
479 446
480 let on_drop = OnDrop::new(|| { 447 let on_drop = OnDrop::new(|| {
481 let regs = T::regs(); 448 let regs = T::regs();
482 unsafe { 449 regs.cr1().modify(|w| {
483 regs.cr1().modify(|w| { 450 if last_slice {
484 if last_slice { 451 w.set_txdmaen(false);
485 w.set_txdmaen(false); 452 }
486 } 453 w.set_tcie(false);
487 w.set_tcie(false); 454 })
488 })
489 }
490 }); 455 });
491 456
492 poll_fn(|cx| { 457 poll_fn(|cx| {
493 state.waker.register(cx.waker()); 458 state.waker.register(cx.waker());
494 459
495 let isr = unsafe { T::regs().isr().read() }; 460 let isr = T::regs().isr().read();
496 if remaining_len == total_len { 461 if remaining_len == total_len {
497 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
498 if first_slice { 462 if first_slice {
499 unsafe { 463 Self::master_write(
500 Self::master_write( 464 address,
501 address, 465 total_len.min(255),
502 total_len.min(255), 466 Stop::Software,
503 Stop::Software, 467 (total_len > 255) || !last_slice,
504 (total_len > 255) || !last_slice, 468 &check_timeout,
505 &check_timeout, 469 )?;
506 )?;
507 }
508 } else { 470 } else {
509 unsafe { 471 Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?;
510 Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; 472 T::regs().cr1().modify(|w| w.set_tcie(true));
511 T::regs().cr1().modify(|w| w.set_tcie(true));
512 }
513 } 473 }
514 } else if !(isr.tcr() || isr.tc()) { 474 } else if !(isr.tcr() || isr.tc()) {
515 // poll_fn was woken without an interrupt present 475 // poll_fn was woken without an interrupt present
@@ -519,13 +479,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
519 } else { 479 } else {
520 let last_piece = (remaining_len <= 255) && last_slice; 480 let last_piece = (remaining_len <= 255) && last_slice;
521 481
522 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers 482 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
523 unsafe { 483 return Poll::Ready(Err(e));
524 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
525 return Poll::Ready(Err(e));
526 }
527 T::regs().cr1().modify(|w| w.set_tcie(true));
528 } 484 }
485 T::regs().cr1().modify(|w| w.set_tcie(true));
529 } 486 }
530 487
531 remaining_len = remaining_len.saturating_sub(255); 488 remaining_len = remaining_len.saturating_sub(255);
@@ -564,7 +521,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
564 w.set_rxdmaen(true); 521 w.set_rxdmaen(true);
565 w.set_tcie(true); 522 w.set_tcie(true);
566 }); 523 });
567 let src = regs.rxdr().ptr() as *mut u8; 524 let src = regs.rxdr().as_ptr() as *mut u8;
568 525
569 let ch = &mut self.rx_dma; 526 let ch = &mut self.rx_dma;
570 let request = ch.request(); 527 let request = ch.request();
@@ -576,30 +533,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
576 533
577 let on_drop = OnDrop::new(|| { 534 let on_drop = OnDrop::new(|| {
578 let regs = T::regs(); 535 let regs = T::regs();
579 unsafe { 536 regs.cr1().modify(|w| {
580 regs.cr1().modify(|w| { 537 w.set_rxdmaen(false);
581 w.set_rxdmaen(false); 538 w.set_tcie(false);
582 w.set_tcie(false); 539 })
583 })
584 }
585 }); 540 });
586 541
587 poll_fn(|cx| { 542 poll_fn(|cx| {
588 state.waker.register(cx.waker()); 543 state.waker.register(cx.waker());
589 544
590 let isr = unsafe { T::regs().isr().read() }; 545 let isr = T::regs().isr().read();
591 if remaining_len == total_len { 546 if remaining_len == total_len {
592 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers 547 Self::master_read(
593 unsafe { 548 address,
594 Self::master_read( 549 total_len.min(255),
595 address, 550 Stop::Software,
596 total_len.min(255), 551 total_len > 255,
597 Stop::Software, 552 restart,
598 total_len > 255, 553 &check_timeout,
599 restart, 554 )?;
600 &check_timeout,
601 )?;
602 }
603 } else if !(isr.tcr() || isr.tc()) { 555 } else if !(isr.tcr() || isr.tc()) {
604 // poll_fn was woken without an interrupt present 556 // poll_fn was woken without an interrupt present
605 return Poll::Pending; 557 return Poll::Pending;
@@ -608,13 +560,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
608 } else { 560 } else {
609 let last_piece = remaining_len <= 255; 561 let last_piece = remaining_len <= 255;
610 562
611 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers 563 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
612 unsafe { 564 return Poll::Ready(Err(e));
613 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
614 return Poll::Ready(Err(e));
615 }
616 T::regs().cr1().modify(|w| w.set_tcie(true));
617 } 565 }
566 T::regs().cr1().modify(|w| w.set_tcie(true));
618 } 567 }
619 568
620 remaining_len = remaining_len.saturating_sub(255); 569 remaining_len = remaining_len.saturating_sub(255);
@@ -758,16 +707,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
758 let first_length = write[0].len(); 707 let first_length = write[0].len();
759 let last_slice_index = write.len() - 1; 708 let last_slice_index = write.len() - 1;
760 709
761 // NOTE(unsafe) We have &mut self 710 Self::master_write(
762 unsafe { 711 address,
763 Self::master_write( 712 first_length.min(255),
764 address, 713 Stop::Software,
765 first_length.min(255), 714 (first_length > 255) || (last_slice_index != 0),
766 Stop::Software, 715 &check_timeout,
767 (first_length > 255) || (last_slice_index != 0), 716 )?;
768 &check_timeout,
769 )?;
770 }
771 717
772 for (idx, slice) in write.iter().enumerate() { 718 for (idx, slice) in write.iter().enumerate() {
773 let slice_len = slice.len(); 719 let slice_len = slice.len();
@@ -780,26 +726,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
780 let last_chunk_idx = total_chunks.saturating_sub(1); 726 let last_chunk_idx = total_chunks.saturating_sub(1);
781 727
782 if idx != 0 { 728 if idx != 0 {
783 // NOTE(unsafe) We have &mut self 729 Self::master_continue(
784 unsafe { 730 slice_len.min(255),
785 Self::master_continue( 731 (idx != last_slice_index) || (slice_len > 255),
786 slice_len.min(255), 732 &check_timeout,
787 (idx != last_slice_index) || (slice_len > 255), 733 )?;
788 &check_timeout,
789 )?;
790 }
791 } 734 }
792 735
793 for (number, chunk) in slice.chunks(255).enumerate() { 736 for (number, chunk) in slice.chunks(255).enumerate() {
794 if number != 0 { 737 if number != 0 {
795 // NOTE(unsafe) We have &mut self 738 Self::master_continue(
796 unsafe { 739 chunk.len(),
797 Self::master_continue( 740 (number != last_chunk_idx) || (idx != last_slice_index),
798 chunk.len(), 741 &check_timeout,
799 (number != last_chunk_idx) || (idx != last_slice_index), 742 )?;
800 &check_timeout,
801 )?;
802 }
803 } 743 }
804 744
805 for byte in chunk { 745 for byte in chunk {
@@ -810,9 +750,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
810 750
811 // Put byte on the wire 751 // Put byte on the wire
812 //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); 752 //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
813 unsafe { 753 T::regs().txdr().write(|w| w.set_txdata(*byte));
814 T::regs().txdr().write(|w| w.set_txdata(*byte));
815 }
816 } 754 }
817 } 755 }
818 } 756 }
@@ -1061,14 +999,12 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> {
1061 type Config = Hertz; 999 type Config = Hertz;
1062 fn set_config(&mut self, config: &Self::Config) { 1000 fn set_config(&mut self, config: &Self::Config) {
1063 let timings = Timings::new(T::frequency(), *config); 1001 let timings = Timings::new(T::frequency(), *config);
1064 unsafe { 1002 T::regs().timingr().write(|reg| {
1065 T::regs().timingr().write(|reg| { 1003 reg.set_presc(timings.prescale);
1066 reg.set_presc(timings.prescale); 1004 reg.set_scll(timings.scll);
1067 reg.set_scll(timings.scll); 1005 reg.set_sclh(timings.sclh);
1068 reg.set_sclh(timings.sclh); 1006 reg.set_sdadel(timings.sdadel);
1069 reg.set_sdadel(timings.sdadel); 1007 reg.set_scldel(timings.scldel);
1070 reg.set_scldel(timings.scldel); 1008 });
1071 });
1072 }
1073 } 1009 }
1074} 1010}
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 2bb199f68..62dda69b4 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -153,19 +153,17 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
153 ) -> Self { 153 ) -> Self {
154 into_ref!(sd, ws, ck, mck); 154 into_ref!(sd, ws, ck, mck);
155 155
156 unsafe { 156 sd.set_as_af(sd.af_num(), AFType::OutputPushPull);
157 sd.set_as_af(sd.af_num(), AFType::OutputPushPull); 157 sd.set_speed(crate::gpio::Speed::VeryHigh);
158 sd.set_speed(crate::gpio::Speed::VeryHigh);
159 158
160 ws.set_as_af(ws.af_num(), AFType::OutputPushPull); 159 ws.set_as_af(ws.af_num(), AFType::OutputPushPull);
161 ws.set_speed(crate::gpio::Speed::VeryHigh); 160 ws.set_speed(crate::gpio::Speed::VeryHigh);
162 161
163 ck.set_as_af(ck.af_num(), AFType::OutputPushPull); 162 ck.set_as_af(ck.af_num(), AFType::OutputPushPull);
164 ck.set_speed(crate::gpio::Speed::VeryHigh); 163 ck.set_speed(crate::gpio::Speed::VeryHigh);
165 164
166 mck.set_as_af(mck.af_num(), AFType::OutputPushPull); 165 mck.set_as_af(mck.af_num(), AFType::OutputPushPull);
167 mck.set_speed(crate::gpio::Speed::VeryHigh); 166 mck.set_speed(crate::gpio::Speed::VeryHigh);
168 }
169 167
170 let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default()); 168 let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default());
171 169
@@ -178,7 +176,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
178 let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format); 176 let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format);
179 177
180 #[cfg(any(spi_v1, spi_f1))] 178 #[cfg(any(spi_v1, spi_f1))]
181 unsafe { 179 {
182 use stm32_metapac::spi::vals::{I2scfg, Odd}; 180 use stm32_metapac::spi::vals::{I2scfg, Odd};
183 181
184 // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR register to define the serial clock baud 182 // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR register to define the serial clock baud
@@ -232,10 +230,6 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
232 w.set_i2se(true) 230 w.set_i2se(true)
233 }); 231 });
234 } 232 }
235 #[cfg(spi_v2)]
236 unsafe {}
237 #[cfg(any(spi_v3, spi_v4))]
238 unsafe {}
239 233
240 Self { 234 Self {
241 _peri: spi, 235 _peri: spi,
@@ -264,12 +258,10 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
264 258
265impl<'d, T: Instance, Tx, Rx> Drop for I2S<'d, T, Tx, Rx> { 259impl<'d, T: Instance, Tx, Rx> Drop for I2S<'d, T, Tx, Rx> {
266 fn drop(&mut self) { 260 fn drop(&mut self) {
267 unsafe { 261 self.sd.as_ref().map(|x| x.set_as_disconnected());
268 self.sd.as_ref().map(|x| x.set_as_disconnected()); 262 self.ws.as_ref().map(|x| x.set_as_disconnected());
269 self.ws.as_ref().map(|x| x.set_as_disconnected()); 263 self.ck.as_ref().map(|x| x.set_as_disconnected());
270 self.ck.as_ref().map(|x| x.set_as_disconnected()); 264 self.mck.as_ref().map(|x| x.set_as_disconnected());
271 self.mck.as_ref().map(|x| x.set_as_disconnected());
272 }
273 } 265 }
274} 266}
275 267
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index f481a5955..37f840c73 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -26,7 +26,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_RX> for Receive
26 ]; 26 ];
27 27
28 // Status register gives channel occupied status. For rx, use cpu1. 28 // Status register gives channel occupied status. For rx, use cpu1.
29 let sr = unsafe { regs.cpu(1).sr().read() }; 29 let sr = regs.cpu(1).sr().read();
30 regs.cpu(0).mr().modify(|w| { 30 regs.cpu(0).mr().modify(|w| {
31 for channel in channels { 31 for channel in channels {
32 if sr.chf(channel as usize) { 32 if sr.chf(channel as usize) {
@@ -57,7 +57,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for Transmi
57 ]; 57 ];
58 58
59 // Status register gives channel occupied status. For tx, use cpu0. 59 // Status register gives channel occupied status. For tx, use cpu0.
60 let sr = unsafe { regs.cpu(0).sr().read() }; 60 let sr = regs.cpu(0).sr().read();
61 regs.cpu(0).mr().modify(|w| { 61 regs.cpu(0).mr().modify(|w| {
62 for channel in channels { 62 for channel in channels {
63 if !sr.chf(channel as usize) { 63 if !sr.chf(channel as usize) {
@@ -98,16 +98,14 @@ impl Ipcc {
98 IPCC::reset(); 98 IPCC::reset();
99 IPCC::set_cpu2(true); 99 IPCC::set_cpu2(true);
100 100
101 unsafe { _configure_pwr() }; 101 _configure_pwr();
102 102
103 let regs = IPCC::regs(); 103 let regs = IPCC::regs();
104 104
105 unsafe { 105 regs.cpu(0).cr().modify(|w| {
106 regs.cpu(0).cr().modify(|w| { 106 w.set_rxoie(true);
107 w.set_rxoie(true); 107 w.set_txfie(true);
108 w.set_txfie(true); 108 });
109 })
110 }
111 109
112 // enable interrupts 110 // enable interrupts
113 crate::interrupt::typelevel::IPCC_C1_RX::unpend(); 111 crate::interrupt::typelevel::IPCC_C1_RX::unpend();
@@ -128,7 +126,7 @@ impl Ipcc {
128 compiler_fence(Ordering::SeqCst); 126 compiler_fence(Ordering::SeqCst);
129 127
130 trace!("ipcc: ch {}: send data", channel as u8); 128 trace!("ipcc: ch {}: send data", channel as u8);
131 unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) } 129 regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true));
132 } 130 }
133 131
134 /// Wait for the tx channel to become clear 132 /// Wait for the tx channel to become clear
@@ -136,20 +134,20 @@ impl Ipcc {
136 let regs = IPCC::regs(); 134 let regs = IPCC::regs();
137 135
138 // This is a race, but is nice for debugging 136 // This is a race, but is nice for debugging
139 if unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { 137 if regs.cpu(0).sr().read().chf(channel as usize) {
140 trace!("ipcc: ch {}: wait for tx free", channel as u8); 138 trace!("ipcc: ch {}: wait for tx free", channel as u8);
141 } 139 }
142 140
143 poll_fn(|cx| { 141 poll_fn(|cx| {
144 IPCC::state().tx_waker_for(channel).register(cx.waker()); 142 IPCC::state().tx_waker_for(channel).register(cx.waker());
145 // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt 143 // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt
146 unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)) } 144 regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false));
147 145
148 compiler_fence(Ordering::SeqCst); 146 compiler_fence(Ordering::SeqCst);
149 147
150 if !unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { 148 if !regs.cpu(0).sr().read().chf(channel as usize) {
151 // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt 149 // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt
152 unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } 150 regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true));
153 151
154 Poll::Ready(()) 152 Poll::Ready(())
155 } else { 153 } else {
@@ -165,20 +163,20 @@ impl Ipcc {
165 163
166 loop { 164 loop {
167 // This is a race, but is nice for debugging 165 // This is a race, but is nice for debugging
168 if !unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { 166 if !regs.cpu(1).sr().read().chf(channel as usize) {
169 trace!("ipcc: ch {}: wait for rx occupied", channel as u8); 167 trace!("ipcc: ch {}: wait for rx occupied", channel as u8);
170 } 168 }
171 169
172 poll_fn(|cx| { 170 poll_fn(|cx| {
173 IPCC::state().rx_waker_for(channel).register(cx.waker()); 171 IPCC::state().rx_waker_for(channel).register(cx.waker());
174 // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt 172 // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt
175 unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)) } 173 regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false));
176 174
177 compiler_fence(Ordering::SeqCst); 175 compiler_fence(Ordering::SeqCst);
178 176
179 if unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { 177 if regs.cpu(1).sr().read().chf(channel as usize) {
180 // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt 178 // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt
181 unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } 179 regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true));
182 180
183 Poll::Ready(()) 181 Poll::Ready(())
184 } else { 182 } else {
@@ -197,7 +195,7 @@ impl Ipcc {
197 trace!("ipcc: ch {}: clear rx", channel as u8); 195 trace!("ipcc: ch {}: clear rx", channel as u8);
198 compiler_fence(Ordering::SeqCst); 196 compiler_fence(Ordering::SeqCst);
199 // If the channel is clear and the read function returns none, fetch more data 197 // If the channel is clear and the read function returns none, fetch more data
200 unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } 198 regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true));
201 } 199 }
202 } 200 }
203} 201}
@@ -208,7 +206,7 @@ impl sealed::Instance for crate::peripherals::IPCC {
208 } 206 }
209 207
210 fn set_cpu2(enabled: bool) { 208 fn set_cpu2(enabled: bool) {
211 unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) } 209 crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled));
212 } 210 }
213 211
214 fn state() -> &'static self::sealed::State { 212 fn state() -> &'static self::sealed::State {
@@ -267,7 +265,7 @@ pub(crate) mod sealed {
267 } 265 }
268} 266}
269 267
270unsafe fn _configure_pwr() { 268fn _configure_pwr() {
271 // TODO: move this to RCC 269 // TODO: move this to RCC
272 270
273 let pwr = crate::pac::PWR; 271 let pwr = crate::pac::PWR;
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 6fde61c06..45a7b5476 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -146,35 +146,35 @@ impl Default for Config {
146pub fn init(config: Config) -> Peripherals { 146pub fn init(config: Config) -> Peripherals {
147 let p = Peripherals::take(); 147 let p = Peripherals::take();
148 148
149 unsafe { 149 #[cfg(dbgmcu)]
150 #[cfg(dbgmcu)] 150 if config.enable_debug_during_sleep {
151 if config.enable_debug_during_sleep { 151 crate::pac::DBGMCU.cr().modify(|cr| {
152 crate::pac::DBGMCU.cr().modify(|cr| { 152 #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))]
153 #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))] 153 {
154 { 154 cr.set_dbg_stop(true);
155 cr.set_dbg_stop(true); 155 cr.set_dbg_standby(true);
156 cr.set_dbg_standby(true); 156 }
157 } 157 #[cfg(any(
158 #[cfg(any( 158 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1,
159 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, 159 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl
160 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl 160 ))]
161 ))] 161 {
162 { 162 cr.set_dbg_sleep(true);
163 cr.set_dbg_sleep(true); 163 cr.set_dbg_stop(true);
164 cr.set_dbg_stop(true); 164 cr.set_dbg_standby(true);
165 cr.set_dbg_standby(true); 165 }
166 } 166 #[cfg(dbgmcu_h7)]
167 #[cfg(dbgmcu_h7)] 167 {
168 { 168 cr.set_d1dbgcken(true);
169 cr.set_d1dbgcken(true); 169 cr.set_d3dbgcken(true);
170 cr.set_d3dbgcken(true); 170 cr.set_dbgsleep_d1(true);
171 cr.set_dbgsleep_d1(true); 171 cr.set_dbgstby_d1(true);
172 cr.set_dbgstby_d1(true); 172 cr.set_dbgstop_d1(true);
173 cr.set_dbgstop_d1(true); 173 }
174 } 174 });
175 }); 175 }
176 }
177 176
177 unsafe {
178 gpio::init(); 178 gpio::init();
179 dma::init( 179 dma::init(
180 #[cfg(bdma)] 180 #[cfg(bdma)]
diff --git a/embassy-stm32/src/pwm/complementary_pwm.rs b/embassy-stm32/src/pwm/complementary_pwm.rs
index cfb79947c..0e153202e 100644
--- a/embassy-stm32/src/pwm/complementary_pwm.rs
+++ b/embassy-stm32/src/pwm/complementary_pwm.rs
@@ -21,7 +21,7 @@ macro_rules! complementary_channel_impl {
21 impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { 21 impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> {
22 pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { 22 pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self {
23 into_ref!(pin); 23 into_ref!(pin);
24 critical_section::with(|_| unsafe { 24 critical_section::with(|_| {
25 pin.set_low(); 25 pin.set_low();
26 pin.set_as_af(pin.af_num(), AFType::OutputPushPull); 26 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
27 #[cfg(gpio_v2)] 27 #[cfg(gpio_v2)]
@@ -72,33 +72,27 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
72 this.inner.set_frequency(freq); 72 this.inner.set_frequency(freq);
73 this.inner.start(); 73 this.inner.start();
74 74
75 unsafe { 75 this.inner.enable_outputs(true);
76 this.inner.enable_outputs(true); 76
77 77 this.inner
78 this.inner 78 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1);
79 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); 79 this.inner
80 this.inner 80 .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1);
81 .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); 81 this.inner
82 this.inner 82 .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1);
83 .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); 83 this.inner
84 this.inner 84 .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1);
85 .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1);
86 }
87 this 85 this
88 } 86 }
89 87
90 pub fn enable(&mut self, channel: Channel) { 88 pub fn enable(&mut self, channel: Channel) {
91 unsafe { 89 self.inner.enable_channel(channel, true);
92 self.inner.enable_channel(channel, true); 90 self.inner.enable_complementary_channel(channel, true);
93 self.inner.enable_complementary_channel(channel, true);
94 }
95 } 91 }
96 92
97 pub fn disable(&mut self, channel: Channel) { 93 pub fn disable(&mut self, channel: Channel) {
98 unsafe { 94 self.inner.enable_complementary_channel(channel, false);
99 self.inner.enable_complementary_channel(channel, false); 95 self.inner.enable_channel(channel, false);
100 self.inner.enable_channel(channel, false);
101 }
102 } 96 }
103 97
104 pub fn set_freq(&mut self, freq: Hertz) { 98 pub fn set_freq(&mut self, freq: Hertz) {
@@ -106,22 +100,20 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
106 } 100 }
107 101
108 pub fn get_max_duty(&self) -> u16 { 102 pub fn get_max_duty(&self) -> u16 {
109 unsafe { self.inner.get_max_compare_value() } 103 self.inner.get_max_compare_value()
110 } 104 }
111 105
112 pub fn set_duty(&mut self, channel: Channel, duty: u16) { 106 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
113 assert!(duty < self.get_max_duty()); 107 assert!(duty < self.get_max_duty());
114 unsafe { self.inner.set_compare_value(channel, duty) } 108 self.inner.set_compare_value(channel, duty)
115 } 109 }
116 110
117 /// Set the dead time as a proportion of max_duty 111 /// Set the dead time as a proportion of max_duty
118 pub fn set_dead_time(&mut self, value: u16) { 112 pub fn set_dead_time(&mut self, value: u16) {
119 let (ckd, value) = compute_dead_time_value(value); 113 let (ckd, value) = compute_dead_time_value(value);
120 114
121 unsafe { 115 self.inner.set_dead_time_clock_division(ckd);
122 self.inner.set_dead_time_clock_division(ckd); 116 self.inner.set_dead_time_value(value);
123 self.inner.set_dead_time_value(value);
124 }
125 } 117 }
126} 118}
127 119
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs
index 0bef07089..5aba2663e 100644
--- a/embassy-stm32/src/pwm/mod.rs
+++ b/embassy-stm32/src/pwm/mod.rs
@@ -59,33 +59,33 @@ pub(crate) mod sealed {
59 59
60 pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { 60 pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance {
61 /// Global output enable. Does not do anything on non-advanced timers. 61 /// Global output enable. Does not do anything on non-advanced timers.
62 unsafe fn enable_outputs(&mut self, enable: bool); 62 fn enable_outputs(&mut self, enable: bool);
63 63
64 unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); 64 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
65 65
66 unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); 66 fn enable_channel(&mut self, channel: Channel, enable: bool);
67 67
68 unsafe fn set_compare_value(&mut self, channel: Channel, value: u16); 68 fn set_compare_value(&mut self, channel: Channel, value: u16);
69 69
70 unsafe fn get_max_compare_value(&self) -> u16; 70 fn get_max_compare_value(&self) -> u16;
71 } 71 }
72 72
73 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { 73 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance {
74 unsafe fn set_dead_time_clock_division(&mut self, value: Ckd); 74 fn set_dead_time_clock_division(&mut self, value: Ckd);
75 75
76 unsafe fn set_dead_time_value(&mut self, value: u8); 76 fn set_dead_time_value(&mut self, value: u8);
77 77
78 unsafe fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); 78 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool);
79 } 79 }
80 80
81 pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance { 81 pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance {
82 unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); 82 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
83 83
84 unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); 84 fn enable_channel(&mut self, channel: Channel, enable: bool);
85 85
86 unsafe fn set_compare_value(&mut self, channel: Channel, value: u32); 86 fn set_compare_value(&mut self, channel: Channel, value: u32);
87 87
88 unsafe fn get_max_compare_value(&self) -> u32; 88 fn get_max_compare_value(&self) -> u32;
89 } 89 }
90} 90}
91 91
@@ -108,9 +108,9 @@ pub trait CaptureCompare32bitInstance:
108macro_rules! impl_compare_capable_16bit { 108macro_rules! impl_compare_capable_16bit {
109 ($inst:ident) => { 109 ($inst:ident) => {
110 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 110 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
111 unsafe fn enable_outputs(&mut self, _enable: bool) {} 111 fn enable_outputs(&mut self, _enable: bool) {}
112 112
113 unsafe fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { 113 fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) {
114 use crate::timer::sealed::GeneralPurpose16bitInstance; 114 use crate::timer::sealed::GeneralPurpose16bitInstance;
115 let r = Self::regs_gp16(); 115 let r = Self::regs_gp16();
116 let raw_channel: usize = channel.raw(); 116 let raw_channel: usize = channel.raw();
@@ -118,19 +118,19 @@ macro_rules! impl_compare_capable_16bit {
118 .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); 118 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
119 } 119 }
120 120
121 unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { 121 fn enable_channel(&mut self, channel: Channel, enable: bool) {
122 use crate::timer::sealed::GeneralPurpose16bitInstance; 122 use crate::timer::sealed::GeneralPurpose16bitInstance;
123 Self::regs_gp16() 123 Self::regs_gp16()
124 .ccer() 124 .ccer()
125 .modify(|w| w.set_cce(channel.raw(), enable)); 125 .modify(|w| w.set_cce(channel.raw(), enable));
126 } 126 }
127 127
128 unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { 128 fn set_compare_value(&mut self, channel: Channel, value: u16) {
129 use crate::timer::sealed::GeneralPurpose16bitInstance; 129 use crate::timer::sealed::GeneralPurpose16bitInstance;
130 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); 130 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
131 } 131 }
132 132
133 unsafe fn get_max_compare_value(&self) -> u16 { 133 fn get_max_compare_value(&self) -> u16 {
134 use crate::timer::sealed::GeneralPurpose16bitInstance; 134 use crate::timer::sealed::GeneralPurpose16bitInstance;
135 Self::regs_gp16().arr().read().arr() 135 Self::regs_gp16().arr().read().arr()
136 } 136 }
@@ -150,7 +150,7 @@ foreach_interrupt! {
150 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { 150 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
151 impl_compare_capable_16bit!($inst); 151 impl_compare_capable_16bit!($inst);
152 impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { 152 impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {
153 unsafe fn set_output_compare_mode( 153 fn set_output_compare_mode(
154 &mut self, 154 &mut self,
155 channel: crate::pwm::Channel, 155 channel: crate::pwm::Channel,
156 mode: OutputCompareMode, 156 mode: OutputCompareMode,
@@ -160,17 +160,17 @@ foreach_interrupt! {
160 Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into())); 160 Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
161 } 161 }
162 162
163 unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { 163 fn enable_channel(&mut self, channel: Channel, enable: bool) {
164 use crate::timer::sealed::GeneralPurpose32bitInstance; 164 use crate::timer::sealed::GeneralPurpose32bitInstance;
165 Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable)); 165 Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable));
166 } 166 }
167 167
168 unsafe fn set_compare_value(&mut self, channel: Channel, value: u32) { 168 fn set_compare_value(&mut self, channel: Channel, value: u32) {
169 use crate::timer::sealed::GeneralPurpose32bitInstance; 169 use crate::timer::sealed::GeneralPurpose32bitInstance;
170 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); 170 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
171 } 171 }
172 172
173 unsafe fn get_max_compare_value(&self) -> u32 { 173 fn get_max_compare_value(&self) -> u32 {
174 use crate::timer::sealed::GeneralPurpose32bitInstance; 174 use crate::timer::sealed::GeneralPurpose32bitInstance;
175 Self::regs_gp32().arr().read().arr() as u32 175 Self::regs_gp32().arr().read().arr() as u32
176 } 176 }
@@ -185,13 +185,13 @@ foreach_interrupt! {
185 185
186 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { 186 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
187 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 187 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
188 unsafe fn enable_outputs(&mut self, enable: bool) { 188 fn enable_outputs(&mut self, enable: bool) {
189 use crate::timer::sealed::AdvancedControlInstance; 189 use crate::timer::sealed::AdvancedControlInstance;
190 let r = Self::regs_advanced(); 190 let r = Self::regs_advanced();
191 r.bdtr().modify(|w| w.set_moe(enable)); 191 r.bdtr().modify(|w| w.set_moe(enable));
192 } 192 }
193 193
194 unsafe fn set_output_compare_mode( 194 fn set_output_compare_mode(
195 &mut self, 195 &mut self,
196 channel: crate::pwm::Channel, 196 channel: crate::pwm::Channel,
197 mode: OutputCompareMode, 197 mode: OutputCompareMode,
@@ -203,21 +203,21 @@ foreach_interrupt! {
203 .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); 203 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
204 } 204 }
205 205
206 unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { 206 fn enable_channel(&mut self, channel: Channel, enable: bool) {
207 use crate::timer::sealed::AdvancedControlInstance; 207 use crate::timer::sealed::AdvancedControlInstance;
208 Self::regs_advanced() 208 Self::regs_advanced()
209 .ccer() 209 .ccer()
210 .modify(|w| w.set_cce(channel.raw(), enable)); 210 .modify(|w| w.set_cce(channel.raw(), enable));
211 } 211 }
212 212
213 unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { 213 fn set_compare_value(&mut self, channel: Channel, value: u16) {
214 use crate::timer::sealed::AdvancedControlInstance; 214 use crate::timer::sealed::AdvancedControlInstance;
215 Self::regs_advanced() 215 Self::regs_advanced()
216 .ccr(channel.raw()) 216 .ccr(channel.raw())
217 .modify(|w| w.set_ccr(value)); 217 .modify(|w| w.set_ccr(value));
218 } 218 }
219 219
220 unsafe fn get_max_compare_value(&self) -> u16 { 220 fn get_max_compare_value(&self) -> u16 {
221 use crate::timer::sealed::AdvancedControlInstance; 221 use crate::timer::sealed::AdvancedControlInstance;
222 Self::regs_advanced().arr().read().arr() 222 Self::regs_advanced().arr().read().arr()
223 } 223 }
@@ -228,17 +228,17 @@ foreach_interrupt! {
228 } 228 }
229 229
230 impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { 230 impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
231 unsafe fn set_dead_time_clock_division(&mut self, value: Ckd) { 231 fn set_dead_time_clock_division(&mut self, value: Ckd) {
232 use crate::timer::sealed::AdvancedControlInstance; 232 use crate::timer::sealed::AdvancedControlInstance;
233 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); 233 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
234 } 234 }
235 235
236 unsafe fn set_dead_time_value(&mut self, value: u8) { 236 fn set_dead_time_value(&mut self, value: u8) {
237 use crate::timer::sealed::AdvancedControlInstance; 237 use crate::timer::sealed::AdvancedControlInstance;
238 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); 238 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
239 } 239 }
240 240
241 unsafe fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { 241 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
242 use crate::timer::sealed::AdvancedControlInstance; 242 use crate::timer::sealed::AdvancedControlInstance;
243 Self::regs_advanced() 243 Self::regs_advanced()
244 .ccer() 244 .ccer()
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs
index b045a2d78..995f59c23 100644
--- a/embassy-stm32/src/pwm/simple_pwm.rs
+++ b/embassy-stm32/src/pwm/simple_pwm.rs
@@ -24,7 +24,7 @@ macro_rules! channel_impl {
24 impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { 24 impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> {
25 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self { 25 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
26 into_ref!(pin); 26 into_ref!(pin);
27 critical_section::with(|_| unsafe { 27 critical_section::with(|_| {
28 pin.set_low(); 28 pin.set_low();
29 pin.set_as_af(pin.af_num(), AFType::OutputPushPull); 29 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
30 #[cfg(gpio_v2)] 30 #[cfg(gpio_v2)]
@@ -71,31 +71,25 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
71 this.inner.set_frequency(freq); 71 this.inner.set_frequency(freq);
72 this.inner.start(); 72 this.inner.start();
73 73
74 unsafe { 74 this.inner.enable_outputs(true);
75 this.inner.enable_outputs(true); 75
76 76 this.inner
77 this.inner 77 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1);
78 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); 78 this.inner
79 this.inner 79 .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1);
80 .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); 80 this.inner
81 this.inner 81 .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1);
82 .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); 82 this.inner
83 this.inner 83 .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1);
84 .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1);
85 }
86 this 84 this
87 } 85 }
88 86
89 pub fn enable(&mut self, channel: Channel) { 87 pub fn enable(&mut self, channel: Channel) {
90 unsafe { 88 self.inner.enable_channel(channel, true);
91 self.inner.enable_channel(channel, true);
92 }
93 } 89 }
94 90
95 pub fn disable(&mut self, channel: Channel) { 91 pub fn disable(&mut self, channel: Channel) {
96 unsafe { 92 self.inner.enable_channel(channel, false);
97 self.inner.enable_channel(channel, false);
98 }
99 } 93 }
100 94
101 pub fn set_freq(&mut self, freq: Hertz) { 95 pub fn set_freq(&mut self, freq: Hertz) {
@@ -103,11 +97,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
103 } 97 }
104 98
105 pub fn get_max_duty(&self) -> u16 { 99 pub fn get_max_duty(&self) -> u16 {
106 unsafe { self.inner.get_max_compare_value() } 100 self.inner.get_max_compare_value()
107 } 101 }
108 102
109 pub fn set_duty(&mut self, channel: Channel, duty: u16) { 103 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
110 assert!(duty < self.get_max_duty()); 104 assert!(duty < self.get_max_duty());
111 unsafe { self.inner.set_compare_value(channel, duty) } 105 self.inner.set_compare_value(channel, duty)
112 } 106 }
113} 107}
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index c3126b37f..e9db934bf 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -96,20 +96,18 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
96 ) -> Self { 96 ) -> Self {
97 into_ref!(peri, d0, d1, d2, d3, sck, nss); 97 into_ref!(peri, d0, d1, d2, d3, sck, nss);
98 98
99 unsafe { 99 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
100 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 100 sck.set_speed(crate::gpio::Speed::VeryHigh);
101 sck.set_speed(crate::gpio::Speed::VeryHigh); 101 nss.set_as_af(nss.af_num(), AFType::OutputPushPull);
102 nss.set_as_af(nss.af_num(), AFType::OutputPushPull); 102 nss.set_speed(crate::gpio::Speed::VeryHigh);
103 nss.set_speed(crate::gpio::Speed::VeryHigh); 103 d0.set_as_af(d0.af_num(), AFType::OutputPushPull);
104 d0.set_as_af(d0.af_num(), AFType::OutputPushPull); 104 d0.set_speed(crate::gpio::Speed::VeryHigh);
105 d0.set_speed(crate::gpio::Speed::VeryHigh); 105 d1.set_as_af(d1.af_num(), AFType::OutputPushPull);
106 d1.set_as_af(d1.af_num(), AFType::OutputPushPull); 106 d1.set_speed(crate::gpio::Speed::VeryHigh);
107 d1.set_speed(crate::gpio::Speed::VeryHigh); 107 d2.set_as_af(d2.af_num(), AFType::OutputPushPull);
108 d2.set_as_af(d2.af_num(), AFType::OutputPushPull); 108 d2.set_speed(crate::gpio::Speed::VeryHigh);
109 d2.set_speed(crate::gpio::Speed::VeryHigh); 109 d3.set_as_af(d3.af_num(), AFType::OutputPushPull);
110 d3.set_as_af(d3.af_num(), AFType::OutputPushPull); 110 d3.set_speed(crate::gpio::Speed::VeryHigh);
111 d3.set_speed(crate::gpio::Speed::VeryHigh);
112 }
113 111
114 Self::new_inner( 112 Self::new_inner(
115 peri, 113 peri,
@@ -138,21 +136,19 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
138 into_ref!(peri, dma); 136 into_ref!(peri, dma);
139 137
140 T::enable(); 138 T::enable();
141 unsafe { 139 T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into()));
142 T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into()));
143 140
144 while T::REGS.sr().read().busy() {} 141 while T::REGS.sr().read().busy() {}
145 142
146 T::REGS.cr().write(|w| { 143 T::REGS.cr().write(|w| {
147 w.set_prescaler(config.prescaler); 144 w.set_prescaler(config.prescaler);
148 w.set_en(true); 145 w.set_en(true);
149 }); 146 });
150 T::REGS.dcr().write(|w| { 147 T::REGS.dcr().write(|w| {
151 w.set_fsize(config.memory_size.into()); 148 w.set_fsize(config.memory_size.into());
152 w.set_csht(config.cs_high_time.into()); 149 w.set_csht(config.cs_high_time.into());
153 w.set_ckmode(false); 150 w.set_ckmode(false);
154 }); 151 });
155 }
156 152
157 Self { 153 Self {
158 _peri: peri, 154 _peri: peri,
@@ -168,148 +164,140 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
168 } 164 }
169 165
170 pub fn command(&mut self, transaction: TransferConfig) { 166 pub fn command(&mut self, transaction: TransferConfig) {
171 unsafe { 167 T::REGS.cr().modify(|v| v.set_dmaen(false));
172 T::REGS.cr().modify(|v| v.set_dmaen(false)); 168 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
173 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
174 169
175 while !T::REGS.sr().read().tcf() {} 170 while !T::REGS.sr().read().tcf() {}
176 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 171 T::REGS.fcr().modify(|v| v.set_ctcf(true));
177 }
178 } 172 }
179 173
180 pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { 174 pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {
181 unsafe { 175 T::REGS.cr().modify(|v| v.set_dmaen(false));
182 T::REGS.cr().modify(|v| v.set_dmaen(false)); 176 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
183 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 177
184 178 if let Some(len) = transaction.data_len {
185 if let Some(len) = transaction.data_len { 179 let current_ar = T::REGS.ar().read().address();
186 let current_ar = T::REGS.ar().read().address(); 180 T::REGS.ccr().modify(|v| {
187 T::REGS.ccr().modify(|v| { 181 v.set_fmode(QspiMode::IndirectRead.into());
188 v.set_fmode(QspiMode::IndirectRead.into()); 182 });
189 }); 183 T::REGS.ar().write(|v| {
190 T::REGS.ar().write(|v| { 184 v.set_address(current_ar);
191 v.set_address(current_ar); 185 });
192 });
193
194 for idx in 0..len {
195 while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
196 buf[idx] = *(T::REGS.dr().ptr() as *mut u8);
197 }
198 }
199 186
200 while !T::REGS.sr().read().tcf() {} 187 for idx in 0..len {
201 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 188 while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
189 buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() };
190 }
202 } 191 }
192
193 while !T::REGS.sr().read().tcf() {}
194 T::REGS.fcr().modify(|v| v.set_ctcf(true));
203 } 195 }
204 196
205 pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { 197 pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) {
206 unsafe { 198 T::REGS.cr().modify(|v| v.set_dmaen(false));
207 T::REGS.cr().modify(|v| v.set_dmaen(false)); 199 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
208 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
209
210 if let Some(len) = transaction.data_len {
211 T::REGS.ccr().modify(|v| {
212 v.set_fmode(QspiMode::IndirectWrite.into());
213 });
214
215 for idx in 0..len {
216 while !T::REGS.sr().read().ftf() {}
217 *(T::REGS.dr().ptr() as *mut u8) = buf[idx];
218 }
219 }
220 200
221 while !T::REGS.sr().read().tcf() {} 201 if let Some(len) = transaction.data_len {
222 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 202 T::REGS.ccr().modify(|v| {
203 v.set_fmode(QspiMode::IndirectWrite.into());
204 });
205
206 for idx in 0..len {
207 while !T::REGS.sr().read().ftf() {}
208 unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) };
209 }
223 } 210 }
211
212 while !T::REGS.sr().read().tcf() {}
213 T::REGS.fcr().modify(|v| v.set_ctcf(true));
224 } 214 }
225 215
226 pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) 216 pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig)
227 where 217 where
228 Dma: QuadDma<T>, 218 Dma: QuadDma<T>,
229 { 219 {
230 unsafe { 220 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
231 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 221
232 222 T::REGS.ccr().modify(|v| {
233 T::REGS.ccr().modify(|v| { 223 v.set_fmode(QspiMode::IndirectRead.into());
234 v.set_fmode(QspiMode::IndirectRead.into()); 224 });
235 }); 225 let current_ar = T::REGS.ar().read().address();
236 let current_ar = T::REGS.ar().read().address(); 226 T::REGS.ar().write(|v| {
237 T::REGS.ar().write(|v| { 227 v.set_address(current_ar);
238 v.set_address(current_ar); 228 });
239 }); 229
240 230 let request = self.dma.request();
241 let request = self.dma.request(); 231 let transfer = unsafe {
242 let transfer = Transfer::new_read( 232 Transfer::new_read(
243 &mut self.dma, 233 &mut self.dma,
244 request, 234 request,
245 T::REGS.dr().ptr() as *mut u8, 235 T::REGS.dr().as_ptr() as *mut u8,
246 buf, 236 buf,
247 Default::default(), 237 Default::default(),
248 ); 238 )
239 };
249 240
250 T::REGS.cr().modify(|v| v.set_dmaen(true)); 241 T::REGS.cr().modify(|v| v.set_dmaen(true));
251 242
252 transfer.blocking_wait(); 243 transfer.blocking_wait();
253 }
254 } 244 }
255 245
256 pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) 246 pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig)
257 where 247 where
258 Dma: QuadDma<T>, 248 Dma: QuadDma<T>,
259 { 249 {
260 unsafe { 250 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
261 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
262 251
263 T::REGS.ccr().modify(|v| { 252 T::REGS.ccr().modify(|v| {
264 v.set_fmode(QspiMode::IndirectWrite.into()); 253 v.set_fmode(QspiMode::IndirectWrite.into());
265 }); 254 });
266 255
267 let request = self.dma.request(); 256 let request = self.dma.request();
268 let transfer = Transfer::new_write( 257 let transfer = unsafe {
258 Transfer::new_write(
269 &mut self.dma, 259 &mut self.dma,
270 request, 260 request,
271 buf, 261 buf,
272 T::REGS.dr().ptr() as *mut u8, 262 T::REGS.dr().as_ptr() as *mut u8,
273 Default::default(), 263 Default::default(),
274 ); 264 )
265 };
275 266
276 T::REGS.cr().modify(|v| v.set_dmaen(true)); 267 T::REGS.cr().modify(|v| v.set_dmaen(true));
277 268
278 transfer.blocking_wait(); 269 transfer.blocking_wait();
279 }
280 } 270 }
281 271
282 fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { 272 fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) {
283 unsafe { 273 T::REGS.fcr().modify(|v| {
284 T::REGS.fcr().modify(|v| { 274 v.set_csmf(true);
285 v.set_csmf(true); 275 v.set_ctcf(true);
286 v.set_ctcf(true); 276 v.set_ctef(true);
287 v.set_ctef(true); 277 v.set_ctof(true);
288 v.set_ctof(true); 278 });
289 });
290 279
291 while T::REGS.sr().read().busy() {} 280 while T::REGS.sr().read().busy() {}
292 281
293 if let Some(len) = transaction.data_len { 282 if let Some(len) = transaction.data_len {
294 T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); 283 T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1));
295 } 284 }
296 285
297 T::REGS.ccr().write(|v| { 286 T::REGS.ccr().write(|v| {
298 v.set_fmode(fmode.into()); 287 v.set_fmode(fmode.into());
299 v.set_imode(transaction.iwidth.into()); 288 v.set_imode(transaction.iwidth.into());
300 v.set_instruction(transaction.instruction); 289 v.set_instruction(transaction.instruction);
301 v.set_admode(transaction.awidth.into()); 290 v.set_admode(transaction.awidth.into());
302 v.set_adsize(self.config.address_size.into()); 291 v.set_adsize(self.config.address_size.into());
303 v.set_dmode(transaction.dwidth.into()); 292 v.set_dmode(transaction.dwidth.into());
304 v.set_abmode(QspiWidth::NONE.into()); 293 v.set_abmode(QspiWidth::NONE.into());
305 v.set_dcyc(transaction.dummy.into()); 294 v.set_dcyc(transaction.dummy.into());
295 });
296
297 if let Some(addr) = transaction.address {
298 T::REGS.ar().write(|v| {
299 v.set_address(addr);
306 }); 300 });
307
308 if let Some(addr) = transaction.address {
309 T::REGS.ar().write(|v| {
310 v.set_address(addr);
311 });
312 }
313 } 301 }
314 } 302 }
315} 303}
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
index e0929ca49..bc430afb2 100644
--- a/embassy-stm32/src/rcc/f4.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -36,18 +36,18 @@ pub struct Config {
36} 36}
37 37
38#[cfg(stm32f410)] 38#[cfg(stm32f410)]
39unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> { 39fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> {
40 None 40 None
41} 41}
42 42
43// Not currently implemented, but will be in the future 43// Not currently implemented, but will be in the future
44#[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] 44#[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))]
45unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> { 45fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> {
46 None 46 None
47} 47}
48 48
49#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] 49#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
50unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> { 50fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
51 let min_div = 2; 51 let min_div = 2;
52 let max_div = 7; 52 let max_div = 7;
53 let target = match plli2s { 53 let target = match plli2s {
@@ -82,13 +82,7 @@ unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
82 Some(output) 82 Some(output)
83} 83}
84 84
85unsafe fn setup_pll( 85fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Option<u32>, pll48clk: bool) -> PllResults {
86 pllsrcclk: u32,
87 use_hse: bool,
88 pllsysclk: Option<u32>,
89 plli2s: Option<u32>,
90 pll48clk: bool,
91) -> PllResults {
92 use crate::pac::rcc::vals::{Pllp, Pllsrc}; 86 use crate::pac::rcc::vals::{Pllp, Pllsrc};
93 87
94 let sysclk = pllsysclk.unwrap_or(pllsrcclk); 88 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
@@ -320,7 +314,7 @@ impl<'d, T: McoInstance> Mco<'d, T> {
320 } 314 }
321} 315}
322 316
323unsafe fn flash_setup(sysclk: u32) { 317fn flash_setup(sysclk: u32) {
324 use crate::pac::flash::vals::Latency; 318 use crate::pac::flash::vals::Latency;
325 319
326 // Be conservative with voltage ranges 320 // Be conservative with voltage ranges
diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs
index 2d21326a3..71215cac5 100644
--- a/embassy-stm32/src/rcc/f7.rs
+++ b/embassy-stm32/src/rcc/f7.rs
@@ -25,7 +25,7 @@ pub struct Config {
25 pub pll48: bool, 25 pub pll48: bool,
26} 26}
27 27
28unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults { 28fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults {
29 use crate::pac::rcc::vals::{Pllp, Pllsrc}; 29 use crate::pac::rcc::vals::{Pllp, Pllsrc};
30 30
31 let sysclk = pllsysclk.unwrap_or(pllsrcclk); 31 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
@@ -97,7 +97,7 @@ unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48
97 } 97 }
98} 98}
99 99
100unsafe fn flash_setup(sysclk: u32) { 100fn flash_setup(sysclk: u32) {
101 use crate::pac::flash::vals::Latency; 101 use crate::pac::flash::vals::Latency;
102 102
103 // Be conservative with voltage ranges 103 // Be conservative with voltage ranges
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index 3e138c7ab..17c73c36b 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -245,7 +245,7 @@ impl Default for Config {
245} 245}
246 246
247impl PllConfig { 247impl PllConfig {
248 pub(crate) unsafe fn init(self) -> u32 { 248 pub(crate) fn init(self) -> u32 {
249 assert!(self.n >= 8 && self.n <= 86); 249 assert!(self.n >= 8 && self.n <= 86);
250 let (src, input_freq) = match self.source { 250 let (src, input_freq) = match self.source {
251 PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0), 251 PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0),
diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs
index 17fbc6056..4025a4e05 100644
--- a/embassy-stm32/src/rcc/h5.rs
+++ b/embassy-stm32/src/rcc/h5.rs
@@ -462,7 +462,7 @@ struct PllOutput {
462 r: Option<Hertz>, 462 r: Option<Hertz>,
463} 463}
464 464
465unsafe fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput { 465fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
466 let Some(config) = config else { 466 let Some(config) = config else {
467 // Stop PLL 467 // Stop PLL
468 RCC.cr().modify(|w| w.set_pllon(num, false)); 468 RCC.cr().modify(|w| w.set_pllon(num, false));
@@ -595,12 +595,9 @@ fn flash_setup(clk: Hertz, vos: VoltageScale) {
595 595
596 defmt::debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq); 596 defmt::debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq);
597 597
598 // NOTE(unsafe) Atomic write 598 FLASH.acr().write(|w| {
599 unsafe { 599 w.set_wrhighfreq(wrhighfreq);
600 FLASH.acr().write(|w| { 600 w.set_latency(latency);
601 w.set_wrhighfreq(wrhighfreq); 601 });
602 w.set_latency(latency); 602 while FLASH.acr().read().latency() != latency {}
603 });
604 while FLASH.acr().read().latency() != latency {}
605 }
606} 603}
diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs
index 0185f7ae8..daa1cd61f 100644
--- a/embassy-stm32/src/rcc/h7.rs
+++ b/embassy-stm32/src/rcc/h7.rs
@@ -253,14 +253,11 @@ fn flash_setup(rcc_aclk: u32, vos: VoltageScale) {
253 }, 253 },
254 }; 254 };
255 255
256 // NOTE(unsafe) Atomic write 256 FLASH.acr().write(|w| {
257 unsafe { 257 w.set_wrhighfreq(progr_delay);
258 FLASH.acr().write(|w| { 258 w.set_latency(wait_states)
259 w.set_wrhighfreq(progr_delay); 259 });
260 w.set_latency(wait_states) 260 while FLASH.acr().read().latency() != wait_states {}
261 });
262 while FLASH.acr().read().latency() != wait_states {}
263 }
264} 261}
265 262
266pub enum McoClock { 263pub enum McoClock {
@@ -474,7 +471,6 @@ pub(crate) unsafe fn init(mut config: Config) {
474 // Configure traceclk from PLL if needed 471 // Configure traceclk from PLL if needed
475 traceclk_setup(&mut config, sys_use_pll1_p); 472 traceclk_setup(&mut config, sys_use_pll1_p);
476 473
477 // NOTE(unsafe) We have exclusive access to the RCC
478 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = pll::pll_setup(srcclk.0, &config.pll1, 0); 474 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = pll::pll_setup(srcclk.0, &config.pll1, 0);
479 let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = pll::pll_setup(srcclk.0, &config.pll2, 1); 475 let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = pll::pll_setup(srcclk.0, &config.pll2, 1);
480 let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = pll::pll_setup(srcclk.0, &config.pll3, 2); 476 let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = pll::pll_setup(srcclk.0, &config.pll3, 2);
@@ -756,7 +752,7 @@ mod pll {
756 /// # Safety 752 /// # Safety
757 /// 753 ///
758 /// Must have exclusive access to the RCC register block 754 /// Must have exclusive access to the RCC register block
759 unsafe fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults { 755 fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults {
760 use crate::pac::rcc::vals::{Pllrge, Pllvcosel}; 756 use crate::pac::rcc::vals::{Pllrge, Pllvcosel};
761 757
762 let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln); 758 let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln);
@@ -785,11 +781,7 @@ mod pll {
785 /// # Safety 781 /// # Safety
786 /// 782 ///
787 /// Must have exclusive access to the RCC register block 783 /// Must have exclusive access to the RCC register block
788 pub(super) unsafe fn pll_setup( 784 pub(super) fn pll_setup(pll_src: u32, config: &PllConfig, plln: usize) -> (Option<u32>, Option<u32>, Option<u32>) {
789 pll_src: u32,
790 config: &PllConfig,
791 plln: usize,
792 ) -> (Option<u32>, Option<u32>, Option<u32>) {
793 use crate::pac::rcc::vals::Divp; 785 use crate::pac::rcc::vals::Divp;
794 786
795 match config.p_ck { 787 match config.p_ck {
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index c657bf70e..b2faec53d 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -34,40 +34,34 @@ impl<'d, T: Instance> Rng<'d, T> {
34 pub fn reset(&mut self) { 34 pub fn reset(&mut self) {
35 // rng_v2 locks up on seed error, needs reset 35 // rng_v2 locks up on seed error, needs reset
36 #[cfg(rng_v2)] 36 #[cfg(rng_v2)]
37 if unsafe { T::regs().sr().read().seis() } { 37 if T::regs().sr().read().seis() {
38 T::reset(); 38 T::reset();
39 } 39 }
40 unsafe { 40 T::regs().cr().modify(|reg| {
41 T::regs().cr().modify(|reg| { 41 reg.set_rngen(true);
42 reg.set_rngen(true); 42 reg.set_ie(true);
43 reg.set_ie(true); 43 });
44 }); 44 T::regs().sr().modify(|reg| {
45 T::regs().sr().modify(|reg| { 45 reg.set_seis(false);
46 reg.set_seis(false); 46 reg.set_ceis(false);
47 reg.set_ceis(false); 47 });
48 });
49 }
50 // Reference manual says to discard the first. 48 // Reference manual says to discard the first.
51 let _ = self.next_u32(); 49 let _ = self.next_u32();
52 } 50 }
53 51
54 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 52 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
55 unsafe { 53 T::regs().cr().modify(|reg| {
56 T::regs().cr().modify(|reg| { 54 reg.set_rngen(true);
57 reg.set_rngen(true); 55 });
58 })
59 }
60 56
61 for chunk in dest.chunks_mut(4) { 57 for chunk in dest.chunks_mut(4) {
62 poll_fn(|cx| { 58 poll_fn(|cx| {
63 RNG_WAKER.register(cx.waker()); 59 RNG_WAKER.register(cx.waker());
64 unsafe { 60 T::regs().cr().modify(|reg| {
65 T::regs().cr().modify(|reg| { 61 reg.set_ie(true);
66 reg.set_ie(true); 62 });
67 });
68 }
69 63
70 let bits = unsafe { T::regs().sr().read() }; 64 let bits = T::regs().sr().read();
71 65
72 if bits.drdy() { 66 if bits.drdy() {
73 Poll::Ready(Ok(())) 67 Poll::Ready(Ok(()))
@@ -82,7 +76,7 @@ impl<'d, T: Instance> Rng<'d, T> {
82 } 76 }
83 }) 77 })
84 .await?; 78 .await?;
85 let random_bytes = unsafe { T::regs().dr().read() }.to_be_bytes(); 79 let random_bytes = T::regs().dr().read().to_be_bytes();
86 for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) { 80 for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) {
87 *dest = *src 81 *dest = *src
88 } 82 }
@@ -95,11 +89,11 @@ impl<'d, T: Instance> Rng<'d, T> {
95impl<'d, T: Instance> RngCore for Rng<'d, T> { 89impl<'d, T: Instance> RngCore for Rng<'d, T> {
96 fn next_u32(&mut self) -> u32 { 90 fn next_u32(&mut self) -> u32 {
97 loop { 91 loop {
98 let sr = unsafe { T::regs().sr().read() }; 92 let sr = T::regs().sr().read();
99 if sr.seis() | sr.ceis() { 93 if sr.seis() | sr.ceis() {
100 self.reset(); 94 self.reset();
101 } else if sr.drdy() { 95 } else if sr.drdy() {
102 return unsafe { T::regs().dr().read() }; 96 return T::regs().dr().read();
103 } 97 }
104 } 98 }
105 } 99 }
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs
index 0a590c1bb..a9c48d88d 100644
--- a/embassy-stm32/src/rtc/datetime.rs
+++ b/embassy-stm32/src/rtc/datetime.rs
@@ -154,29 +154,27 @@ pub(super) fn write_date_time(rtc: &Rtc, t: DateTime) {
154 let yr_offset = (yr - 1970_u16) as u8; 154 let yr_offset = (yr - 1970_u16) as u8;
155 let (yt, yu) = byte_to_bcd2(yr_offset); 155 let (yt, yu) = byte_to_bcd2(yr_offset);
156 156
157 unsafe { 157 use crate::pac::rtc::vals::Ampm;
158 use crate::pac::rtc::vals::Ampm; 158
159 159 rtc.tr().write(|w| {
160 rtc.tr().write(|w| { 160 w.set_ht(ht);
161 w.set_ht(ht); 161 w.set_hu(hu);
162 w.set_hu(hu); 162 w.set_mnt(mnt);
163 w.set_mnt(mnt); 163 w.set_mnu(mnu);
164 w.set_mnu(mnu); 164 w.set_st(st);
165 w.set_st(st); 165 w.set_su(su);
166 w.set_su(su); 166 w.set_pm(Ampm::AM);
167 w.set_pm(Ampm::AM); 167 });
168 }); 168
169 169 rtc.dr().write(|w| {
170 rtc.dr().write(|w| { 170 w.set_dt(dt);
171 w.set_dt(dt); 171 w.set_du(du);
172 w.set_du(du); 172 w.set_mt(mt > 0);
173 w.set_mt(mt > 0); 173 w.set_mu(mu);
174 w.set_mu(mu); 174 w.set_yt(yt);
175 w.set_yt(yt); 175 w.set_yu(yu);
176 w.set_yu(yu); 176 w.set_wdu(day_of_week_to_u8(t.day_of_week));
177 w.set_wdu(day_of_week_to_u8(t.day_of_week)); 177 });
178 });
179 }
180} 178}
181 179
182pub(super) fn datetime( 180pub(super) fn datetime(
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 962927fb1..12a2ac795 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -113,7 +113,7 @@ impl Default for RtcCalibrationCyclePeriod {
113 113
114impl<'d, T: Instance> Rtc<'d, T> { 114impl<'d, T: Instance> Rtc<'d, T> {
115 pub fn new(_rtc: impl Peripheral<P = T> + 'd, rtc_config: RtcConfig) -> Self { 115 pub fn new(_rtc: impl Peripheral<P = T> + 'd, rtc_config: RtcConfig) -> Self {
116 unsafe { T::enable_peripheral_clk() }; 116 T::enable_peripheral_clk();
117 117
118 let mut rtc_struct = Self { 118 let mut rtc_struct = Self {
119 phantom: PhantomData, 119 phantom: PhantomData,
@@ -144,34 +144,32 @@ impl<'d, T: Instance> Rtc<'d, T> {
144 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. 144 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
145 pub fn now(&self) -> Result<DateTime, RtcError> { 145 pub fn now(&self) -> Result<DateTime, RtcError> {
146 let r = T::regs(); 146 let r = T::regs();
147 unsafe { 147 let tr = r.tr().read();
148 let tr = r.tr().read(); 148 let second = bcd2_to_byte((tr.st(), tr.su()));
149 let second = bcd2_to_byte((tr.st(), tr.su())); 149 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
150 let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); 150 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
151 let hour = bcd2_to_byte((tr.ht(), tr.hu())); 151 // Reading either RTC_SSR or RTC_TR locks the values in the higher-order
152 // Reading either RTC_SSR or RTC_TR locks the values in the higher-order 152 // calendar shadow registers until RTC_DR is read.
153 // calendar shadow registers until RTC_DR is read. 153 let dr = r.dr().read();
154 let dr = r.dr().read(); 154
155 155 let weekday = dr.wdu();
156 let weekday = dr.wdu(); 156 let day = bcd2_to_byte((dr.dt(), dr.du()));
157 let day = bcd2_to_byte((dr.dt(), dr.du())); 157 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
158 let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); 158 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
159 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; 159
160 160 self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
161 self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
162 }
163 } 161 }
164 162
165 /// Check if daylight savings time is active. 163 /// Check if daylight savings time is active.
166 pub fn get_daylight_savings(&self) -> bool { 164 pub fn get_daylight_savings(&self) -> bool {
167 let cr = unsafe { T::regs().cr().read() }; 165 let cr = T::regs().cr().read();
168 cr.bkp() 166 cr.bkp()
169 } 167 }
170 168
171 /// Enable/disable daylight savings time. 169 /// Enable/disable daylight savings time.
172 pub fn set_daylight_savings(&mut self, daylight_savings: bool) { 170 pub fn set_daylight_savings(&mut self, daylight_savings: bool) {
173 self.write(true, |rtc| { 171 self.write(true, |rtc| {
174 unsafe { rtc.cr().modify(|w| w.set_bkp(daylight_savings)) }; 172 rtc.cr().modify(|w| w.set_bkp(daylight_savings));
175 }) 173 })
176 } 174 }
177 175
@@ -228,7 +226,7 @@ pub(crate) mod sealed {
228 crate::pac::RTC 226 crate::pac::RTC
229 } 227 }
230 228
231 unsafe fn enable_peripheral_clk() {} 229 fn enable_peripheral_clk() {}
232 230
233 /// Read content of the backup register. 231 /// Read content of the backup register.
234 /// 232 ///
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index adaafe67a..e1615b34c 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -8,74 +8,72 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
8 /// It this changes the RTC clock source the time will be reset 8 /// It this changes the RTC clock source the time will be reset
9 pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { 9 pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) {
10 // Unlock the backup domain 10 // Unlock the backup domain
11 unsafe { 11 let clock_config = rtc_config.clock_config as u8;
12 let clock_config = rtc_config.clock_config as u8;
13 12
14 #[cfg(not(rtc_v2wb))] 13 #[cfg(not(rtc_v2wb))]
15 use stm32_metapac::rcc::vals::Rtcsel; 14 use stm32_metapac::rcc::vals::Rtcsel;
16 15
17 #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] 16 #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))]
18 let cr = crate::pac::PWR.cr(); 17 let cr = crate::pac::PWR.cr();
19 #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] 18 #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))]
20 let cr = crate::pac::PWR.cr1(); 19 let cr = crate::pac::PWR.cr1();
21 20
22 // TODO: Missing from PAC for l0 and f0? 21 // TODO: Missing from PAC for l0 and f0?
23 #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] 22 #[cfg(not(any(rtc_v2f0, rtc_v2l0)))]
24 { 23 {
25 cr.modify(|w| w.set_dbp(true)); 24 cr.modify(|w| w.set_dbp(true));
26 while !cr.read().dbp() {} 25 while !cr.read().dbp() {}
27 } 26 }
28 27
29 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 28 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
30 let reg = crate::pac::RCC.bdcr().read(); 29 let reg = crate::pac::RCC.bdcr().read();
31 #[cfg(any(rtc_v2l0, rtc_v2l1))] 30 #[cfg(any(rtc_v2l0, rtc_v2l1))]
32 let reg = crate::pac::RCC.csr().read(); 31 let reg = crate::pac::RCC.csr().read();
33 32
34 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] 33 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))]
35 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); 34 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
36 35
37 #[cfg(rtc_v2wb)] 36 #[cfg(rtc_v2wb)]
38 let rtcsel = reg.rtcsel(); 37 let rtcsel = reg.rtcsel();
39 #[cfg(not(rtc_v2wb))] 38 #[cfg(not(rtc_v2wb))]
40 let rtcsel = reg.rtcsel().0; 39 let rtcsel = reg.rtcsel().0;
41 40
42 if !reg.rtcen() || rtcsel != clock_config { 41 if !reg.rtcen() || rtcsel != clock_config {
43 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 42 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
44 crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); 43 crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true));
45 44
45 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
46 let cr = crate::pac::RCC.bdcr();
47 #[cfg(any(rtc_v2l0, rtc_v2l1))]
48 let cr = crate::pac::RCC.csr();
49
50 cr.modify(|w| {
51 // Reset
46 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 52 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
47 let cr = crate::pac::RCC.bdcr(); 53 w.set_bdrst(false);
48 #[cfg(any(rtc_v2l0, rtc_v2l1))] 54
49 let cr = crate::pac::RCC.csr(); 55 // Select RTC source
50 56 #[cfg(not(rtc_v2wb))]
51 cr.modify(|w| { 57 w.set_rtcsel(Rtcsel(clock_config));
52 // Reset 58 #[cfg(rtc_v2wb)]
53 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 59 w.set_rtcsel(clock_config);
54 w.set_bdrst(false); 60 w.set_rtcen(true);
55 61
56 // Select RTC source 62 // Restore bcdr
57 #[cfg(not(rtc_v2wb))] 63 #[cfg(any(rtc_v2l4, rtc_v2wb))]
58 w.set_rtcsel(Rtcsel(clock_config)); 64 w.set_lscosel(reg.lscosel());
59 #[cfg(rtc_v2wb)] 65 #[cfg(any(rtc_v2l4, rtc_v2wb))]
60 w.set_rtcsel(clock_config); 66 w.set_lscoen(reg.lscoen());
61 w.set_rtcen(true); 67
62 68 w.set_lseon(reg.lseon());
63 // Restore bcdr 69
64 #[cfg(any(rtc_v2l4, rtc_v2wb))] 70 #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))]
65 w.set_lscosel(reg.lscosel()); 71 w.set_lsedrv(reg.lsedrv());
66 #[cfg(any(rtc_v2l4, rtc_v2wb))] 72 w.set_lsebyp(reg.lsebyp());
67 w.set_lscoen(reg.lscoen()); 73 });
68
69 w.set_lseon(reg.lseon());
70
71 #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))]
72 w.set_lsedrv(reg.lsedrv());
73 w.set_lsebyp(reg.lsebyp());
74 });
75 }
76 } 74 }
77 75
78 self.write(true, |rtc| unsafe { 76 self.write(true, |rtc| {
79 rtc.cr().modify(|w| { 77 rtc.cr().modify(|w| {
80 #[cfg(rtc_v2f2)] 78 #[cfg(rtc_v2f2)]
81 w.set_fmt(false); 79 w.set_fmt(false);
@@ -117,47 +115,45 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
117 clock_drift = clock_drift / RTC_CALR_RESOLUTION_PPM; 115 clock_drift = clock_drift / RTC_CALR_RESOLUTION_PPM;
118 116
119 self.write(false, |rtc| { 117 self.write(false, |rtc| {
120 unsafe { 118 rtc.calr().write(|w| {
121 rtc.calr().write(|w| { 119 match period {
122 match period { 120 super::RtcCalibrationCyclePeriod::Seconds8 => {
123 super::RtcCalibrationCyclePeriod::Seconds8 => { 121 w.set_calw8(stm32_metapac::rtc::vals::Calw8::EIGHT_SECOND);
124 w.set_calw8(stm32_metapac::rtc::vals::Calw8::EIGHT_SECOND);
125 }
126 super::RtcCalibrationCyclePeriod::Seconds16 => {
127 w.set_calw16(stm32_metapac::rtc::vals::Calw16::SIXTEEN_SECOND);
128 }
129 super::RtcCalibrationCyclePeriod::Seconds32 => {
130 // Set neither `calw8` nor `calw16` to use 32 seconds
131 }
132 } 122 }
133 123 super::RtcCalibrationCyclePeriod::Seconds16 => {
134 // Extra pulses during calibration cycle period: CALP * 512 - CALM 124 w.set_calw16(stm32_metapac::rtc::vals::Calw16::SIXTEEN_SECOND);
135 // 125 }
136 // CALP sets whether pulses are added or omitted. 126 super::RtcCalibrationCyclePeriod::Seconds32 => {
137 // 127 // Set neither `calw8` nor `calw16` to use 32 seconds
138 // CALM contains how many pulses (out of 512) are masked in a
139 // given calibration cycle period.
140 if clock_drift > 0.0 {
141 // Maximum (about 512.2) rounds to 512.
142 clock_drift += 0.5;
143
144 // When the offset is positive (0 to 512), the opposite of
145 // the offset (512 - offset) is masked, i.e. for the
146 // maximum offset (512), 0 pulses are masked.
147 w.set_calp(stm32_metapac::rtc::vals::Calp::INCREASEFREQ);
148 w.set_calm(512 - clock_drift as u16);
149 } else {
150 // Minimum (about -510.7) rounds to -511.
151 clock_drift -= 0.5;
152
153 // When the offset is negative or zero (-511 to 0),
154 // the absolute offset is masked, i.e. for the minimum
155 // offset (-511), 511 pulses are masked.
156 w.set_calp(stm32_metapac::rtc::vals::Calp::NOCHANGE);
157 w.set_calm((clock_drift * -1.0) as u16);
158 } 128 }
159 }); 129 }
160 } 130
131 // Extra pulses during calibration cycle period: CALP * 512 - CALM
132 //
133 // CALP sets whether pulses are added or omitted.
134 //
135 // CALM contains how many pulses (out of 512) are masked in a
136 // given calibration cycle period.
137 if clock_drift > 0.0 {
138 // Maximum (about 512.2) rounds to 512.
139 clock_drift += 0.5;
140
141 // When the offset is positive (0 to 512), the opposite of
142 // the offset (512 - offset) is masked, i.e. for the
143 // maximum offset (512), 0 pulses are masked.
144 w.set_calp(stm32_metapac::rtc::vals::Calp::INCREASEFREQ);
145 w.set_calm(512 - clock_drift as u16);
146 } else {
147 // Minimum (about -510.7) rounds to -511.
148 clock_drift -= 0.5;
149
150 // When the offset is negative or zero (-511 to 0),
151 // the absolute offset is masked, i.e. for the minimum
152 // offset (-511), 511 pulses are masked.
153 w.set_calp(stm32_metapac::rtc::vals::Calp::NOCHANGE);
154 w.set_calm((clock_drift * -1.0) as u16);
155 }
156 });
161 }) 157 })
162 } 158 }
163 159
@@ -168,31 +164,27 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
168 let r = T::regs(); 164 let r = T::regs();
169 // Disable write protection. 165 // Disable write protection.
170 // This is safe, as we're only writin the correct and expected values. 166 // This is safe, as we're only writin the correct and expected values.
171 unsafe { 167 r.wpr().write(|w| w.set_key(0xca));
172 r.wpr().write(|w| w.set_key(0xca)); 168 r.wpr().write(|w| w.set_key(0x53));
173 r.wpr().write(|w| w.set_key(0x53)); 169
174 170 // true if initf bit indicates RTC peripheral is in init mode
175 // true if initf bit indicates RTC peripheral is in init mode 171 if init_mode && !r.isr().read().initf() {
176 if init_mode && !r.isr().read().initf() { 172 // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode
177 // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode 173 r.isr().modify(|w| w.set_init(Init::INITMODE));
178 r.isr().modify(|w| w.set_init(Init::INITMODE)); 174 // wait till init state entered
179 // wait till init state entered 175 // ~2 RTCCLK cycles
180 // ~2 RTCCLK cycles 176 while !r.isr().read().initf() {}
181 while !r.isr().read().initf() {}
182 }
183 } 177 }
184 178
185 let result = f(&r); 179 let result = f(&r);
186 180
187 unsafe { 181 if init_mode {
188 if init_mode { 182 r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode
189 r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode
190 }
191
192 // Re-enable write protection.
193 // This is safe, as the field accepts the full range of 8-bit values.
194 r.wpr().write(|w| w.set_key(0xff));
195 } 183 }
184
185 // Re-enable write protection.
186 // This is safe, as the field accepts the full range of 8-bit values.
187 r.wpr().write(|w| w.set_key(0xff));
196 result 188 result
197 } 189 }
198} 190}
@@ -200,7 +192,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
200impl sealed::Instance for crate::peripherals::RTC { 192impl sealed::Instance for crate::peripherals::RTC {
201 const BACKUP_REGISTER_COUNT: usize = 20; 193 const BACKUP_REGISTER_COUNT: usize = 20;
202 194
203 unsafe fn enable_peripheral_clk() { 195 fn enable_peripheral_clk() {
204 #[cfg(any(rtc_v2l4, rtc_v2wb))] 196 #[cfg(any(rtc_v2l4, rtc_v2wb))]
205 { 197 {
206 // enable peripheral clock for communication 198 // enable peripheral clock for communication
@@ -213,7 +205,7 @@ impl sealed::Instance for crate::peripherals::RTC {
213 205
214 fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> { 206 fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> {
215 if register < Self::BACKUP_REGISTER_COUNT { 207 if register < Self::BACKUP_REGISTER_COUNT {
216 Some(unsafe { rtc.bkpr(register).read().bkp() }) 208 Some(rtc.bkpr(register).read().bkp())
217 } else { 209 } else {
218 None 210 None
219 } 211 }
@@ -221,7 +213,7 @@ impl sealed::Instance for crate::peripherals::RTC {
221 213
222 fn write_backup_register(rtc: &Rtc, register: usize, value: u32) { 214 fn write_backup_register(rtc: &Rtc, register: usize, value: u32) {
223 if register < Self::BACKUP_REGISTER_COUNT { 215 if register < Self::BACKUP_REGISTER_COUNT {
224 unsafe { rtc.bkpr(register).write(|w| w.set_bkp(value)) } 216 rtc.bkpr(register).write(|w| w.set_bkp(value));
225 } 217 }
226 } 218 }
227} 219}
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs
index 24f6496a6..7c91046a2 100644
--- a/embassy-stm32/src/rtc/v3.rs
+++ b/embassy-stm32/src/rtc/v3.rs
@@ -8,70 +8,66 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
8 /// It this changes the RTC clock source the time will be reset 8 /// It this changes the RTC clock source the time will be reset
9 pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { 9 pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) {
10 // Unlock the backup domain 10 // Unlock the backup domain
11 unsafe { 11 #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))]
12 #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] 12 {
13 { 13 crate::pac::PWR.cr1().modify(|w| w.set_dbp(true));
14 crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); 14 while !crate::pac::PWR.cr1().read().dbp() {}
15 while !crate::pac::PWR.cr1().read().dbp() {} 15 }
16 } 16 #[cfg(any(rcc_wl5, rcc_wle))]
17 #[cfg(any(rcc_wl5, rcc_wle))] 17 {
18 { 18 use crate::pac::pwr::vals::Dbp;
19 use crate::pac::pwr::vals::Dbp; 19
20 20 crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED));
21 crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); 21 while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {}
22 while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} 22 }
23 } 23
24 24 let reg = crate::pac::RCC.bdcr().read();
25 let reg = crate::pac::RCC.bdcr().read(); 25 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
26 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); 26
27 27 let config_rtcsel = rtc_config.clock_config as u8;
28 let config_rtcsel = rtc_config.clock_config as u8; 28 #[cfg(not(any(rcc_wl5, rcc_wle)))]
29 #[cfg(not(any(rcc_wl5, rcc_wle)))] 29 let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel);
30 let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel); 30
31 31 if !reg.rtcen() || reg.rtcsel() != config_rtcsel {
32 if !reg.rtcen() || reg.rtcsel() != config_rtcsel { 32 crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true));
33 crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); 33
34 34 crate::pac::RCC.bdcr().modify(|w| {
35 crate::pac::RCC.bdcr().modify(|w| { 35 // Reset
36 // Reset 36 w.set_bdrst(false);
37 w.set_bdrst(false); 37
38 38 // Select RTC source
39 // Select RTC source 39 w.set_rtcsel(config_rtcsel);
40 w.set_rtcsel(config_rtcsel); 40
41 41 w.set_rtcen(true);
42 w.set_rtcen(true); 42
43 43 // Restore bcdr
44 // Restore bcdr 44 w.set_lscosel(reg.lscosel());
45 w.set_lscosel(reg.lscosel()); 45 w.set_lscoen(reg.lscoen());
46 w.set_lscoen(reg.lscoen()); 46
47 47 w.set_lseon(reg.lseon());
48 w.set_lseon(reg.lseon()); 48 w.set_lsedrv(reg.lsedrv());
49 w.set_lsedrv(reg.lsedrv()); 49 w.set_lsebyp(reg.lsebyp());
50 w.set_lsebyp(reg.lsebyp()); 50 });
51 });
52 }
53 } 51 }
54 52
55 self.write(true, |rtc| { 53 self.write(true, |rtc| {
56 unsafe { 54 rtc.cr().modify(|w| {
57 rtc.cr().modify(|w| { 55 w.set_fmt(Fmt::TWENTYFOURHOUR);
58 w.set_fmt(Fmt::TWENTYFOURHOUR); 56 w.set_osel(Osel::DISABLED);
59 w.set_osel(Osel::DISABLED); 57 w.set_pol(Pol::HIGH);
60 w.set_pol(Pol::HIGH); 58 });
61 }); 59
62 60 rtc.prer().modify(|w| {
63 rtc.prer().modify(|w| { 61 w.set_prediv_s(rtc_config.sync_prescaler);
64 w.set_prediv_s(rtc_config.sync_prescaler); 62 w.set_prediv_a(rtc_config.async_prescaler);
65 w.set_prediv_a(rtc_config.async_prescaler); 63 });
66 }); 64
67 65 // TODO: configuration for output pins
68 // TODO: configuration for output pins 66 rtc.cr().modify(|w| {
69 rtc.cr().modify(|w| { 67 w.set_out2en(false);
70 w.set_out2en(false); 68 w.set_tampalrm_type(TampalrmType::PUSHPULL);
71 w.set_tampalrm_type(TampalrmType::PUSHPULL); 69 w.set_tampalrm_pu(TampalrmPu::NOPULLUP);
72 w.set_tampalrm_pu(TampalrmPu::NOPULLUP); 70 });
73 });
74 }
75 }); 71 });
76 72
77 self.rtc_config = rtc_config; 73 self.rtc_config = rtc_config;
@@ -99,47 +95,45 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
99 clock_drift = clock_drift / Self::RTC_CALR_RESOLUTION_PPM; 95 clock_drift = clock_drift / Self::RTC_CALR_RESOLUTION_PPM;
100 96
101 self.write(false, |rtc| { 97 self.write(false, |rtc| {
102 unsafe { 98 rtc.calr().write(|w| {
103 rtc.calr().write(|w| { 99 match period {
104 match period { 100 RtcCalibrationCyclePeriod::Seconds8 => {
105 RtcCalibrationCyclePeriod::Seconds8 => { 101 w.set_calw8(Calw8::EIGHTSECONDS);
106 w.set_calw8(Calw8::EIGHTSECONDS);
107 }
108 RtcCalibrationCyclePeriod::Seconds16 => {
109 w.set_calw16(Calw16::SIXTEENSECONDS);
110 }
111 RtcCalibrationCyclePeriod::Seconds32 => {
112 // Set neither `calw8` nor `calw16` to use 32 seconds
113 }
114 } 102 }
115 103 RtcCalibrationCyclePeriod::Seconds16 => {
116 // Extra pulses during calibration cycle period: CALP * 512 - CALM 104 w.set_calw16(Calw16::SIXTEENSECONDS);
117 //
118 // CALP sets whether pulses are added or omitted.
119 //
120 // CALM contains how many pulses (out of 512) are masked in a
121 // given calibration cycle period.
122 if clock_drift > 0.0 {
123 // Maximum (about 512.2) rounds to 512.
124 clock_drift += 0.5;
125
126 // When the offset is positive (0 to 512), the opposite of
127 // the offset (512 - offset) is masked, i.e. for the
128 // maximum offset (512), 0 pulses are masked.
129 w.set_calp(Calp::INCREASEFREQ);
130 w.set_calm(512 - clock_drift as u16);
131 } else {
132 // Minimum (about -510.7) rounds to -511.
133 clock_drift -= 0.5;
134
135 // When the offset is negative or zero (-511 to 0),
136 // the absolute offset is masked, i.e. for the minimum
137 // offset (-511), 511 pulses are masked.
138 w.set_calp(Calp::NOCHANGE);
139 w.set_calm((clock_drift * -1.0) as u16);
140 } 105 }
141 }); 106 RtcCalibrationCyclePeriod::Seconds32 => {
142 } 107 // Set neither `calw8` nor `calw16` to use 32 seconds
108 }
109 }
110
111 // Extra pulses during calibration cycle period: CALP * 512 - CALM
112 //
113 // CALP sets whether pulses are added or omitted.
114 //
115 // CALM contains how many pulses (out of 512) are masked in a
116 // given calibration cycle period.
117 if clock_drift > 0.0 {
118 // Maximum (about 512.2) rounds to 512.
119 clock_drift += 0.5;
120
121 // When the offset is positive (0 to 512), the opposite of
122 // the offset (512 - offset) is masked, i.e. for the
123 // maximum offset (512), 0 pulses are masked.
124 w.set_calp(Calp::INCREASEFREQ);
125 w.set_calm(512 - clock_drift as u16);
126 } else {
127 // Minimum (about -510.7) rounds to -511.
128 clock_drift -= 0.5;
129
130 // When the offset is negative or zero (-511 to 0),
131 // the absolute offset is masked, i.e. for the minimum
132 // offset (-511), 511 pulses are masked.
133 w.set_calp(Calp::NOCHANGE);
134 w.set_calm((clock_drift * -1.0) as u16);
135 }
136 });
143 }) 137 })
144 } 138 }
145 139
@@ -150,29 +144,26 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
150 let r = T::regs(); 144 let r = T::regs();
151 // Disable write protection. 145 // Disable write protection.
152 // This is safe, as we're only writin the correct and expected values. 146 // This is safe, as we're only writin the correct and expected values.
153 unsafe { 147 r.wpr().write(|w| w.set_key(Key::DEACTIVATE1));
154 r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); 148 r.wpr().write(|w| w.set_key(Key::DEACTIVATE2));
155 r.wpr().write(|w| w.set_key(Key::DEACTIVATE2)); 149
156 150 if init_mode && !r.icsr().read().initf() {
157 if init_mode && !r.icsr().read().initf() { 151 r.icsr().modify(|w| w.set_init(Init::INITMODE));
158 r.icsr().modify(|w| w.set_init(Init::INITMODE)); 152 // wait till init state entered
159 // wait till init state entered 153 // ~2 RTCCLK cycles
160 // ~2 RTCCLK cycles 154 while !r.icsr().read().initf() {}
161 while !r.icsr().read().initf() {}
162 }
163 } 155 }
164 156
165 let result = f(&r); 157 let result = f(&r);
166 158
167 unsafe { 159 if init_mode {
168 if init_mode { 160 r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode
169 r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode
170 }
171
172 // Re-enable write protection.
173 // This is safe, as the field accepts the full range of 8-bit values.
174 r.wpr().write(|w| w.set_key(Key::ACTIVATE));
175 } 161 }
162
163 // Re-enable write protection.
164 // This is safe, as the field accepts the full range of 8-bit values.
165 r.wpr().write(|w| w.set_key(Key::ACTIVATE));
166
176 result 167 result
177 } 168 }
178} 169}
@@ -192,7 +183,7 @@ impl sealed::Instance for crate::peripherals::RTC {
192 fn write_backup_register(_rtc: &Rtc, register: usize, _value: u32) { 183 fn write_backup_register(_rtc: &Rtc, register: usize, _value: u32) {
193 if register < Self::BACKUP_REGISTER_COUNT { 184 if register < Self::BACKUP_REGISTER_COUNT {
194 // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC 185 // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC
195 //unsafe { self.rtc.bkpr()[register].write(|w| w.bits(value)) } 186 //self.rtc.bkpr()[register].write(|w| w.bits(value))
196 } 187 }
197 } 188 }
198} 189}
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 28eb49ab6..80a336a48 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -28,17 +28,14 @@ pub struct InterruptHandler<T: Instance> {
28impl<T: Instance> InterruptHandler<T> { 28impl<T: Instance> InterruptHandler<T> {
29 fn data_interrupts(enable: bool) { 29 fn data_interrupts(enable: bool) {
30 let regs = T::regs(); 30 let regs = T::regs();
31 // NOTE(unsafe) Atomic write 31 regs.maskr().write(|w| {
32 unsafe { 32 w.set_dcrcfailie(enable);
33 regs.maskr().write(|w| { 33 w.set_dtimeoutie(enable);
34 w.set_dcrcfailie(enable); 34 w.set_dataendie(enable);
35 w.set_dtimeoutie(enable);
36 w.set_dataendie(enable);
37 35
38 #[cfg(sdmmc_v2)] 36 #[cfg(sdmmc_v2)]
39 w.set_dabortie(enable); 37 w.set_dabortie(enable);
40 }); 38 });
41 }
42 } 39 }
43} 40}
44 41
@@ -285,7 +282,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
285 ) -> Self { 282 ) -> Self {
286 into_ref!(clk, cmd, d0); 283 into_ref!(clk, cmd, d0);
287 284
288 critical_section::with(|_| unsafe { 285 critical_section::with(|_| {
289 clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); 286 clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None);
290 cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); 287 cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up);
291 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); 288 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up);
@@ -322,7 +319,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
322 ) -> Self { 319 ) -> Self {
323 into_ref!(clk, cmd, d0, d1, d2, d3); 320 into_ref!(clk, cmd, d0, d1, d2, d3);
324 321
325 critical_section::with(|_| unsafe { 322 critical_section::with(|_| {
326 clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); 323 clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None);
327 cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); 324 cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up);
328 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); 325 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up);
@@ -364,7 +361,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
364 ) -> Self { 361 ) -> Self {
365 into_ref!(clk, cmd, d0); 362 into_ref!(clk, cmd, d0);
366 363
367 critical_section::with(|_| unsafe { 364 critical_section::with(|_| {
368 clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); 365 clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None);
369 cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); 366 cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up);
370 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); 367 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up);
@@ -400,7 +397,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
400 ) -> Self { 397 ) -> Self {
401 into_ref!(clk, cmd, d0, d1, d2, d3); 398 into_ref!(clk, cmd, d0, d1, d2, d3);
402 399
403 critical_section::with(|_| unsafe { 400 critical_section::with(|_| {
404 clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); 401 clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None);
405 cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); 402 cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up);
406 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); 403 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up);
@@ -451,26 +448,24 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
451 unsafe { T::Interrupt::enable() }; 448 unsafe { T::Interrupt::enable() };
452 449
453 let regs = T::regs(); 450 let regs = T::regs();
454 unsafe { 451 regs.clkcr().write(|w| {
455 regs.clkcr().write(|w| { 452 w.set_pwrsav(false);
456 w.set_pwrsav(false); 453 w.set_negedge(false);
457 w.set_negedge(false);
458
459 // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors.
460 // See chip erratas for more details.
461 #[cfg(sdmmc_v1)]
462 w.set_hwfc_en(false);
463 #[cfg(sdmmc_v2)]
464 w.set_hwfc_en(true);
465 454
466 #[cfg(sdmmc_v1)] 455 // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors.
467 w.set_clken(true); 456 // See chip erratas for more details.
468 }); 457 #[cfg(sdmmc_v1)]
458 w.set_hwfc_en(false);
459 #[cfg(sdmmc_v2)]
460 w.set_hwfc_en(true);
469 461
470 // Power off, writen 00: Clock to the card is stopped; 462 #[cfg(sdmmc_v1)]
471 // D[7:0], CMD, and CK are driven high. 463 w.set_clken(true);
472 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); 464 });
473 } 465
466 // Power off, writen 00: Clock to the card is stopped;
467 // D[7:0], CMD, and CK are driven high.
468 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8));
474 469
475 Self { 470 Self {
476 _peri: sdmmc, 471 _peri: sdmmc,
@@ -495,14 +490,11 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
495 fn data_active() -> bool { 490 fn data_active() -> bool {
496 let regs = T::regs(); 491 let regs = T::regs();
497 492
498 // NOTE(unsafe) Atomic read with no side-effects 493 let status = regs.star().read();
499 unsafe { 494 #[cfg(sdmmc_v1)]
500 let status = regs.star().read(); 495 return status.rxact() || status.txact();
501 #[cfg(sdmmc_v1)] 496 #[cfg(sdmmc_v2)]
502 return status.rxact() || status.txact(); 497 return status.dpsmact();
503 #[cfg(sdmmc_v2)]
504 return status.dpsmact();
505 }
506 } 498 }
507 499
508 /// Coammand transfer is in progress 500 /// Coammand transfer is in progress
@@ -510,14 +502,11 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
510 fn cmd_active() -> bool { 502 fn cmd_active() -> bool {
511 let regs = T::regs(); 503 let regs = T::regs();
512 504
513 // NOTE(unsafe) Atomic read with no side-effects 505 let status = regs.star().read();
514 unsafe { 506 #[cfg(sdmmc_v1)]
515 let status = regs.star().read(); 507 return status.cmdact();
516 #[cfg(sdmmc_v1)] 508 #[cfg(sdmmc_v2)]
517 return status.cmdact(); 509 return status.cpsmact();
518 #[cfg(sdmmc_v2)]
519 return status.cpsmact();
520 }
521 } 510 }
522 511
523 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) 512 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
@@ -542,44 +531,41 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
542 Self::wait_idle(); 531 Self::wait_idle();
543 Self::clear_interrupt_flags(); 532 Self::clear_interrupt_flags();
544 533
545 // NOTE(unsafe) We have exclusive access to the regisers 534 regs.dtimer()
546 unsafe { 535 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
547 regs.dtimer() 536 regs.dlenr().write(|w| w.set_datalength(length_bytes));
548 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
549 regs.dlenr().write(|w| w.set_datalength(length_bytes));
550 537
551 #[cfg(sdmmc_v1)] 538 #[cfg(sdmmc_v1)]
552 let transfer = { 539 let transfer = unsafe {
553 let request = self.dma.request(); 540 let request = self.dma.request();
554 Transfer::new_read( 541 Transfer::new_read(
555 &mut self.dma, 542 &mut self.dma,
556 request, 543 request,
557 regs.fifor().ptr() as *mut u32, 544 regs.fifor().as_ptr() as *mut u32,
558 buffer, 545 buffer,
559 DMA_TRANSFER_OPTIONS, 546 DMA_TRANSFER_OPTIONS,
560 ) 547 )
561 }; 548 };
562 #[cfg(sdmmc_v2)] 549 #[cfg(sdmmc_v2)]
563 let transfer = { 550 let transfer = {
564 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); 551 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32));
565 regs.idmactrlr().modify(|w| w.set_idmaen(true)); 552 regs.idmactrlr().modify(|w| w.set_idmaen(true));
566 Transfer { 553 Transfer {
567 _dummy: core::marker::PhantomData, 554 _dummy: core::marker::PhantomData,
568 } 555 }
569 }; 556 };
570 557
571 regs.dctrl().modify(|w| { 558 regs.dctrl().modify(|w| {
572 w.set_dblocksize(block_size); 559 w.set_dblocksize(block_size);
573 w.set_dtdir(true); 560 w.set_dtdir(true);
574 #[cfg(sdmmc_v1)] 561 #[cfg(sdmmc_v1)]
575 { 562 {
576 w.set_dmaen(true); 563 w.set_dmaen(true);
577 w.set_dten(true); 564 w.set_dten(true);
578 } 565 }
579 }); 566 });
580 567
581 transfer 568 transfer
582 }
583 } 569 }
584 570
585 /// # Safety 571 /// # Safety
@@ -598,59 +584,54 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
598 Self::wait_idle(); 584 Self::wait_idle();
599 Self::clear_interrupt_flags(); 585 Self::clear_interrupt_flags();
600 586
601 // NOTE(unsafe) We have exclusive access to the regisers 587 regs.dtimer()
602 unsafe { 588 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
603 regs.dtimer() 589 regs.dlenr().write(|w| w.set_datalength(length_bytes));
604 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
605 regs.dlenr().write(|w| w.set_datalength(length_bytes));
606 590
607 #[cfg(sdmmc_v1)] 591 #[cfg(sdmmc_v1)]
608 let transfer = { 592 let transfer = unsafe {
609 let request = self.dma.request(); 593 let request = self.dma.request();
610 Transfer::new_write( 594 Transfer::new_write(
611 &mut self.dma, 595 &mut self.dma,
612 request, 596 request,
613 buffer, 597 buffer,
614 regs.fifor().ptr() as *mut u32, 598 regs.fifor().as_ptr() as *mut u32,
615 DMA_TRANSFER_OPTIONS, 599 DMA_TRANSFER_OPTIONS,
616 ) 600 )
617 }; 601 };
618 #[cfg(sdmmc_v2)] 602 #[cfg(sdmmc_v2)]
619 let transfer = { 603 let transfer = {
620 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32)); 604 regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32));
621 regs.idmactrlr().modify(|w| w.set_idmaen(true)); 605 regs.idmactrlr().modify(|w| w.set_idmaen(true));
622 Transfer { 606 Transfer {
623 _dummy: core::marker::PhantomData, 607 _dummy: core::marker::PhantomData,
624 } 608 }
625 }; 609 };
626 610
627 regs.dctrl().modify(|w| { 611 regs.dctrl().modify(|w| {
628 w.set_dblocksize(block_size); 612 w.set_dblocksize(block_size);
629 w.set_dtdir(false); 613 w.set_dtdir(false);
630 #[cfg(sdmmc_v1)] 614 #[cfg(sdmmc_v1)]
631 { 615 {
632 w.set_dmaen(true); 616 w.set_dmaen(true);
633 w.set_dten(true); 617 w.set_dten(true);
634 } 618 }
635 }); 619 });
636 620
637 transfer 621 transfer
638 }
639 } 622 }
640 623
641 /// Stops the DMA datapath 624 /// Stops the DMA datapath
642 fn stop_datapath() { 625 fn stop_datapath() {
643 let regs = T::regs(); 626 let regs = T::regs();
644 627
645 unsafe { 628 #[cfg(sdmmc_v1)]
646 #[cfg(sdmmc_v1)] 629 regs.dctrl().modify(|w| {
647 regs.dctrl().modify(|w| { 630 w.set_dmaen(false);
648 w.set_dmaen(false); 631 w.set_dten(false);
649 w.set_dten(false); 632 });
650 }); 633 #[cfg(sdmmc_v2)]
651 #[cfg(sdmmc_v2)] 634 regs.idmactrlr().modify(|w| w.set_idmaen(false));
652 regs.idmactrlr().modify(|w| w.set_idmaen(false));
653 }
654 } 635 }
655 636
656 /// Sets the CLKDIV field in CLKCR. Updates clock field in self 637 /// Sets the CLKDIV field in CLKCR. Updates clock field in self
@@ -673,16 +654,13 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
673 assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); 654 assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32);
674 self.clock = new_clock; 655 self.clock = new_clock;
675 656
676 // NOTE(unsafe) We have exclusive access to the regblock 657 // CPSMACT and DPSMACT must be 0 to set CLKDIV
677 unsafe { 658 Self::wait_idle();
678 // CPSMACT and DPSMACT must be 0 to set CLKDIV 659 regs.clkcr().modify(|w| {
679 Self::wait_idle(); 660 w.set_clkdiv(clkdiv);
680 regs.clkcr().modify(|w| { 661 #[cfg(sdmmc_v1)]
681 w.set_clkdiv(clkdiv); 662 w.set_bypass(_bypass);
682 #[cfg(sdmmc_v1)] 663 });
683 w.set_bypass(_bypass);
684 });
685 }
686 664
687 Ok(()) 665 Ok(())
688 } 666 }
@@ -710,7 +688,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
710 688
711 // Arm `OnDrop` after the buffer, so it will be dropped first 689 // Arm `OnDrop` after the buffer, so it will be dropped first
712 let regs = T::regs(); 690 let regs = T::regs();
713 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 691 let on_drop = OnDrop::new(|| Self::on_drop());
714 692
715 let transfer = self.prepare_datapath_read(&mut status, 64, 6); 693 let transfer = self.prepare_datapath_read(&mut status, 64, 6);
716 InterruptHandler::<T>::data_interrupts(true); 694 InterruptHandler::<T>::data_interrupts(true);
@@ -718,7 +696,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
718 696
719 let res = poll_fn(|cx| { 697 let res = poll_fn(|cx| {
720 T::state().register(cx.waker()); 698 T::state().register(cx.waker());
721 let status = unsafe { regs.star().read() }; 699 let status = regs.star().read();
722 700
723 if status.dcrcfail() { 701 if status.dcrcfail() {
724 return Poll::Ready(Err(Error::Crc)); 702 return Poll::Ready(Err(Error::Crc));
@@ -769,8 +747,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
769 747
770 Self::cmd(Cmd::card_status(rca << 16), false)?; // CMD13 748 Self::cmd(Cmd::card_status(rca << 16), false)?; // CMD13
771 749
772 // NOTE(unsafe) Atomic read with no side-effects 750 let r1 = regs.respr(0).read().cardstatus();
773 let r1 = unsafe { regs.respr(0).read().cardstatus() };
774 Ok(r1.into()) 751 Ok(r1.into())
775 } 752 }
776 753
@@ -786,7 +763,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
786 763
787 // Arm `OnDrop` after the buffer, so it will be dropped first 764 // Arm `OnDrop` after the buffer, so it will be dropped first
788 let regs = T::regs(); 765 let regs = T::regs();
789 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 766 let on_drop = OnDrop::new(|| Self::on_drop());
790 767
791 let transfer = self.prepare_datapath_read(&mut status, 64, 6); 768 let transfer = self.prepare_datapath_read(&mut status, 64, 6);
792 InterruptHandler::<T>::data_interrupts(true); 769 InterruptHandler::<T>::data_interrupts(true);
@@ -794,7 +771,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
794 771
795 let res = poll_fn(|cx| { 772 let res = poll_fn(|cx| {
796 T::state().register(cx.waker()); 773 T::state().register(cx.waker());
797 let status = unsafe { regs.star().read() }; 774 let status = regs.star().read();
798 775
799 if status.dcrcfail() { 776 if status.dcrcfail() {
800 return Poll::Ready(Err(Error::Crc)); 777 return Poll::Ready(Err(Error::Crc));
@@ -840,35 +817,32 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
840 #[inline(always)] 817 #[inline(always)]
841 fn clear_interrupt_flags() { 818 fn clear_interrupt_flags() {
842 let regs = T::regs(); 819 let regs = T::regs();
843 // NOTE(unsafe) Atomic write 820 regs.icr().write(|w| {
844 unsafe { 821 w.set_ccrcfailc(true);
845 regs.icr().write(|w| { 822 w.set_dcrcfailc(true);
846 w.set_ccrcfailc(true); 823 w.set_ctimeoutc(true);
847 w.set_dcrcfailc(true); 824 w.set_dtimeoutc(true);
848 w.set_ctimeoutc(true); 825 w.set_txunderrc(true);
849 w.set_dtimeoutc(true); 826 w.set_rxoverrc(true);
850 w.set_txunderrc(true); 827 w.set_cmdrendc(true);
851 w.set_rxoverrc(true); 828 w.set_cmdsentc(true);
852 w.set_cmdrendc(true); 829 w.set_dataendc(true);
853 w.set_cmdsentc(true); 830 w.set_dbckendc(true);
854 w.set_dataendc(true); 831 w.set_sdioitc(true);
855 w.set_dbckendc(true);
856 w.set_sdioitc(true);
857 832
858 #[cfg(sdmmc_v2)] 833 #[cfg(sdmmc_v2)]
859 { 834 {
860 w.set_dholdc(true); 835 w.set_dholdc(true);
861 w.set_dabortc(true); 836 w.set_dabortc(true);
862 w.set_busyd0endc(true); 837 w.set_busyd0endc(true);
863 w.set_ackfailc(true); 838 w.set_ackfailc(true);
864 w.set_acktimeoutc(true); 839 w.set_acktimeoutc(true);
865 w.set_vswendc(true); 840 w.set_vswendc(true);
866 w.set_ckstopc(true); 841 w.set_ckstopc(true);
867 w.set_idmatec(true); 842 w.set_idmatec(true);
868 w.set_idmabtcc(true); 843 w.set_idmabtcc(true);
869 } 844 }
870 }); 845 });
871 }
872 } 846 }
873 847
874 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { 848 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
@@ -880,7 +854,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
880 854
881 // Arm `OnDrop` after the buffer, so it will be dropped first 855 // Arm `OnDrop` after the buffer, so it will be dropped first
882 let regs = T::regs(); 856 let regs = T::regs();
883 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 857 let on_drop = OnDrop::new(|| Self::on_drop());
884 858
885 let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3); 859 let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3);
886 InterruptHandler::<T>::data_interrupts(true); 860 InterruptHandler::<T>::data_interrupts(true);
@@ -888,7 +862,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
888 862
889 let res = poll_fn(|cx| { 863 let res = poll_fn(|cx| {
890 T::state().register(cx.waker()); 864 T::state().register(cx.waker());
891 let status = unsafe { regs.star().read() }; 865 let status = regs.star().read();
892 866
893 if status.dcrcfail() { 867 if status.dcrcfail() {
894 return Poll::Ready(Err(Error::Crc)); 868 return Poll::Ready(Err(Error::Crc));
@@ -921,59 +895,53 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
921 let regs = T::regs(); 895 let regs = T::regs();
922 896
923 Self::clear_interrupt_flags(); 897 Self::clear_interrupt_flags();
924 // NOTE(safety) Atomic operations 898 // CP state machine must be idle
925 unsafe { 899 while Self::cmd_active() {}
926 // CP state machine must be idle
927 while Self::cmd_active() {}
928 900
929 // Command arg 901 // Command arg
930 regs.argr().write(|w| w.set_cmdarg(cmd.arg)); 902 regs.argr().write(|w| w.set_cmdarg(cmd.arg));
931
932 // Command index and start CP State Machine
933 regs.cmdr().write(|w| {
934 w.set_waitint(false);
935 w.set_waitresp(cmd.resp as u8);
936 w.set_cmdindex(cmd.cmd);
937 w.set_cpsmen(true);
938 903
939 #[cfg(sdmmc_v2)] 904 // Command index and start CP State Machine
940 { 905 regs.cmdr().write(|w| {
941 // Special mode in CP State Machine 906 w.set_waitint(false);
942 // CMD12: Stop Transmission 907 w.set_waitresp(cmd.resp as u8);
943 let cpsm_stop_transmission = cmd.cmd == 12; 908 w.set_cmdindex(cmd.cmd);
944 w.set_cmdstop(cpsm_stop_transmission); 909 w.set_cpsmen(true);
945 w.set_cmdtrans(data);
946 }
947 });
948 910
949 let mut status; 911 #[cfg(sdmmc_v2)]
950 if cmd.resp == Response::None { 912 {
951 // Wait for CMDSENT or a timeout 913 // Special mode in CP State Machine
952 while { 914 // CMD12: Stop Transmission
953 status = regs.star().read(); 915 let cpsm_stop_transmission = cmd.cmd == 12;
954 !(status.ctimeout() || status.cmdsent()) 916 w.set_cmdstop(cpsm_stop_transmission);
955 } {} 917 w.set_cmdtrans(data);
956 } else {
957 // Wait for CMDREND or CCRCFAIL or a timeout
958 while {
959 status = regs.star().read();
960 !(status.ctimeout() || status.cmdrend() || status.ccrcfail())
961 } {}
962 } 918 }
919 });
963 920
964 if status.ctimeout() { 921 let mut status;
965 return Err(Error::Timeout); 922 if cmd.resp == Response::None {
966 } else if status.ccrcfail() { 923 // Wait for CMDSENT or a timeout
967 return Err(Error::Crc); 924 while {
968 } 925 status = regs.star().read();
969 Ok(()) 926 !(status.ctimeout() || status.cmdsent())
927 } {}
928 } else {
929 // Wait for CMDREND or CCRCFAIL or a timeout
930 while {
931 status = regs.star().read();
932 !(status.ctimeout() || status.cmdrend() || status.ccrcfail())
933 } {}
934 }
935
936 if status.ctimeout() {
937 return Err(Error::Timeout);
938 } else if status.ccrcfail() {
939 return Err(Error::Crc);
970 } 940 }
941 Ok(())
971 } 942 }
972 943
973 /// # Safety 944 fn on_drop() {
974 ///
975 /// Ensure that `regs` has exclusive access to the regblocks
976 unsafe fn on_drop() {
977 let regs = T::regs(); 945 let regs = T::regs();
978 if Self::data_active() { 946 if Self::data_active() {
979 Self::clear_interrupt_flags(); 947 Self::clear_interrupt_flags();
@@ -1017,141 +985,138 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1017 false => BusWidth::One, 985 false => BusWidth::One,
1018 }; 986 };
1019 987
1020 // NOTE(unsafe) We have exclusive access to the peripheral 988 // While the SD/SDIO card or eMMC is in identification mode,
1021 unsafe { 989 // the SDMMC_CK frequency must be no more than 400 kHz.
1022 // While the SD/SDIO card or eMMC is in identification mode, 990 let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
1023 // the SDMMC_CK frequency must be no more than 400 kHz. 991 self.clock = init_clock;
1024 let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0));
1025 self.clock = init_clock;
1026
1027 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1028 Self::wait_idle();
1029
1030 regs.clkcr().modify(|w| {
1031 w.set_widbus(0);
1032 w.set_clkdiv(clkdiv);
1033 #[cfg(sdmmc_v1)]
1034 w.set_bypass(_bypass);
1035 });
1036 992
1037 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); 993 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1038 Self::cmd(Cmd::idle(), false)?; 994 Self::wait_idle();
1039 995
1040 // Check if cards supports CMD8 (with pattern) 996 regs.clkcr().modify(|w| {
1041 Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?; 997 w.set_widbus(0);
1042 let r1 = regs.respr(0).read().cardstatus(); 998 w.set_clkdiv(clkdiv);
999 #[cfg(sdmmc_v1)]
1000 w.set_bypass(_bypass);
1001 });
1043 1002
1044 let mut card = if r1 == 0x1AA { 1003 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1045 // Card echoed back the pattern. Must be at least v2 1004 Self::cmd(Cmd::idle(), false)?;
1046 Card::default()
1047 } else {
1048 return Err(Error::UnsupportedCardVersion);
1049 };
1050 1005
1051 let ocr = loop { 1006 // Check if cards supports CMD8 (with pattern)
1052 // Signal that next command is a app command 1007 Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?;
1053 Self::cmd(Cmd::app_cmd(0), false)?; // CMD55 1008 let r1 = regs.respr(0).read().cardstatus();
1054 1009
1055 let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32 1010 let mut card = if r1 == 0x1AA {
1056 | CmdAppOper::HIGH_CAPACITY as u32 1011 // Card echoed back the pattern. Must be at least v2
1057 | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32; 1012 Card::default()
1013 } else {
1014 return Err(Error::UnsupportedCardVersion);
1015 };
1058 1016
1059 // Initialize card 1017 let ocr = loop {
1060 match Self::cmd(Cmd::app_op_cmd(arg), false) { 1018 // Signal that next command is a app command
1061 // ACMD41 1019 Self::cmd(Cmd::app_cmd(0), false)?; // CMD55
1062 Ok(_) => (),
1063 Err(Error::Crc) => (),
1064 Err(err) => return Err(err),
1065 }
1066 let ocr: OCR = regs.respr(0).read().cardstatus().into();
1067 if !ocr.is_busy() {
1068 // Power up done
1069 break ocr;
1070 }
1071 };
1072 1020
1073 if ocr.high_capacity() { 1021 let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32
1074 // Card is SDHC or SDXC or SDUC 1022 | CmdAppOper::HIGH_CAPACITY as u32
1075 card.card_type = CardCapacity::SDHC; 1023 | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32;
1076 } else {
1077 card.card_type = CardCapacity::SDSC;
1078 }
1079 card.ocr = ocr;
1080
1081 Self::cmd(Cmd::all_send_cid(), false)?; // CMD2
1082 let cid0 = regs.respr(0).read().cardstatus() as u128;
1083 let cid1 = regs.respr(1).read().cardstatus() as u128;
1084 let cid2 = regs.respr(2).read().cardstatus() as u128;
1085 let cid3 = regs.respr(3).read().cardstatus() as u128;
1086 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1087 card.cid = cid.into();
1088
1089 Self::cmd(Cmd::send_rel_addr(), false)?;
1090 card.rca = regs.respr(0).read().cardstatus() >> 16;
1091
1092 Self::cmd(Cmd::send_csd(card.rca << 16), false)?;
1093 let csd0 = regs.respr(0).read().cardstatus() as u128;
1094 let csd1 = regs.respr(1).read().cardstatus() as u128;
1095 let csd2 = regs.respr(2).read().cardstatus() as u128;
1096 let csd3 = regs.respr(3).read().cardstatus() as u128;
1097 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1098 card.csd = csd.into();
1099
1100 self.select_card(Some(&card))?;
1101
1102 self.get_scr(&mut card).await?;
1103
1104 // Set bus width
1105 let (width, acmd_arg) = match bus_width {
1106 BusWidth::Eight => unimplemented!(),
1107 BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2),
1108 _ => (BusWidth::One, 0),
1109 };
1110 Self::cmd(Cmd::app_cmd(card.rca << 16), false)?;
1111 Self::cmd(Cmd::cmd6(acmd_arg), false)?;
1112
1113 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1114 Self::wait_idle();
1115
1116 regs.clkcr().modify(|w| {
1117 w.set_widbus(match width {
1118 BusWidth::One => 0,
1119 BusWidth::Four => 1,
1120 BusWidth::Eight => 2,
1121 _ => panic!("Invalid Bus Width"),
1122 })
1123 });
1124 1024
1125 // Set Clock 1025 // Initialize card
1126 if freq.0 <= 25_000_000 { 1026 match Self::cmd(Cmd::app_op_cmd(arg), false) {
1127 // Final clock frequency 1027 // ACMD41
1128 self.clkcr_set_clkdiv(freq.0, width)?; 1028 Ok(_) => (),
1129 } else { 1029 Err(Error::Crc) => (),
1130 // Switch to max clock for SDR12 1030 Err(err) => return Err(err),
1131 self.clkcr_set_clkdiv(25_000_000, width)?;
1132 } 1031 }
1032 let ocr: OCR = regs.respr(0).read().cardstatus().into();
1033 if !ocr.is_busy() {
1034 // Power up done
1035 break ocr;
1036 }
1037 };
1038
1039 if ocr.high_capacity() {
1040 // Card is SDHC or SDXC or SDUC
1041 card.card_type = CardCapacity::SDHC;
1042 } else {
1043 card.card_type = CardCapacity::SDSC;
1044 }
1045 card.ocr = ocr;
1046
1047 Self::cmd(Cmd::all_send_cid(), false)?; // CMD2
1048 let cid0 = regs.respr(0).read().cardstatus() as u128;
1049 let cid1 = regs.respr(1).read().cardstatus() as u128;
1050 let cid2 = regs.respr(2).read().cardstatus() as u128;
1051 let cid3 = regs.respr(3).read().cardstatus() as u128;
1052 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1053 card.cid = cid.into();
1054
1055 Self::cmd(Cmd::send_rel_addr(), false)?;
1056 card.rca = regs.respr(0).read().cardstatus() >> 16;
1057
1058 Self::cmd(Cmd::send_csd(card.rca << 16), false)?;
1059 let csd0 = regs.respr(0).read().cardstatus() as u128;
1060 let csd1 = regs.respr(1).read().cardstatus() as u128;
1061 let csd2 = regs.respr(2).read().cardstatus() as u128;
1062 let csd3 = regs.respr(3).read().cardstatus() as u128;
1063 let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3);
1064 card.csd = csd.into();
1065
1066 self.select_card(Some(&card))?;
1067
1068 self.get_scr(&mut card).await?;
1069
1070 // Set bus width
1071 let (width, acmd_arg) = match bus_width {
1072 BusWidth::Eight => unimplemented!(),
1073 BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2),
1074 _ => (BusWidth::One, 0),
1075 };
1076 Self::cmd(Cmd::app_cmd(card.rca << 16), false)?;
1077 Self::cmd(Cmd::cmd6(acmd_arg), false)?;
1078
1079 // CPSMACT and DPSMACT must be 0 to set WIDBUS
1080 Self::wait_idle();
1133 1081
1134 self.card = Some(card); 1082 regs.clkcr().modify(|w| {
1083 w.set_widbus(match width {
1084 BusWidth::One => 0,
1085 BusWidth::Four => 1,
1086 BusWidth::Eight => 2,
1087 _ => panic!("Invalid Bus Width"),
1088 })
1089 });
1090
1091 // Set Clock
1092 if freq.0 <= 25_000_000 {
1093 // Final clock frequency
1094 self.clkcr_set_clkdiv(freq.0, width)?;
1095 } else {
1096 // Switch to max clock for SDR12
1097 self.clkcr_set_clkdiv(25_000_000, width)?;
1098 }
1135 1099
1136 // Read status 1100 self.card = Some(card);
1137 self.read_sd_status().await?;
1138 1101
1139 if freq.0 > 25_000_000 { 1102 // Read status
1140 // Switch to SDR25 1103 self.read_sd_status().await?;
1141 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?;
1142 1104
1143 if self.signalling == Signalling::SDR25 { 1105 if freq.0 > 25_000_000 {
1144 // Set final clock frequency 1106 // Switch to SDR25
1145 self.clkcr_set_clkdiv(freq.0, width)?; 1107 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?;
1146 1108
1147 if self.read_status(&card)?.state() != CurrentState::Transfer { 1109 if self.signalling == Signalling::SDR25 {
1148 return Err(Error::SignalingSwitchFailed); 1110 // Set final clock frequency
1149 } 1111 self.clkcr_set_clkdiv(freq.0, width)?;
1112
1113 if self.read_status(&card)?.state() != CurrentState::Transfer {
1114 return Err(Error::SignalingSwitchFailed);
1150 } 1115 }
1151 } 1116 }
1152 // Read status after signalling change
1153 self.read_sd_status().await?;
1154 } 1117 }
1118 // Read status after signalling change
1119 self.read_sd_status().await?;
1155 1120
1156 Ok(()) 1121 Ok(())
1157 } 1122 }
@@ -1172,7 +1137,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1172 Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 1137 Self::cmd(Cmd::set_block_length(512), false)?; // CMD16
1173 1138
1174 let regs = T::regs(); 1139 let regs = T::regs();
1175 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 1140 let on_drop = OnDrop::new(|| Self::on_drop());
1176 1141
1177 let transfer = self.prepare_datapath_read(buffer, 512, 9); 1142 let transfer = self.prepare_datapath_read(buffer, 512, 9);
1178 InterruptHandler::<T>::data_interrupts(true); 1143 InterruptHandler::<T>::data_interrupts(true);
@@ -1180,7 +1145,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1180 1145
1181 let res = poll_fn(|cx| { 1146 let res = poll_fn(|cx| {
1182 T::state().register(cx.waker()); 1147 T::state().register(cx.waker());
1183 let status = unsafe { regs.star().read() }; 1148 let status = regs.star().read();
1184 1149
1185 if status.dcrcfail() { 1150 if status.dcrcfail() {
1186 return Poll::Ready(Err(Error::Crc)); 1151 return Poll::Ready(Err(Error::Crc));
@@ -1217,7 +1182,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1217 Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 1182 Self::cmd(Cmd::set_block_length(512), false)?; // CMD16
1218 1183
1219 let regs = T::regs(); 1184 let regs = T::regs();
1220 let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); 1185 let on_drop = OnDrop::new(|| Self::on_drop());
1221 1186
1222 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes 1187 // sdmmc_v1 uses different cmd/dma order than v2, but only for writes
1223 #[cfg(sdmmc_v1)] 1188 #[cfg(sdmmc_v1)]
@@ -1231,7 +1196,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1231 1196
1232 let res = poll_fn(|cx| { 1197 let res = poll_fn(|cx| {
1233 T::state().register(cx.waker()); 1198 T::state().register(cx.waker());
1234 let status = unsafe { regs.star().read() }; 1199 let status = regs.star().read();
1235 1200
1236 if status.dcrcfail() { 1201 if status.dcrcfail() {
1237 return Poll::Ready(Err(Error::Crc)); 1202 return Poll::Ready(Err(Error::Crc));
@@ -1289,9 +1254,9 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1289impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { 1254impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> {
1290 fn drop(&mut self) { 1255 fn drop(&mut self) {
1291 T::Interrupt::disable(); 1256 T::Interrupt::disable();
1292 unsafe { Self::on_drop() }; 1257 Self::on_drop();
1293 1258
1294 critical_section::with(|_| unsafe { 1259 critical_section::with(|_| {
1295 self.clk.set_as_disconnected(); 1260 self.clk.set_as_disconnected();
1296 self.cmd.set_as_disconnected(); 1261 self.cmd.set_as_disconnected();
1297 self.d0.set_as_disconnected(); 1262 self.d0.set_as_disconnected();
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 580971e45..1cddac992 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -98,14 +98,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
98 Polarity::IdleHigh => Pull::Up, 98 Polarity::IdleHigh => Pull::Up,
99 }; 99 };
100 100
101 unsafe { 101 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode);
102 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode); 102 sck.set_speed(crate::gpio::Speed::VeryHigh);
103 sck.set_speed(crate::gpio::Speed::VeryHigh); 103 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
104 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); 104 mosi.set_speed(crate::gpio::Speed::VeryHigh);
105 mosi.set_speed(crate::gpio::Speed::VeryHigh); 105 miso.set_as_af(miso.af_num(), AFType::Input);
106 miso.set_as_af(miso.af_num(), AFType::Input); 106 miso.set_speed(crate::gpio::Speed::VeryHigh);
107 miso.set_speed(crate::gpio::Speed::VeryHigh);
108 }
109 107
110 Self::new_inner( 108 Self::new_inner(
111 peri, 109 peri,
@@ -129,12 +127,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
129 config: Config, 127 config: Config,
130 ) -> Self { 128 ) -> Self {
131 into_ref!(sck, miso); 129 into_ref!(sck, miso);
132 unsafe { 130 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
133 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 131 sck.set_speed(crate::gpio::Speed::VeryHigh);
134 sck.set_speed(crate::gpio::Speed::VeryHigh); 132 miso.set_as_af(miso.af_num(), AFType::Input);
135 miso.set_as_af(miso.af_num(), AFType::Input); 133 miso.set_speed(crate::gpio::Speed::VeryHigh);
136 miso.set_speed(crate::gpio::Speed::VeryHigh);
137 }
138 134
139 Self::new_inner( 135 Self::new_inner(
140 peri, 136 peri,
@@ -158,12 +154,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
158 config: Config, 154 config: Config,
159 ) -> Self { 155 ) -> Self {
160 into_ref!(sck, mosi); 156 into_ref!(sck, mosi);
161 unsafe { 157 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
162 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 158 sck.set_speed(crate::gpio::Speed::VeryHigh);
163 sck.set_speed(crate::gpio::Speed::VeryHigh); 159 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
164 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); 160 mosi.set_speed(crate::gpio::Speed::VeryHigh);
165 mosi.set_speed(crate::gpio::Speed::VeryHigh);
166 }
167 161
168 Self::new_inner( 162 Self::new_inner(
169 peri, 163 peri,
@@ -186,10 +180,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
186 config: Config, 180 config: Config,
187 ) -> Self { 181 ) -> Self {
188 into_ref!(mosi); 182 into_ref!(mosi);
189 unsafe { 183 mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down);
190 mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); 184 mosi.set_speed(crate::gpio::Speed::Medium);
191 mosi.set_speed(crate::gpio::Speed::Medium);
192 }
193 185
194 Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config) 186 Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config)
195 } 187 }
@@ -247,7 +239,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
247 T::reset(); 239 T::reset();
248 240
249 #[cfg(any(spi_v1, spi_f1))] 241 #[cfg(any(spi_v1, spi_f1))]
250 unsafe { 242 {
251 T::REGS.cr2().modify(|w| { 243 T::REGS.cr2().modify(|w| {
252 w.set_ssoe(false); 244 w.set_ssoe(false);
253 }); 245 });
@@ -270,7 +262,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
270 }); 262 });
271 } 263 }
272 #[cfg(spi_v2)] 264 #[cfg(spi_v2)]
273 unsafe { 265 {
274 T::REGS.cr2().modify(|w| { 266 T::REGS.cr2().modify(|w| {
275 let (ds, frxth) = <u8 as sealed::Word>::CONFIG; 267 let (ds, frxth) = <u8 as sealed::Word>::CONFIG;
276 w.set_frxth(frxth); 268 w.set_frxth(frxth);
@@ -292,7 +284,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
292 }); 284 });
293 } 285 }
294 #[cfg(any(spi_v3, spi_v4, spi_v5))] 286 #[cfg(any(spi_v3, spi_v4, spi_v5))]
295 unsafe { 287 {
296 T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff); 288 T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff);
297 T::REGS.cfg2().modify(|w| { 289 T::REGS.cfg2().modify(|w| {
298 //w.set_ssoe(true); 290 //w.set_ssoe(true);
@@ -343,29 +335,25 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
343 let lsbfirst = config.raw_byte_order(); 335 let lsbfirst = config.raw_byte_order();
344 336
345 #[cfg(any(spi_v1, spi_f1, spi_v2))] 337 #[cfg(any(spi_v1, spi_f1, spi_v2))]
346 unsafe { 338 T::REGS.cr1().modify(|w| {
347 T::REGS.cr1().modify(|w| { 339 w.set_cpha(cpha);
348 w.set_cpha(cpha); 340 w.set_cpol(cpol);
349 w.set_cpol(cpol); 341 w.set_lsbfirst(lsbfirst);
350 w.set_lsbfirst(lsbfirst); 342 });
351 });
352 }
353 343
354 #[cfg(any(spi_v3, spi_v4, spi_v5))] 344 #[cfg(any(spi_v3, spi_v4, spi_v5))]
355 unsafe { 345 T::REGS.cfg2().modify(|w| {
356 T::REGS.cfg2().modify(|w| { 346 w.set_cpha(cpha);
357 w.set_cpha(cpha); 347 w.set_cpol(cpol);
358 w.set_cpol(cpol); 348 w.set_lsbfirst(lsbfirst);
359 w.set_lsbfirst(lsbfirst); 349 });
360 });
361 }
362 } 350 }
363 351
364 pub fn get_current_config(&self) -> Config { 352 pub fn get_current_config(&self) -> Config {
365 #[cfg(any(spi_v1, spi_f1, spi_v2))] 353 #[cfg(any(spi_v1, spi_f1, spi_v2))]
366 let cfg = unsafe { T::REGS.cr1().read() }; 354 let cfg = T::REGS.cr1().read();
367 #[cfg(any(spi_v3, spi_v4, spi_v5))] 355 #[cfg(any(spi_v3, spi_v4, spi_v5))]
368 let cfg = unsafe { T::REGS.cfg2().read() }; 356 let cfg = T::REGS.cfg2().read();
369 let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { 357 let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
370 Polarity::IdleLow 358 Polarity::IdleLow
371 } else { 359 } else {
@@ -395,7 +383,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
395 } 383 }
396 384
397 #[cfg(any(spi_v1, spi_f1))] 385 #[cfg(any(spi_v1, spi_f1))]
398 unsafe { 386 {
399 T::REGS.cr1().modify(|reg| { 387 T::REGS.cr1().modify(|reg| {
400 reg.set_spe(false); 388 reg.set_spe(false);
401 reg.set_dff(word_size) 389 reg.set_dff(word_size)
@@ -405,7 +393,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
405 }); 393 });
406 } 394 }
407 #[cfg(spi_v2)] 395 #[cfg(spi_v2)]
408 unsafe { 396 {
409 T::REGS.cr1().modify(|w| { 397 T::REGS.cr1().modify(|w| {
410 w.set_spe(false); 398 w.set_spe(false);
411 }); 399 });
@@ -418,7 +406,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
418 }); 406 });
419 } 407 }
420 #[cfg(any(spi_v3, spi_v4, spi_v5))] 408 #[cfg(any(spi_v3, spi_v4, spi_v5))]
421 unsafe { 409 {
422 T::REGS.cr1().modify(|w| { 410 T::REGS.cr1().modify(|w| {
423 w.set_csusp(true); 411 w.set_csusp(true);
424 }); 412 });
@@ -447,26 +435,22 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
447 } 435 }
448 436
449 self.set_word_size(W::CONFIG); 437 self.set_word_size(W::CONFIG);
450 unsafe { 438 T::REGS.cr1().modify(|w| {
451 T::REGS.cr1().modify(|w| { 439 w.set_spe(false);
452 w.set_spe(false); 440 });
453 });
454 }
455 441
456 let tx_request = self.txdma.request(); 442 let tx_request = self.txdma.request();
457 let tx_dst = T::REGS.tx_ptr(); 443 let tx_dst = T::REGS.tx_ptr();
458 let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) }; 444 let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) };
459 445
460 unsafe { 446 set_txdmaen(T::REGS, true);
461 set_txdmaen(T::REGS, true); 447 T::REGS.cr1().modify(|w| {
462 T::REGS.cr1().modify(|w| { 448 w.set_spe(true);
463 w.set_spe(true); 449 });
464 }); 450 #[cfg(any(spi_v3, spi_v4, spi_v5))]
465 #[cfg(any(spi_v3, spi_v4, spi_v5))] 451 T::REGS.cr1().modify(|w| {
466 T::REGS.cr1().modify(|w| { 452 w.set_cstart(true);
467 w.set_cstart(true); 453 });
468 });
469 }
470 454
471 tx_f.await; 455 tx_f.await;
472 456
@@ -485,11 +469,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
485 } 469 }
486 470
487 self.set_word_size(W::CONFIG); 471 self.set_word_size(W::CONFIG);
488 unsafe { 472 T::REGS.cr1().modify(|w| {
489 T::REGS.cr1().modify(|w| { 473 w.set_spe(false);
490 w.set_spe(false); 474 });
491 });
492 }
493 475
494 // SPIv3 clears rxfifo on SPE=0 476 // SPIv3 clears rxfifo on SPE=0
495 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 477 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
@@ -517,16 +499,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
517 ) 499 )
518 }; 500 };
519 501
520 unsafe { 502 set_txdmaen(T::REGS, true);
521 set_txdmaen(T::REGS, true); 503 T::REGS.cr1().modify(|w| {
522 T::REGS.cr1().modify(|w| { 504 w.set_spe(true);
523 w.set_spe(true); 505 });
524 }); 506 #[cfg(any(spi_v3, spi_v4, spi_v5))]
525 #[cfg(any(spi_v3, spi_v4, spi_v5))] 507 T::REGS.cr1().modify(|w| {
526 T::REGS.cr1().modify(|w| { 508 w.set_cstart(true);
527 w.set_cstart(true); 509 });
528 });
529 }
530 510
531 join(tx_f, rx_f).await; 511 join(tx_f, rx_f).await;
532 512
@@ -548,11 +528,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
548 } 528 }
549 529
550 self.set_word_size(W::CONFIG); 530 self.set_word_size(W::CONFIG);
551 unsafe { 531 T::REGS.cr1().modify(|w| {
552 T::REGS.cr1().modify(|w| { 532 w.set_spe(false);
553 w.set_spe(false); 533 });
554 });
555 }
556 534
557 // SPIv3 clears rxfifo on SPE=0 535 // SPIv3 clears rxfifo on SPE=0
558 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 536 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
@@ -568,16 +546,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
568 let tx_dst = T::REGS.tx_ptr(); 546 let tx_dst = T::REGS.tx_ptr();
569 let tx_f = unsafe { Transfer::new_write_raw(&mut self.txdma, tx_request, write, tx_dst, Default::default()) }; 547 let tx_f = unsafe { Transfer::new_write_raw(&mut self.txdma, tx_request, write, tx_dst, Default::default()) };
570 548
571 unsafe { 549 set_txdmaen(T::REGS, true);
572 set_txdmaen(T::REGS, true); 550 T::REGS.cr1().modify(|w| {
573 T::REGS.cr1().modify(|w| { 551 w.set_spe(true);
574 w.set_spe(true); 552 });
575 }); 553 #[cfg(any(spi_v3, spi_v4, spi_v5))]
576 #[cfg(any(spi_v3, spi_v4, spi_v5))] 554 T::REGS.cr1().modify(|w| {
577 T::REGS.cr1().modify(|w| { 555 w.set_cstart(true);
578 w.set_cstart(true); 556 });
579 });
580 }
581 557
582 join(tx_f, rx_f).await; 558 join(tx_f, rx_f).await;
583 559
@@ -603,7 +579,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
603 } 579 }
604 580
605 pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { 581 pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
606 unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } 582 T::REGS.cr1().modify(|w| w.set_spe(true));
607 flush_rx_fifo(T::REGS); 583 flush_rx_fifo(T::REGS);
608 self.set_word_size(W::CONFIG); 584 self.set_word_size(W::CONFIG);
609 for word in words.iter() { 585 for word in words.iter() {
@@ -613,7 +589,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
613 } 589 }
614 590
615 pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { 591 pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
616 unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } 592 T::REGS.cr1().modify(|w| w.set_spe(true));
617 flush_rx_fifo(T::REGS); 593 flush_rx_fifo(T::REGS);
618 self.set_word_size(W::CONFIG); 594 self.set_word_size(W::CONFIG);
619 for word in words.iter_mut() { 595 for word in words.iter_mut() {
@@ -623,7 +599,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
623 } 599 }
624 600
625 pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { 601 pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
626 unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } 602 T::REGS.cr1().modify(|w| w.set_spe(true));
627 flush_rx_fifo(T::REGS); 603 flush_rx_fifo(T::REGS);
628 self.set_word_size(W::CONFIG); 604 self.set_word_size(W::CONFIG);
629 for word in words.iter_mut() { 605 for word in words.iter_mut() {
@@ -633,7 +609,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
633 } 609 }
634 610
635 pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { 611 pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
636 unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } 612 T::REGS.cr1().modify(|w| w.set_spe(true));
637 flush_rx_fifo(T::REGS); 613 flush_rx_fifo(T::REGS);
638 self.set_word_size(W::CONFIG); 614 self.set_word_size(W::CONFIG);
639 let len = read.len().max(write.len()); 615 let len = read.len().max(write.len());
@@ -650,11 +626,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
650 626
651impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { 627impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
652 fn drop(&mut self) { 628 fn drop(&mut self) {
653 unsafe { 629 self.sck.as_ref().map(|x| x.set_as_disconnected());
654 self.sck.as_ref().map(|x| x.set_as_disconnected()); 630 self.mosi.as_ref().map(|x| x.set_as_disconnected());
655 self.mosi.as_ref().map(|x| x.set_as_disconnected()); 631 self.miso.as_ref().map(|x| x.set_as_disconnected());
656 self.miso.as_ref().map(|x| x.set_as_disconnected());
657 }
658 } 632 }
659} 633}
660 634
@@ -690,7 +664,7 @@ impl RegsExt for Regs {
690 let dr = self.dr(); 664 let dr = self.dr();
691 #[cfg(any(spi_v3, spi_v4, spi_v5))] 665 #[cfg(any(spi_v3, spi_v4, spi_v5))]
692 let dr = self.txdr(); 666 let dr = self.txdr();
693 dr.ptr() as *mut W 667 dr.as_ptr() as *mut W
694 } 668 }
695 669
696 fn rx_ptr<W>(&self) -> *mut W { 670 fn rx_ptr<W>(&self) -> *mut W {
@@ -698,7 +672,7 @@ impl RegsExt for Regs {
698 let dr = self.dr(); 672 let dr = self.dr();
699 #[cfg(any(spi_v3, spi_v4, spi_v5))] 673 #[cfg(any(spi_v3, spi_v4, spi_v5))]
700 let dr = self.rxdr(); 674 let dr = self.rxdr();
701 dr.ptr() as *mut W 675 dr.as_ptr() as *mut W
702 } 676 }
703} 677}
704 678
@@ -731,7 +705,7 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> {
731 705
732fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> { 706fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> {
733 loop { 707 loop {
734 let sr = unsafe { regs.sr().read() }; 708 let sr = regs.sr().read();
735 709
736 check_error_flags(sr)?; 710 check_error_flags(sr)?;
737 711
@@ -748,7 +722,7 @@ fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> {
748 722
749fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { 723fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
750 loop { 724 loop {
751 let sr = unsafe { regs.sr().read() }; 725 let sr = regs.sr().read();
752 726
753 check_error_flags(sr)?; 727 check_error_flags(sr)?;
754 728
@@ -764,72 +738,64 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
764} 738}
765 739
766fn flush_rx_fifo(regs: Regs) { 740fn flush_rx_fifo(regs: Regs) {
767 unsafe { 741 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
768 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 742 while regs.sr().read().rxne() {
769 while regs.sr().read().rxne() { 743 let _ = regs.dr().read();
770 let _ = regs.dr().read(); 744 }
771 } 745 #[cfg(any(spi_v3, spi_v4, spi_v5))]
772 #[cfg(any(spi_v3, spi_v4, spi_v5))] 746 while regs.sr().read().rxp() {
773 while regs.sr().read().rxp() { 747 let _ = regs.rxdr().read();
774 let _ = regs.rxdr().read();
775 }
776 } 748 }
777} 749}
778 750
779fn set_txdmaen(regs: Regs, val: bool) { 751fn set_txdmaen(regs: Regs, val: bool) {
780 unsafe { 752 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
781 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 753 regs.cr2().modify(|reg| {
782 regs.cr2().modify(|reg| { 754 reg.set_txdmaen(val);
783 reg.set_txdmaen(val); 755 });
784 }); 756 #[cfg(any(spi_v3, spi_v4, spi_v5))]
785 #[cfg(any(spi_v3, spi_v4, spi_v5))] 757 regs.cfg1().modify(|reg| {
786 regs.cfg1().modify(|reg| { 758 reg.set_txdmaen(val);
787 reg.set_txdmaen(val); 759 });
788 });
789 }
790} 760}
791 761
792fn set_rxdmaen(regs: Regs, val: bool) { 762fn set_rxdmaen(regs: Regs, val: bool) {
793 unsafe { 763 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
794 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 764 regs.cr2().modify(|reg| {
795 regs.cr2().modify(|reg| { 765 reg.set_rxdmaen(val);
796 reg.set_rxdmaen(val); 766 });
797 }); 767 #[cfg(any(spi_v3, spi_v4, spi_v5))]
798 #[cfg(any(spi_v3, spi_v4, spi_v5))] 768 regs.cfg1().modify(|reg| {
799 regs.cfg1().modify(|reg| { 769 reg.set_rxdmaen(val);
800 reg.set_rxdmaen(val); 770 });
801 });
802 }
803} 771}
804 772
805fn finish_dma(regs: Regs) { 773fn finish_dma(regs: Regs) {
806 unsafe { 774 #[cfg(spi_v2)]
807 #[cfg(spi_v2)] 775 while regs.sr().read().ftlvl() > 0 {}
808 while regs.sr().read().ftlvl() > 0 {}
809 776
810 #[cfg(any(spi_v3, spi_v4, spi_v5))] 777 #[cfg(any(spi_v3, spi_v4, spi_v5))]
811 while !regs.sr().read().txc() {} 778 while !regs.sr().read().txc() {}
812 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 779 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
813 while regs.sr().read().bsy() {} 780 while regs.sr().read().bsy() {}
814 781
815 // Disable the spi peripheral 782 // Disable the spi peripheral
816 regs.cr1().modify(|w| { 783 regs.cr1().modify(|w| {
817 w.set_spe(false); 784 w.set_spe(false);
818 }); 785 });
819 786
820 // The peripheral automatically disables the DMA stream on completion without error, 787 // The peripheral automatically disables the DMA stream on completion without error,
821 // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. 788 // but it does not clear the RXDMAEN/TXDMAEN flag in CR2.
822 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 789 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
823 regs.cr2().modify(|reg| { 790 regs.cr2().modify(|reg| {
824 reg.set_txdmaen(false); 791 reg.set_txdmaen(false);
825 reg.set_rxdmaen(false); 792 reg.set_rxdmaen(false);
826 }); 793 });
827 #[cfg(any(spi_v3, spi_v4, spi_v5))] 794 #[cfg(any(spi_v3, spi_v4, spi_v5))]
828 regs.cfg1().modify(|reg| { 795 regs.cfg1().modify(|reg| {
829 reg.set_txdmaen(false); 796 reg.set_txdmaen(false);
830 reg.set_rxdmaen(false); 797 reg.set_rxdmaen(false);
831 }); 798 });
832 }
833} 799}
834 800
835fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> { 801fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> {
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index e82501a45..2622442f4 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -155,8 +155,7 @@ impl RtcDriver {
155 155
156 let timer_freq = T::frequency(); 156 let timer_freq = T::frequency();
157 157
158 // NOTE(unsafe) Critical section to use the unsafe methods 158 critical_section::with(|_| {
159 critical_section::with(|_| unsafe {
160 r.cr1().modify(|w| w.set_cen(false)); 159 r.cr1().modify(|w| w.set_cen(false));
161 r.cnt().write(|w| w.set_cnt(0)); 160 r.cnt().write(|w| w.set_cnt(0));
162 161
@@ -184,7 +183,7 @@ impl RtcDriver {
184 }); 183 });
185 184
186 <T as BasicInstance>::Interrupt::unpend(); 185 <T as BasicInstance>::Interrupt::unpend();
187 <T as BasicInstance>::Interrupt::enable(); 186 unsafe { <T as BasicInstance>::Interrupt::enable() };
188 187
189 r.cr1().modify(|w| w.set_cen(true)); 188 r.cr1().modify(|w| w.set_cen(true));
190 }) 189 })
@@ -193,9 +192,8 @@ impl RtcDriver {
193 fn on_interrupt(&self) { 192 fn on_interrupt(&self) {
194 let r = T::regs_gp16(); 193 let r = T::regs_gp16();
195 194
196 // NOTE(unsafe) Use critical section to access the methods
197 // XXX: reduce the size of this critical section ? 195 // XXX: reduce the size of this critical section ?
198 critical_section::with(|cs| unsafe { 196 critical_section::with(|cs| {
199 let sr = r.sr().read(); 197 let sr = r.sr().read();
200 let dier = r.dier().read(); 198 let dier = r.dier().read();
201 199
@@ -228,7 +226,7 @@ impl RtcDriver {
228 let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; 226 let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
229 let t = (period as u64) << 15; 227 let t = (period as u64) << 15;
230 228
231 critical_section::with(move |cs| unsafe { 229 critical_section::with(move |cs| {
232 r.dier().modify(move |w| { 230 r.dier().modify(move |w| {
233 for n in 0..ALARM_COUNT { 231 for n in 0..ALARM_COUNT {
234 let alarm = &self.alarms.borrow(cs)[n]; 232 let alarm = &self.alarms.borrow(cs)[n];
@@ -269,8 +267,7 @@ impl Driver for RtcDriver {
269 267
270 let period = self.period.load(Ordering::Relaxed); 268 let period = self.period.load(Ordering::Relaxed);
271 compiler_fence(Ordering::Acquire); 269 compiler_fence(Ordering::Acquire);
272 // NOTE(unsafe) Atomic read with no side-effects 270 let counter = r.cnt().read().cnt();
273 let counter = unsafe { r.cnt().read().cnt() };
274 calc_now(period, counter) 271 calc_now(period, counter)
275 } 272 }
276 273
@@ -310,7 +307,7 @@ impl Driver for RtcDriver {
310 if timestamp <= t { 307 if timestamp <= t {
311 // If alarm timestamp has passed the alarm will not fire. 308 // If alarm timestamp has passed the alarm will not fire.
312 // Disarm the alarm and return `false` to indicate that. 309 // Disarm the alarm and return `false` to indicate that.
313 unsafe { r.dier().modify(|w| w.set_ccie(n + 1, false)) }; 310 r.dier().modify(|w| w.set_ccie(n + 1, false));
314 311
315 alarm.timestamp.set(u64::MAX); 312 alarm.timestamp.set(u64::MAX);
316 313
@@ -321,12 +318,11 @@ impl Driver for RtcDriver {
321 318
322 // Write the CCR value regardless of whether we're going to enable it now or not. 319 // Write the CCR value regardless of whether we're going to enable it now or not.
323 // This way, when we enable it later, the right value is already set. 320 // This way, when we enable it later, the right value is already set.
324 unsafe { r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)) }; 321 r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16));
325 322
326 // Enable it if it'll happen soon. Otherwise, `next_period` will enable it. 323 // Enable it if it'll happen soon. Otherwise, `next_period` will enable it.
327 let diff = timestamp - t; 324 let diff = timestamp - t;
328 // NOTE(unsafe) We're in a critical section 325 r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000));
329 unsafe { r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)) };
330 326
331 true 327 true
332 }) 328 })
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 14db97024..09b7a3776 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -60,25 +60,19 @@ macro_rules! impl_basic_16bit_timer {
60 type Interrupt = crate::interrupt::typelevel::$irq; 60 type Interrupt = crate::interrupt::typelevel::$irq;
61 61
62 fn regs() -> crate::pac::timer::TimBasic { 62 fn regs() -> crate::pac::timer::TimBasic {
63 crate::pac::timer::TimBasic(crate::pac::$inst.0) 63 unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) }
64 } 64 }
65 65
66 fn start(&mut self) { 66 fn start(&mut self) {
67 unsafe { 67 Self::regs().cr1().modify(|r| r.set_cen(true));
68 Self::regs().cr1().modify(|r| r.set_cen(true));
69 }
70 } 68 }
71 69
72 fn stop(&mut self) { 70 fn stop(&mut self) {
73 unsafe { 71 Self::regs().cr1().modify(|r| r.set_cen(false));
74 Self::regs().cr1().modify(|r| r.set_cen(false));
75 }
76 } 72 }
77 73
78 fn reset(&mut self) { 74 fn reset(&mut self) {
79 unsafe { 75 Self::regs().cnt().write(|r| r.set_cnt(0));
80 Self::regs().cnt().write(|r| r.set_cnt(0));
81 }
82 } 76 }
83 77
84 fn set_frequency(&mut self, frequency: Hertz) { 78 fn set_frequency(&mut self, frequency: Hertz) {
@@ -90,35 +84,29 @@ macro_rules! impl_basic_16bit_timer {
90 let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); 84 let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into());
91 85
92 let regs = Self::regs(); 86 let regs = Self::regs();
93 unsafe { 87 regs.psc().write(|r| r.set_psc(psc));
94 regs.psc().write(|r| r.set_psc(psc)); 88 regs.arr().write(|r| r.set_arr(arr));
95 regs.arr().write(|r| r.set_arr(arr));
96 89
97 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); 90 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
98 regs.egr().write(|r| r.set_ug(true)); 91 regs.egr().write(|r| r.set_ug(true));
99 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); 92 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
100 }
101 } 93 }
102 94
103 fn clear_update_interrupt(&mut self) -> bool { 95 fn clear_update_interrupt(&mut self) -> bool {
104 let regs = Self::regs(); 96 let regs = Self::regs();
105 unsafe { 97 let sr = regs.sr().read();
106 let sr = regs.sr().read(); 98 if sr.uif() {
107 if sr.uif() { 99 regs.sr().modify(|r| {
108 regs.sr().modify(|r| { 100 r.set_uif(false);
109 r.set_uif(false); 101 });
110 }); 102 true
111 true 103 } else {
112 } else { 104 false
113 false
114 }
115 } 105 }
116 } 106 }
117 107
118 fn enable_update_interrupt(&mut self, enable: bool) { 108 fn enable_update_interrupt(&mut self, enable: bool) {
119 unsafe { 109 Self::regs().dier().write(|r| r.set_uie(enable));
120 Self::regs().dier().write(|r| r.set_uie(enable));
121 }
122 } 110 }
123 } 111 }
124 }; 112 };
@@ -141,14 +129,12 @@ macro_rules! impl_32bit_timer {
141 let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into())); 129 let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()));
142 130
143 let regs = Self::regs_gp32(); 131 let regs = Self::regs_gp32();
144 unsafe { 132 regs.psc().write(|r| r.set_psc(psc));
145 regs.psc().write(|r| r.set_psc(psc)); 133 regs.arr().write(|r| r.set_arr(arr));
146 regs.arr().write(|r| r.set_arr(arr));
147 134
148 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); 135 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
149 regs.egr().write(|r| r.set_ug(true)); 136 regs.egr().write(|r| r.set_ug(true));
150 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); 137 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
151 }
152 } 138 }
153 } 139 }
154 }; 140 };
@@ -185,7 +171,7 @@ foreach_interrupt! {
185 171
186 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 172 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
187 fn regs_gp16() -> crate::pac::timer::TimGp16 { 173 fn regs_gp16() -> crate::pac::timer::TimGp16 {
188 crate::pac::timer::TimGp16(crate::pac::$inst.0) 174 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
189 } 175 }
190 } 176 }
191 177
@@ -206,7 +192,7 @@ foreach_interrupt! {
206 192
207 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 193 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
208 fn regs_gp16() -> crate::pac::timer::TimGp16 { 194 fn regs_gp16() -> crate::pac::timer::TimGp16 {
209 crate::pac::timer::TimGp16(crate::pac::$inst.0) 195 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
210 } 196 }
211 } 197 }
212 198
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 086196a2c..433ad299c 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -19,68 +19,64 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
19 let state = T::buffered_state(); 19 let state = T::buffered_state();
20 20
21 // RX 21 // RX
22 unsafe { 22 let sr_val = sr(r).read();
23 let sr = sr(r).read(); 23 // On v1 & v2, reading DR clears the rxne, error and idle interrupt
24 // On v1 & v2, reading DR clears the rxne, error and idle interrupt 24 // flags. Keep this close to the SR read to reduce the chance of a
25 // flags. Keep this close to the SR read to reduce the chance of a 25 // flag being set in-between.
26 // flag being set in-between. 26 let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) {
27 let dr = if sr.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr.ore() || sr.idle()) { 27 Some(rdr(r).read_volatile())
28 Some(rdr(r).read_volatile()) 28 } else {
29 None
30 };
31 clear_interrupt_flags(r, sr_val);
32
33 if sr_val.pe() {
34 warn!("Parity error");
35 }
36 if sr_val.fe() {
37 warn!("Framing error");
38 }
39 if sr_val.ne() {
40 warn!("Noise error");
41 }
42 if sr_val.ore() {
43 warn!("Overrun error");
44 }
45 if sr_val.rxne() {
46 let mut rx_writer = state.rx_buf.writer();
47 let buf = rx_writer.push_slice();
48 if !buf.is_empty() {
49 buf[0] = dr.unwrap();
50 rx_writer.push_done(1);
29 } else { 51 } else {
30 None 52 // FIXME: Should we disable any further RX interrupts when the buffer becomes full.
31 };
32 clear_interrupt_flags(r, sr);
33
34 if sr.pe() {
35 warn!("Parity error");
36 }
37 if sr.fe() {
38 warn!("Framing error");
39 }
40 if sr.ne() {
41 warn!("Noise error");
42 }
43 if sr.ore() {
44 warn!("Overrun error");
45 }
46 if sr.rxne() {
47 let mut rx_writer = state.rx_buf.writer();
48 let buf = rx_writer.push_slice();
49 if !buf.is_empty() {
50 buf[0] = dr.unwrap();
51 rx_writer.push_done(1);
52 } else {
53 // FIXME: Should we disable any further RX interrupts when the buffer becomes full.
54 }
55
56 if state.rx_buf.is_full() {
57 state.rx_waker.wake();
58 }
59 } 53 }
60 54
61 if sr.idle() { 55 if state.rx_buf.is_full() {
62 state.rx_waker.wake(); 56 state.rx_waker.wake();
63 } 57 }
64 } 58 }
65 59
60 if sr_val.idle() {
61 state.rx_waker.wake();
62 }
63
66 // TX 64 // TX
67 unsafe { 65 if sr(r).read().txe() {
68 if sr(r).read().txe() { 66 let mut tx_reader = state.tx_buf.reader();
69 let mut tx_reader = state.tx_buf.reader(); 67 let buf = tx_reader.pop_slice();
70 let buf = tx_reader.pop_slice(); 68 if !buf.is_empty() {
71 if !buf.is_empty() { 69 r.cr1().modify(|w| {
72 r.cr1().modify(|w| { 70 w.set_txeie(true);
73 w.set_txeie(true); 71 });
74 }); 72 tdr(r).write_volatile(buf[0].into());
75 tdr(r).write_volatile(buf[0].into()); 73 tx_reader.pop_done(1);
76 tx_reader.pop_done(1); 74 state.tx_waker.wake();
77 state.tx_waker.wake(); 75 } else {
78 } else { 76 // Disable interrupt until we have something to transmit again
79 // Disable interrupt until we have something to transmit again 77 r.cr1().modify(|w| {
80 r.cr1().modify(|w| { 78 w.set_txeie(false);
81 w.set_txeie(false); 79 });
82 });
83 }
84 } 80 }
85 } 81 }
86 } 82 }
@@ -150,14 +146,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
150 T::enable(); 146 T::enable();
151 T::reset(); 147 T::reset();
152 148
153 unsafe { 149 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
154 rts.set_as_af(rts.af_num(), AFType::OutputPushPull); 150 cts.set_as_af(cts.af_num(), AFType::Input);
155 cts.set_as_af(cts.af_num(), AFType::Input); 151 T::regs().cr3().write(|w| {
156 T::regs().cr3().write(|w| { 152 w.set_rtse(true);
157 w.set_rtse(true); 153 w.set_ctse(true);
158 w.set_ctse(true); 154 });
159 });
160 }
161 155
162 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) 156 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
163 } 157 }
@@ -178,12 +172,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
178 T::enable(); 172 T::enable();
179 T::reset(); 173 T::reset();
180 174
181 unsafe { 175 de.set_as_af(de.af_num(), AFType::OutputPushPull);
182 de.set_as_af(de.af_num(), AFType::OutputPushPull); 176 T::regs().cr3().write(|w| {
183 T::regs().cr3().write(|w| { 177 w.set_dem(true);
184 w.set_dem(true); 178 });
185 });
186 }
187 179
188 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) 180 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
189 } 181 }
@@ -205,22 +197,18 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
205 unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; 197 unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
206 198
207 let r = T::regs(); 199 let r = T::regs();
208 unsafe { 200 rx.set_as_af(rx.af_num(), AFType::Input);
209 rx.set_as_af(rx.af_num(), AFType::Input); 201 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
210 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
211 }
212 202
213 configure(r, &config, T::frequency(), T::KIND, true, true); 203 configure(r, &config, T::frequency(), T::KIND, true, true);
214 204
215 unsafe { 205 r.cr1().modify(|w| {
216 r.cr1().modify(|w| { 206 #[cfg(lpuart_v2)]
217 #[cfg(lpuart_v2)] 207 w.set_fifoen(true);
218 w.set_fifoen(true);
219 208
220 w.set_rxneie(true); 209 w.set_rxneie(true);
221 w.set_idleie(true); 210 w.set_idleie(true);
222 }); 211 });
223 }
224 212
225 T::Interrupt::unpend(); 213 T::Interrupt::unpend();
226 unsafe { T::Interrupt::enable() }; 214 unsafe { T::Interrupt::enable() };
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index da3644a81..47a79c187 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -36,35 +36,31 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
36 let r = T::regs(); 36 let r = T::regs();
37 let s = T::state(); 37 let s = T::state();
38 38
39 let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) }; 39 let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read());
40 40
41 let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie()); 41 let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
42 if has_errors { 42 if has_errors {
43 // clear all interrupts and DMA Rx Request 43 // clear all interrupts and DMA Rx Request
44 unsafe { 44 r.cr1().modify(|w| {
45 r.cr1().modify(|w| { 45 // disable RXNE interrupt
46 // disable RXNE interrupt 46 w.set_rxneie(false);
47 w.set_rxneie(false); 47 // disable parity interrupt
48 // disable parity interrupt 48 w.set_peie(false);
49 w.set_peie(false); 49 // disable idle line interrupt
50 // disable idle line interrupt 50 w.set_idleie(false);
51 w.set_idleie(false); 51 });
52 }); 52 r.cr3().modify(|w| {
53 r.cr3().modify(|w| { 53 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
54 // disable Error Interrupt: (Frame error, Noise error, Overrun error) 54 w.set_eie(false);
55 w.set_eie(false); 55 // disable DMA Rx Request
56 // disable DMA Rx Request 56 w.set_dmar(false);
57 w.set_dmar(false); 57 });
58 });
59 }
60 } else if cr1.idleie() && sr.idle() { 58 } else if cr1.idleie() && sr.idle() {
61 // IDLE detected: no more data will come 59 // IDLE detected: no more data will come
62 unsafe { 60 r.cr1().modify(|w| {
63 r.cr1().modify(|w| { 61 // disable idle line detection
64 // disable idle line detection 62 w.set_idleie(false);
65 w.set_idleie(false); 63 });
66 });
67 }
68 } else if cr1.rxneie() { 64 } else if cr1.rxneie() {
69 // We cannot check the RXNE flag as it is auto-cleared by the DMA controller 65 // We cannot check the RXNE flag as it is auto-cleared by the DMA controller
70 66
@@ -205,12 +201,10 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
205 T::enable(); 201 T::enable();
206 T::reset(); 202 T::reset();
207 203
208 unsafe { 204 cts.set_as_af(cts.af_num(), AFType::Input);
209 cts.set_as_af(cts.af_num(), AFType::Input); 205 T::regs().cr3().write(|w| {
210 T::regs().cr3().write(|w| { 206 w.set_ctse(true);
211 w.set_ctse(true); 207 });
212 });
213 }
214 Self::new_inner(peri, tx, tx_dma, config) 208 Self::new_inner(peri, tx, tx_dma, config)
215 } 209 }
216 210
@@ -224,9 +218,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
224 218
225 let r = T::regs(); 219 let r = T::regs();
226 220
227 unsafe { 221 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
228 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
229 }
230 222
231 configure(r, &config, T::frequency(), T::KIND, false, true); 223 configure(r, &config, T::frequency(), T::KIND, false, true);
232 224
@@ -245,11 +237,9 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
245 { 237 {
246 let ch = &mut self.tx_dma; 238 let ch = &mut self.tx_dma;
247 let request = ch.request(); 239 let request = ch.request();
248 unsafe { 240 T::regs().cr3().modify(|reg| {
249 T::regs().cr3().modify(|reg| { 241 reg.set_dmat(true);
250 reg.set_dmat(true); 242 });
251 });
252 }
253 // If we don't assign future to a variable, the data register pointer 243 // If we don't assign future to a variable, the data register pointer
254 // is held across an await and makes the future non-Send. 244 // is held across an await and makes the future non-Send.
255 let transfer = unsafe { Transfer::new_write(ch, request, buffer, tdr(T::regs()), Default::default()) }; 245 let transfer = unsafe { Transfer::new_write(ch, request, buffer, tdr(T::regs()), Default::default()) };
@@ -258,21 +248,17 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
258 } 248 }
259 249
260 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 250 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
261 unsafe { 251 let r = T::regs();
262 let r = T::regs(); 252 for &b in buffer {
263 for &b in buffer { 253 while !sr(r).read().txe() {}
264 while !sr(r).read().txe() {} 254 unsafe { tdr(r).write_volatile(b) };
265 tdr(r).write_volatile(b);
266 }
267 } 255 }
268 Ok(()) 256 Ok(())
269 } 257 }
270 258
271 pub fn blocking_flush(&mut self) -> Result<(), Error> { 259 pub fn blocking_flush(&mut self) -> Result<(), Error> {
272 unsafe { 260 let r = T::regs();
273 let r = T::regs(); 261 while !sr(r).read().tc() {}
274 while !sr(r).read().tc() {}
275 }
276 Ok(()) 262 Ok(())
277 } 263 }
278} 264}
@@ -305,12 +291,10 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
305 T::enable(); 291 T::enable();
306 T::reset(); 292 T::reset();
307 293
308 unsafe { 294 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
309 rts.set_as_af(rts.af_num(), AFType::OutputPushPull); 295 T::regs().cr3().write(|w| {
310 T::regs().cr3().write(|w| { 296 w.set_rtse(true);
311 w.set_rtse(true); 297 });
312 });
313 }
314 298
315 Self::new_inner(peri, rx, rx_dma, config) 299 Self::new_inner(peri, rx, rx_dma, config)
316 } 300 }
@@ -325,9 +309,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
325 309
326 let r = T::regs(); 310 let r = T::regs();
327 311
328 unsafe { 312 rx.set_as_af(rx.af_num(), AFType::Input);
329 rx.set_as_af(rx.af_num(), AFType::Input);
330 }
331 313
332 configure(r, &config, T::frequency(), T::KIND, true, false); 314 configure(r, &config, T::frequency(), T::KIND, true, false);
333 315
@@ -347,7 +329,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
347 } 329 }
348 330
349 #[cfg(any(usart_v1, usart_v2))] 331 #[cfg(any(usart_v1, usart_v2))]
350 unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> { 332 fn check_rx_flags(&mut self) -> Result<bool, Error> {
351 let r = T::regs(); 333 let r = T::regs();
352 loop { 334 loop {
353 // Handle all buffered error flags. 335 // Handle all buffered error flags.
@@ -380,7 +362,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
380 } 362 }
381 363
382 #[cfg(any(usart_v3, usart_v4))] 364 #[cfg(any(usart_v3, usart_v4))]
383 unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> { 365 fn check_rx_flags(&mut self) -> Result<bool, Error> {
384 let r = T::regs(); 366 let r = T::regs();
385 let sr = r.isr().read(); 367 let sr = r.isr().read();
386 if sr.pe() { 368 if sr.pe() {
@@ -410,22 +392,18 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
410 392
411 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { 393 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
412 let r = T::regs(); 394 let r = T::regs();
413 unsafe { 395 if self.check_rx_flags()? {
414 if self.check_rx_flags()? { 396 Ok(unsafe { rdr(r).read_volatile() })
415 Ok(rdr(r).read_volatile()) 397 } else {
416 } else { 398 Err(nb::Error::WouldBlock)
417 Err(nb::Error::WouldBlock)
418 }
419 } 399 }
420 } 400 }
421 401
422 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 402 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
423 unsafe { 403 let r = T::regs();
424 let r = T::regs(); 404 for b in buffer {
425 for b in buffer { 405 while !self.check_rx_flags()? {}
426 while !self.check_rx_flags()? {} 406 unsafe { *b = rdr(r).read_volatile() }
427 *b = rdr(r).read_volatile();
428 }
429 } 407 }
430 Ok(()) 408 Ok(())
431 } 409 }
@@ -451,23 +429,20 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
451 let on_drop = OnDrop::new(move || { 429 let on_drop = OnDrop::new(move || {
452 // defmt::trace!("Clear all USART interrupts and DMA Read Request"); 430 // defmt::trace!("Clear all USART interrupts and DMA Read Request");
453 // clear all interrupts and DMA Rx Request 431 // clear all interrupts and DMA Rx Request
454 // SAFETY: only clears Rx related flags 432 r.cr1().modify(|w| {
455 unsafe { 433 // disable RXNE interrupt
456 r.cr1().modify(|w| { 434 w.set_rxneie(false);
457 // disable RXNE interrupt 435 // disable parity interrupt
458 w.set_rxneie(false); 436 w.set_peie(false);
459 // disable parity interrupt 437 // disable idle line interrupt
460 w.set_peie(false); 438 w.set_idleie(false);
461 // disable idle line interrupt 439 });
462 w.set_idleie(false); 440 r.cr3().modify(|w| {
463 }); 441 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
464 r.cr3().modify(|w| { 442 w.set_eie(false);
465 // disable Error Interrupt: (Frame error, Noise error, Overrun error) 443 // disable DMA Rx Request
466 w.set_eie(false); 444 w.set_dmar(false);
467 // disable DMA Rx Request 445 });
468 w.set_dmar(false);
469 });
470 }
471 }); 446 });
472 447
473 let ch = &mut self.rx_dma; 448 let ch = &mut self.rx_dma;
@@ -480,78 +455,74 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
480 // future which will complete when DMA Read request completes 455 // future which will complete when DMA Read request completes
481 let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) }; 456 let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) };
482 457
483 // SAFETY: The only way we might have a problem is using split rx and tx 458 // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer
484 // here we only modify or read Rx related flags, interrupts and DMA channel 459 if !self.detect_previous_overrun {
485 unsafe { 460 let sr = sr(r).read();
486 // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer 461 // This read also clears the error and idle interrupt flags on v1.
487 if !self.detect_previous_overrun { 462 unsafe { rdr(r).read_volatile() };
488 let sr = sr(r).read(); 463 clear_interrupt_flags(r, sr);
489 // This read also clears the error and idle interrupt flags on v1. 464 }
490 rdr(r).read_volatile();
491 clear_interrupt_flags(r, sr);
492 }
493
494 r.cr1().modify(|w| {
495 // disable RXNE interrupt
496 w.set_rxneie(false);
497 // enable parity interrupt if not ParityNone
498 w.set_peie(w.pce());
499 });
500 465
501 r.cr3().modify(|w| { 466 r.cr1().modify(|w| {
502 // enable Error Interrupt: (Frame error, Noise error, Overrun error) 467 // disable RXNE interrupt
503 w.set_eie(true); 468 w.set_rxneie(false);
504 // enable DMA Rx Request 469 // enable parity interrupt if not ParityNone
505 w.set_dmar(true); 470 w.set_peie(w.pce());
506 }); 471 });
507 472
508 compiler_fence(Ordering::SeqCst); 473 r.cr3().modify(|w| {
474 // enable Error Interrupt: (Frame error, Noise error, Overrun error)
475 w.set_eie(true);
476 // enable DMA Rx Request
477 w.set_dmar(true);
478 });
509 479
510 // In case of errors already pending when reception started, interrupts may have already been raised 480 compiler_fence(Ordering::SeqCst);
511 // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts
512 // have been disabled in interrupt handler and DMA Rx Request has been disabled.
513 481
514 let cr3 = r.cr3().read(); 482 // In case of errors already pending when reception started, interrupts may have already been raised
483 // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts
484 // have been disabled in interrupt handler and DMA Rx Request has been disabled.
515 485
516 if !cr3.dmar() { 486 let cr3 = r.cr3().read();
517 // something went wrong
518 // because the only way to get this flag cleared is to have an interrupt
519 487
520 // DMA will be stopped when transfer is dropped 488 if !cr3.dmar() {
489 // something went wrong
490 // because the only way to get this flag cleared is to have an interrupt
521 491
522 let sr = sr(r).read(); 492 // DMA will be stopped when transfer is dropped
523 // This read also clears the error and idle interrupt flags on v1.
524 rdr(r).read_volatile();
525 clear_interrupt_flags(r, sr);
526 493
527 if sr.pe() { 494 let sr = sr(r).read();
528 return Err(Error::Parity); 495 // This read also clears the error and idle interrupt flags on v1.
529 } 496 unsafe { rdr(r).read_volatile() };
530 if sr.fe() { 497 clear_interrupt_flags(r, sr);
531 return Err(Error::Framing);
532 }
533 if sr.ne() {
534 return Err(Error::Noise);
535 }
536 if sr.ore() {
537 return Err(Error::Overrun);
538 }
539 498
540 unreachable!(); 499 if sr.pe() {
500 return Err(Error::Parity);
541 } 501 }
542 502 if sr.fe() {
543 if enable_idle_line_detection { 503 return Err(Error::Framing);
544 // clear idle flag
545 let sr = sr(r).read();
546 // This read also clears the error and idle interrupt flags on v1.
547 rdr(r).read_volatile();
548 clear_interrupt_flags(r, sr);
549
550 // enable idle interrupt
551 r.cr1().modify(|w| {
552 w.set_idleie(true);
553 });
554 } 504 }
505 if sr.ne() {
506 return Err(Error::Noise);
507 }
508 if sr.ore() {
509 return Err(Error::Overrun);
510 }
511
512 unreachable!();
513 }
514
515 if enable_idle_line_detection {
516 // clear idle flag
517 let sr = sr(r).read();
518 // This read also clears the error and idle interrupt flags on v1.
519 unsafe { rdr(r).read_volatile() };
520 clear_interrupt_flags(r, sr);
521
522 // enable idle interrupt
523 r.cr1().modify(|w| {
524 w.set_idleie(true);
525 });
555 } 526 }
556 527
557 compiler_fence(Ordering::SeqCst); 528 compiler_fence(Ordering::SeqCst);
@@ -562,15 +533,11 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
562 533
563 s.rx_waker.register(cx.waker()); 534 s.rx_waker.register(cx.waker());
564 535
565 // SAFETY: read only and we only use Rx related flags 536 let sr = sr(r).read();
566 let sr = unsafe { sr(r).read() };
567 537
568 // SAFETY: only clears Rx related flags 538 // This read also clears the error and idle interrupt flags on v1.
569 unsafe { 539 unsafe { rdr(r).read_volatile() };
570 // This read also clears the error and idle interrupt flags on v1. 540 clear_interrupt_flags(r, sr);
571 rdr(r).read_volatile();
572 clear_interrupt_flags(r, sr);
573 }
574 541
575 compiler_fence(Ordering::SeqCst); 542 compiler_fence(Ordering::SeqCst);
576 543
@@ -677,14 +644,12 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
677 T::enable(); 644 T::enable();
678 T::reset(); 645 T::reset();
679 646
680 unsafe { 647 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
681 rts.set_as_af(rts.af_num(), AFType::OutputPushPull); 648 cts.set_as_af(cts.af_num(), AFType::Input);
682 cts.set_as_af(cts.af_num(), AFType::Input); 649 T::regs().cr3().write(|w| {
683 T::regs().cr3().write(|w| { 650 w.set_rtse(true);
684 w.set_rtse(true); 651 w.set_ctse(true);
685 w.set_ctse(true); 652 });
686 });
687 }
688 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) 653 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
689 } 654 }
690 655
@@ -704,12 +669,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
704 T::enable(); 669 T::enable();
705 T::reset(); 670 T::reset();
706 671
707 unsafe { 672 de.set_as_af(de.af_num(), AFType::OutputPushPull);
708 de.set_as_af(de.af_num(), AFType::OutputPushPull); 673 T::regs().cr3().write(|w| {
709 T::regs().cr3().write(|w| { 674 w.set_dem(true);
710 w.set_dem(true); 675 });
711 });
712 }
713 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) 676 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
714 } 677 }
715 678
@@ -725,10 +688,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
725 688
726 let r = T::regs(); 689 let r = T::regs();
727 690
728 unsafe { 691 rx.set_as_af(rx.af_num(), AFType::Input);
729 rx.set_as_af(rx.af_num(), AFType::Input); 692 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
730 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
731 }
732 693
733 configure(r, &config, T::frequency(), T::KIND, true, true); 694 configure(r, &config, T::frequency(), T::KIND, true, true);
734 695
@@ -847,11 +808,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
847 if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { 808 if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) {
848 over8 = true; 809 over8 = true;
849 let div = div as u32; 810 let div = div as u32;
850 unsafe { 811 r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07)));
851 r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07))); 812 #[cfg(usart_v4)]
852 #[cfg(usart_v4)] 813 r.presc().write(|w| w.set_prescaler(_presc_val));
853 r.presc().write(|w| w.set_prescaler(_presc_val));
854 }
855 found = Some(div); 814 found = Some(div);
856 break; 815 break;
857 } 816 }
@@ -860,11 +819,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
860 819
861 if div < brr_max { 820 if div < brr_max {
862 let div = div as u32; 821 let div = div as u32;
863 unsafe { 822 r.brr().write_value(regs::Brr(div));
864 r.brr().write_value(regs::Brr(div)); 823 #[cfg(usart_v4)]
865 #[cfg(usart_v4)] 824 r.presc().write(|w| w.set_prescaler(_presc_val));
866 r.presc().write(|w| w.set_prescaler(_presc_val));
867 }
868 found = Some(div); 825 found = Some(div);
869 break; 826 break;
870 } 827 }
@@ -883,44 +840,42 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
883 pclk_freq.0 / div 840 pclk_freq.0 / div
884 ); 841 );
885 842
886 unsafe { 843 r.cr2().write(|w| {
887 r.cr2().write(|w| { 844 w.set_stop(match config.stop_bits {
888 w.set_stop(match config.stop_bits { 845 StopBits::STOP0P5 => vals::Stop::STOP0P5,
889 StopBits::STOP0P5 => vals::Stop::STOP0P5, 846 StopBits::STOP1 => vals::Stop::STOP1,
890 StopBits::STOP1 => vals::Stop::STOP1, 847 StopBits::STOP1P5 => vals::Stop::STOP1P5,
891 StopBits::STOP1P5 => vals::Stop::STOP1P5, 848 StopBits::STOP2 => vals::Stop::STOP2,
892 StopBits::STOP2 => vals::Stop::STOP2,
893 });
894 }); 849 });
895 r.cr1().write(|w| { 850 });
896 // enable uart 851 r.cr1().write(|w| {
897 w.set_ue(true); 852 // enable uart
898 // enable transceiver 853 w.set_ue(true);
899 w.set_te(enable_tx); 854 // enable transceiver
900 // enable receiver 855 w.set_te(enable_tx);
901 w.set_re(enable_rx); 856 // enable receiver
902 // configure word size 857 w.set_re(enable_rx);
903 w.set_m0(if config.parity != Parity::ParityNone { 858 // configure word size
904 vals::M0::BIT9 859 w.set_m0(if config.parity != Parity::ParityNone {
905 } else { 860 vals::M0::BIT9
906 vals::M0::BIT8 861 } else {
907 }); 862 vals::M0::BIT8
908 // configure parity
909 w.set_pce(config.parity != Parity::ParityNone);
910 w.set_ps(match config.parity {
911 Parity::ParityOdd => vals::Ps::ODD,
912 Parity::ParityEven => vals::Ps::EVEN,
913 _ => vals::Ps::EVEN,
914 });
915 #[cfg(not(usart_v1))]
916 w.set_over8(vals::Over8(over8 as _));
917 }); 863 });
918 864 // configure parity
919 #[cfg(not(usart_v1))] 865 w.set_pce(config.parity != Parity::ParityNone);
920 r.cr3().modify(|w| { 866 w.set_ps(match config.parity {
921 w.set_onebit(config.assume_noise_free); 867 Parity::ParityOdd => vals::Ps::ODD,
868 Parity::ParityEven => vals::Ps::EVEN,
869 _ => vals::Ps::EVEN,
922 }); 870 });
923 } 871 #[cfg(not(usart_v1))]
872 w.set_over8(vals::Over8(over8 as _));
873 });
874
875 #[cfg(not(usart_v1))]
876 r.cr3().modify(|w| {
877 w.set_onebit(config.assume_noise_free);
878 });
924} 879}
925 880
926mod eh02 { 881mod eh02 {
@@ -1111,12 +1066,12 @@ use self::sealed::Kind;
1111 1066
1112#[cfg(any(usart_v1, usart_v2))] 1067#[cfg(any(usart_v1, usart_v2))]
1113fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { 1068fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
1114 r.dr().ptr() as _ 1069 r.dr().as_ptr() as _
1115} 1070}
1116 1071
1117#[cfg(any(usart_v1, usart_v2))] 1072#[cfg(any(usart_v1, usart_v2))]
1118fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { 1073fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
1119 r.dr().ptr() as _ 1074 r.dr().as_ptr() as _
1120} 1075}
1121 1076
1122#[cfg(any(usart_v1, usart_v2))] 1077#[cfg(any(usart_v1, usart_v2))]
@@ -1126,18 +1081,18 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::p
1126 1081
1127#[cfg(any(usart_v1, usart_v2))] 1082#[cfg(any(usart_v1, usart_v2))]
1128#[allow(unused)] 1083#[allow(unused)]
1129unsafe fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) { 1084fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) {
1130 // On v1 the flags are cleared implicitly by reads and writes to DR. 1085 // On v1 the flags are cleared implicitly by reads and writes to DR.
1131} 1086}
1132 1087
1133#[cfg(any(usart_v3, usart_v4))] 1088#[cfg(any(usart_v3, usart_v4))]
1134fn tdr(r: Regs) -> *mut u8 { 1089fn tdr(r: Regs) -> *mut u8 {
1135 r.tdr().ptr() as _ 1090 r.tdr().as_ptr() as _
1136} 1091}
1137 1092
1138#[cfg(any(usart_v3, usart_v4))] 1093#[cfg(any(usart_v3, usart_v4))]
1139fn rdr(r: Regs) -> *mut u8 { 1094fn rdr(r: Regs) -> *mut u8 {
1140 r.rdr().ptr() as _ 1095 r.rdr().as_ptr() as _
1141} 1096}
1142 1097
1143#[cfg(any(usart_v3, usart_v4))] 1098#[cfg(any(usart_v3, usart_v4))]
@@ -1147,7 +1102,7 @@ fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> {
1147 1102
1148#[cfg(any(usart_v3, usart_v4))] 1103#[cfg(any(usart_v3, usart_v4))]
1149#[allow(unused)] 1104#[allow(unused)]
1150unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { 1105fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
1151 r.icr().write(|w| *w = regs::Icr(sr.0)); 1106 r.icr().write(|w| *w = regs::Icr(sr.0));
1152} 1107}
1153 1108
@@ -1214,7 +1169,7 @@ macro_rules! impl_usart {
1214 type Interrupt = crate::interrupt::typelevel::$irq; 1169 type Interrupt = crate::interrupt::typelevel::$irq;
1215 1170
1216 fn regs() -> Regs { 1171 fn regs() -> Regs {
1217 Regs(crate::pac::$inst.0) 1172 unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) }
1218 } 1173 }
1219 1174
1220 fn state() -> &'static crate::usart::sealed::State { 1175 fn state() -> &'static crate::usart::sealed::State {
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index 511b71c7f..c74d7e092 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -59,23 +59,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
59 59
60 let r = T::regs(); 60 let r = T::regs();
61 // clear all interrupts and DMA Rx Request 61 // clear all interrupts and DMA Rx Request
62 // SAFETY: only clears Rx related flags 62 r.cr1().modify(|w| {
63 unsafe { 63 // disable RXNE interrupt
64 r.cr1().modify(|w| { 64 w.set_rxneie(false);
65 // disable RXNE interrupt 65 // enable parity interrupt if not ParityNone
66 w.set_rxneie(false); 66 w.set_peie(w.pce());
67 // enable parity interrupt if not ParityNone 67 // enable idle line interrupt
68 w.set_peie(w.pce()); 68 w.set_idleie(true);
69 // enable idle line interrupt 69 });
70 w.set_idleie(true); 70 r.cr3().modify(|w| {
71 }); 71 // enable Error Interrupt: (Frame error, Noise error, Overrun error)
72 r.cr3().modify(|w| { 72 w.set_eie(true);
73 // enable Error Interrupt: (Frame error, Noise error, Overrun error) 73 // enable DMA Rx Request
74 w.set_eie(true); 74 w.set_dmar(true);
75 // enable DMA Rx Request 75 });
76 w.set_dmar(true);
77 });
78 }
79 } 76 }
80 77
81 /// Stop uart background receive 78 /// Stop uart background receive
@@ -84,23 +81,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
84 81
85 let r = T::regs(); 82 let r = T::regs();
86 // clear all interrupts and DMA Rx Request 83 // clear all interrupts and DMA Rx Request
87 // SAFETY: only clears Rx related flags 84 r.cr1().modify(|w| {
88 unsafe { 85 // disable RXNE interrupt
89 r.cr1().modify(|w| { 86 w.set_rxneie(false);
90 // disable RXNE interrupt 87 // disable parity interrupt
91 w.set_rxneie(false); 88 w.set_peie(false);
92 // disable parity interrupt 89 // disable idle line interrupt
93 w.set_peie(false); 90 w.set_idleie(false);
94 // disable idle line interrupt 91 });
95 w.set_idleie(false); 92 r.cr3().modify(|w| {
96 }); 93 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
97 r.cr3().modify(|w| { 94 w.set_eie(false);
98 // disable Error Interrupt: (Frame error, Noise error, Overrun error) 95 // disable DMA Rx Request
99 w.set_eie(false); 96 w.set_dmar(false);
100 // disable DMA Rx Request 97 });
101 w.set_dmar(false);
102 });
103 }
104 98
105 compiler_fence(Ordering::SeqCst); 99 compiler_fence(Ordering::SeqCst);
106 } 100 }
@@ -117,8 +111,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
117 let r = T::regs(); 111 let r = T::regs();
118 112
119 // Start background receive if it was not already started 113 // Start background receive if it was not already started
120 // SAFETY: read only 114 match r.cr3().read().dmar() {
121 match unsafe { r.cr3().read().dmar() } {
122 false => self.start()?, 115 false => self.start()?,
123 _ => {} 116 _ => {}
124 }; 117 };
@@ -213,19 +206,17 @@ fn check_for_errors(s: Sr) -> Result<(), Error> {
213 206
214/// Clear IDLE and return the Sr register 207/// Clear IDLE and return the Sr register
215fn clear_idle_flag(r: Regs) -> Sr { 208fn clear_idle_flag(r: Regs) -> Sr {
216 unsafe { 209 // SAFETY: read only and we only use Rx related flags
217 // SAFETY: read only and we only use Rx related flags
218 210
219 let sr = sr(r).read(); 211 let sr = sr(r).read();
220 212
221 // This read also clears the error and idle interrupt flags on v1. 213 // This read also clears the error and idle interrupt flags on v1.
222 rdr(r).read_volatile(); 214 unsafe { rdr(r).read_volatile() };
223 clear_interrupt_flags(r, sr); 215 clear_interrupt_flags(r, sr);
224 216
225 r.cr1().modify(|w| w.set_idleie(true)); 217 r.cr1().modify(|w| w.set_idleie(true));
226 218
227 sr 219 sr
228 }
229} 220}
230 221
231#[cfg(all(feature = "unstable-traits", feature = "nightly"))] 222#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 7486bd376..2367127e8 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -28,82 +28,80 @@ pub struct InterruptHandler<T: Instance> {
28 28
29impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { 29impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
30 unsafe fn on_interrupt() { 30 unsafe fn on_interrupt() {
31 unsafe { 31 let regs = T::regs();
32 let regs = T::regs(); 32 //let x = regs.istr().read().0;
33 //let x = regs.istr().read().0; 33 //trace!("USB IRQ: {:08x}", x);
34 //trace!("USB IRQ: {:08x}", x);
35
36 let istr = regs.istr().read();
37
38 if istr.susp() {
39 //trace!("USB IRQ: susp");
40 IRQ_SUSPEND.store(true, Ordering::Relaxed);
41 regs.cntr().modify(|w| {
42 w.set_fsusp(true);
43 w.set_lpmode(true);
44 });
45
46 // Write 0 to clear.
47 let mut clear = regs::Istr(!0);
48 clear.set_susp(false);
49 regs.istr().write_value(clear);
50
51 // Wake main thread.
52 BUS_WAKER.wake();
53 }
54 34
55 if istr.wkup() { 35 let istr = regs.istr().read();
56 //trace!("USB IRQ: wkup");
57 IRQ_RESUME.store(true, Ordering::Relaxed);
58 regs.cntr().modify(|w| {
59 w.set_fsusp(false);
60 w.set_lpmode(false);
61 });
62
63 // Write 0 to clear.
64 let mut clear = regs::Istr(!0);
65 clear.set_wkup(false);
66 regs.istr().write_value(clear);
67
68 // Wake main thread.
69 BUS_WAKER.wake();
70 }
71 36
72 if istr.reset() { 37 if istr.susp() {
73 //trace!("USB IRQ: reset"); 38 //trace!("USB IRQ: susp");
74 IRQ_RESET.store(true, Ordering::Relaxed); 39 IRQ_SUSPEND.store(true, Ordering::Relaxed);
40 regs.cntr().modify(|w| {
41 w.set_fsusp(true);
42 w.set_lpmode(true);
43 });
75 44
76 // Write 0 to clear. 45 // Write 0 to clear.
77 let mut clear = regs::Istr(!0); 46 let mut clear = regs::Istr(!0);
78 clear.set_reset(false); 47 clear.set_susp(false);
79 regs.istr().write_value(clear); 48 regs.istr().write_value(clear);
80 49
81 // Wake main thread. 50 // Wake main thread.
82 BUS_WAKER.wake(); 51 BUS_WAKER.wake();
83 } 52 }
84 53
85 if istr.ctr() { 54 if istr.wkup() {
86 let index = istr.ep_id() as usize; 55 //trace!("USB IRQ: wkup");
87 let mut epr = regs.epr(index).read(); 56 IRQ_RESUME.store(true, Ordering::Relaxed);
88 if epr.ctr_rx() { 57 regs.cntr().modify(|w| {
89 if index == 0 && epr.setup() { 58 w.set_fsusp(false);
90 EP0_SETUP.store(true, Ordering::Relaxed); 59 w.set_lpmode(false);
91 } 60 });
92 //trace!("EP {} RX, setup={}", index, epr.setup()); 61
93 EP_OUT_WAKERS[index].wake(); 62 // Write 0 to clear.
94 } 63 let mut clear = regs::Istr(!0);
95 if epr.ctr_tx() { 64 clear.set_wkup(false);
96 //trace!("EP {} TX", index); 65 regs.istr().write_value(clear);
97 EP_IN_WAKERS[index].wake(); 66
67 // Wake main thread.
68 BUS_WAKER.wake();
69 }
70
71 if istr.reset() {
72 //trace!("USB IRQ: reset");
73 IRQ_RESET.store(true, Ordering::Relaxed);
74
75 // Write 0 to clear.
76 let mut clear = regs::Istr(!0);
77 clear.set_reset(false);
78 regs.istr().write_value(clear);
79
80 // Wake main thread.
81 BUS_WAKER.wake();
82 }
83
84 if istr.ctr() {
85 let index = istr.ep_id() as usize;
86 let mut epr = regs.epr(index).read();
87 if epr.ctr_rx() {
88 if index == 0 && epr.setup() {
89 EP0_SETUP.store(true, Ordering::Relaxed);
98 } 90 }
99 epr.set_dtog_rx(false); 91 //trace!("EP {} RX, setup={}", index, epr.setup());
100 epr.set_dtog_tx(false); 92 EP_OUT_WAKERS[index].wake();
101 epr.set_stat_rx(Stat(0)); 93 }
102 epr.set_stat_tx(Stat(0)); 94 if epr.ctr_tx() {
103 epr.set_ctr_rx(!epr.ctr_rx()); 95 //trace!("EP {} TX", index);
104 epr.set_ctr_tx(!epr.ctr_tx()); 96 EP_IN_WAKERS[index].wake();
105 regs.epr(index).write_value(epr);
106 } 97 }
98 epr.set_dtog_rx(false);
99 epr.set_dtog_tx(false);
100 epr.set_stat_rx(Stat(0));
101 epr.set_stat_tx(Stat(0));
102 epr.set_ctr_rx(!epr.ctr_rx());
103 epr.set_ctr_tx(!epr.ctr_tx());
104 regs.epr(index).write_value(epr);
107 } 105 }
108 } 106 }
109} 107}
@@ -168,20 +166,20 @@ fn calc_out_len(len: u16) -> (u16, u16) {
168mod btable { 166mod btable {
169 use super::*; 167 use super::*;
170 168
171 pub(super) unsafe fn write_in<T: Instance>(index: usize, addr: u16) { 169 pub(super) fn write_in<T: Instance>(index: usize, addr: u16) {
172 USBRAM.mem(index * 4 + 0).write_value(addr); 170 USBRAM.mem(index * 4 + 0).write_value(addr);
173 } 171 }
174 172
175 pub(super) unsafe fn write_in_len<T: Instance>(index: usize, _addr: u16, len: u16) { 173 pub(super) fn write_in_len<T: Instance>(index: usize, _addr: u16, len: u16) {
176 USBRAM.mem(index * 4 + 1).write_value(len); 174 USBRAM.mem(index * 4 + 1).write_value(len);
177 } 175 }
178 176
179 pub(super) unsafe fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) { 177 pub(super) fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) {
180 USBRAM.mem(index * 4 + 2).write_value(addr); 178 USBRAM.mem(index * 4 + 2).write_value(addr);
181 USBRAM.mem(index * 4 + 3).write_value(max_len_bits); 179 USBRAM.mem(index * 4 + 3).write_value(max_len_bits);
182 } 180 }
183 181
184 pub(super) unsafe fn read_out_len<T: Instance>(index: usize) -> u16 { 182 pub(super) fn read_out_len<T: Instance>(index: usize) -> u16 {
185 USBRAM.mem(index * 4 + 3).read() 183 USBRAM.mem(index * 4 + 3).read()
186 } 184 }
187} 185}
@@ -189,19 +187,19 @@ mod btable {
189mod btable { 187mod btable {
190 use super::*; 188 use super::*;
191 189
192 pub(super) unsafe fn write_in<T: Instance>(_index: usize, _addr: u16) {} 190 pub(super) fn write_in<T: Instance>(_index: usize, _addr: u16) {}
193 191
194 pub(super) unsafe fn write_in_len<T: Instance>(index: usize, addr: u16, len: u16) { 192 pub(super) fn write_in_len<T: Instance>(index: usize, addr: u16, len: u16) {
195 USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16)); 193 USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16));
196 } 194 }
197 195
198 pub(super) unsafe fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) { 196 pub(super) fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) {
199 USBRAM 197 USBRAM
200 .mem(index * 2 + 1) 198 .mem(index * 2 + 1)
201 .write_value((addr as u32) | ((max_len_bits as u32) << 16)); 199 .write_value((addr as u32) | ((max_len_bits as u32) << 16));
202 } 200 }
203 201
204 pub(super) unsafe fn read_out_len<T: Instance>(index: usize) -> u16 { 202 pub(super) fn read_out_len<T: Instance>(index: usize) -> u16 {
205 (USBRAM.mem(index * 2 + 1).read() >> 16) as u16 203 (USBRAM.mem(index * 2 + 1).read() >> 16) as u16
206 } 204 }
207} 205}
@@ -216,7 +214,7 @@ impl<T: Instance> EndpointBuffer<T> {
216 fn read(&mut self, buf: &mut [u8]) { 214 fn read(&mut self, buf: &mut [u8]) {
217 assert!(buf.len() <= self.len as usize); 215 assert!(buf.len() <= self.len as usize);
218 for i in 0..(buf.len() + USBRAM_ALIGN - 1) / USBRAM_ALIGN { 216 for i in 0..(buf.len() + USBRAM_ALIGN - 1) / USBRAM_ALIGN {
219 let val = unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read() }; 217 let val = USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read();
220 let n = USBRAM_ALIGN.min(buf.len() - i * USBRAM_ALIGN); 218 let n = USBRAM_ALIGN.min(buf.len() - i * USBRAM_ALIGN);
221 buf[i * USBRAM_ALIGN..][..n].copy_from_slice(&val.to_le_bytes()[..n]); 219 buf[i * USBRAM_ALIGN..][..n].copy_from_slice(&val.to_le_bytes()[..n]);
222 } 220 }
@@ -233,7 +231,7 @@ impl<T: Instance> EndpointBuffer<T> {
233 let val = u16::from_le_bytes(val); 231 let val = u16::from_le_bytes(val);
234 #[cfg(usbram_32_2048)] 232 #[cfg(usbram_32_2048)]
235 let val = u32::from_le_bytes(val); 233 let val = u32::from_le_bytes(val);
236 unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val) }; 234 USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val);
237 } 235 }
238 } 236 }
239} 237}
@@ -266,36 +264,32 @@ impl<'d, T: Instance> Driver<'d, T> {
266 let regs = T::regs(); 264 let regs = T::regs();
267 265
268 #[cfg(stm32l5)] 266 #[cfg(stm32l5)]
269 unsafe { 267 {
270 crate::peripherals::PWR::enable(); 268 crate::peripherals::PWR::enable();
271 crate::pac::PWR.cr2().modify(|w| w.set_usv(true)); 269 crate::pac::PWR.cr2().modify(|w| w.set_usv(true));
272 } 270 }
273 271
274 #[cfg(pwr_h5)] 272 #[cfg(pwr_h5)]
275 unsafe { 273 crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true));
276 crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true))
277 }
278 274
279 unsafe { 275 <T as RccPeripheral>::enable();
280 <T as RccPeripheral>::enable(); 276 <T as RccPeripheral>::reset();
281 <T as RccPeripheral>::reset();
282 277
283 regs.cntr().write(|w| { 278 regs.cntr().write(|w| {
284 w.set_pdwn(false); 279 w.set_pdwn(false);
285 w.set_fres(true); 280 w.set_fres(true);
286 }); 281 });
287 282
288 #[cfg(time)] 283 #[cfg(time)]
289 embassy_time::block_for(embassy_time::Duration::from_millis(100)); 284 embassy_time::block_for(embassy_time::Duration::from_millis(100));
290 #[cfg(not(time))] 285 #[cfg(not(time))]
291 cortex_m::asm::delay(crate::rcc::get_freqs().sys.0 / 10); 286 cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.0 / 10);
292 287
293 #[cfg(not(usb_v4))] 288 #[cfg(not(usb_v4))]
294 regs.btable().write(|w| w.set_btable(0)); 289 regs.btable().write(|w| w.set_btable(0));
295 290
296 dp.set_as_af(dp.af_num(), AFType::OutputPushPull); 291 dp.set_as_af(dp.af_num(), AFType::OutputPushPull);
297 dm.set_as_af(dm.af_num(), AFType::OutputPushPull); 292 dm.set_as_af(dm.af_num(), AFType::OutputPushPull);
298 }
299 293
300 // Initialize the bus so that it signals that power is available 294 // Initialize the bus so that it signals that power is available
301 BUS_WAKER.wake(); 295 BUS_WAKER.wake();
@@ -363,7 +357,7 @@ impl<'d, T: Instance> Driver<'d, T> {
363 let addr = self.alloc_ep_mem(len); 357 let addr = self.alloc_ep_mem(len);
364 358
365 trace!(" len_bits = {:04x}", len_bits); 359 trace!(" len_bits = {:04x}", len_bits);
366 unsafe { btable::write_out::<T>(index, addr, len_bits) } 360 btable::write_out::<T>(index, addr, len_bits);
367 361
368 EndpointBuffer { 362 EndpointBuffer {
369 addr, 363 addr,
@@ -379,7 +373,7 @@ impl<'d, T: Instance> Driver<'d, T> {
379 let addr = self.alloc_ep_mem(len); 373 let addr = self.alloc_ep_mem(len);
380 374
381 // ep_in_len is written when actually TXing packets. 375 // ep_in_len is written when actually TXing packets.
382 unsafe { btable::write_in::<T>(index, addr) } 376 btable::write_in::<T>(index, addr);
383 377
384 EndpointBuffer { 378 EndpointBuffer {
385 addr, 379 addr,
@@ -440,19 +434,17 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
440 434
441 let regs = T::regs(); 435 let regs = T::regs();
442 436
443 unsafe { 437 regs.cntr().write(|w| {
444 regs.cntr().write(|w| { 438 w.set_pdwn(false);
445 w.set_pdwn(false); 439 w.set_fres(false);
446 w.set_fres(false); 440 w.set_resetm(true);
447 w.set_resetm(true); 441 w.set_suspm(true);
448 w.set_suspm(true); 442 w.set_wkupm(true);
449 w.set_wkupm(true); 443 w.set_ctrm(true);
450 w.set_ctrm(true); 444 });
451 });
452 445
453 #[cfg(any(usb_v3, usb_v4))] 446 #[cfg(any(usb_v3, usb_v4))]
454 regs.bcdr().write(|w| w.set_dppu(true)) 447 regs.bcdr().write(|w| w.set_dppu(true));
455 }
456 448
457 trace!("enabled"); 449 trace!("enabled");
458 450
@@ -485,7 +477,7 @@ pub struct Bus<'d, T: Instance> {
485 477
486impl<'d, T: Instance> driver::Bus for Bus<'d, T> { 478impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
487 async fn poll(&mut self) -> Event { 479 async fn poll(&mut self) -> Event {
488 poll_fn(move |cx| unsafe { 480 poll_fn(move |cx| {
489 BUS_WAKER.register(cx.waker()); 481 BUS_WAKER.register(cx.waker());
490 482
491 if self.inited { 483 if self.inited {
@@ -548,7 +540,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
548 match ep_addr.direction() { 540 match ep_addr.direction() {
549 Direction::In => { 541 Direction::In => {
550 loop { 542 loop {
551 let r = unsafe { reg.read() }; 543 let r = reg.read();
552 match r.stat_tx() { 544 match r.stat_tx() {
553 Stat::DISABLED => break, // if disabled, stall does nothing. 545 Stat::DISABLED => break, // if disabled, stall does nothing.
554 Stat::STALL => break, // done! 546 Stat::STALL => break, // done!
@@ -559,7 +551,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
559 }; 551 };
560 let mut w = invariant(r); 552 let mut w = invariant(r);
561 w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); 553 w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0));
562 unsafe { reg.write_value(w) }; 554 reg.write_value(w);
563 } 555 }
564 } 556 }
565 } 557 }
@@ -567,7 +559,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
567 } 559 }
568 Direction::Out => { 560 Direction::Out => {
569 loop { 561 loop {
570 let r = unsafe { reg.read() }; 562 let r = reg.read();
571 match r.stat_rx() { 563 match r.stat_rx() {
572 Stat::DISABLED => break, // if disabled, stall does nothing. 564 Stat::DISABLED => break, // if disabled, stall does nothing.
573 Stat::STALL => break, // done! 565 Stat::STALL => break, // done!
@@ -578,7 +570,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
578 }; 570 };
579 let mut w = invariant(r); 571 let mut w = invariant(r);
580 w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); 572 w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0));
581 unsafe { reg.write_value(w) }; 573 reg.write_value(w);
582 } 574 }
583 } 575 }
584 } 576 }
@@ -589,7 +581,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
589 581
590 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool { 582 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
591 let regs = T::regs(); 583 let regs = T::regs();
592 let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; 584 let epr = regs.epr(ep_addr.index() as _).read();
593 match ep_addr.direction() { 585 match ep_addr.direction() {
594 Direction::In => epr.stat_tx() == Stat::STALL, 586 Direction::In => epr.stat_tx() == Stat::STALL,
595 Direction::Out => epr.stat_rx() == Stat::STALL, 587 Direction::Out => epr.stat_rx() == Stat::STALL,
@@ -600,7 +592,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
600 trace!("set_enabled {:x} {}", ep_addr, enabled); 592 trace!("set_enabled {:x} {}", ep_addr, enabled);
601 // This can race, so do a retry loop. 593 // This can race, so do a retry loop.
602 let reg = T::regs().epr(ep_addr.index() as _); 594 let reg = T::regs().epr(ep_addr.index() as _);
603 trace!("EPR before: {:04x}", unsafe { reg.read() }.0); 595 trace!("EPR before: {:04x}", reg.read().0);
604 match ep_addr.direction() { 596 match ep_addr.direction() {
605 Direction::In => { 597 Direction::In => {
606 loop { 598 loop {
@@ -608,13 +600,13 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
608 false => Stat::DISABLED, 600 false => Stat::DISABLED,
609 true => Stat::NAK, 601 true => Stat::NAK,
610 }; 602 };
611 let r = unsafe { reg.read() }; 603 let r = reg.read();
612 if r.stat_tx() == want_stat { 604 if r.stat_tx() == want_stat {
613 break; 605 break;
614 } 606 }
615 let mut w = invariant(r); 607 let mut w = invariant(r);
616 w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); 608 w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0));
617 unsafe { reg.write_value(w) }; 609 reg.write_value(w);
618 } 610 }
619 EP_IN_WAKERS[ep_addr.index()].wake(); 611 EP_IN_WAKERS[ep_addr.index()].wake();
620 } 612 }
@@ -624,18 +616,18 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
624 false => Stat::DISABLED, 616 false => Stat::DISABLED,
625 true => Stat::VALID, 617 true => Stat::VALID,
626 }; 618 };
627 let r = unsafe { reg.read() }; 619 let r = reg.read();
628 if r.stat_rx() == want_stat { 620 if r.stat_rx() == want_stat {
629 break; 621 break;
630 } 622 }
631 let mut w = invariant(r); 623 let mut w = invariant(r);
632 w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); 624 w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0));
633 unsafe { reg.write_value(w) }; 625 reg.write_value(w);
634 } 626 }
635 EP_OUT_WAKERS[ep_addr.index()].wake(); 627 EP_OUT_WAKERS[ep_addr.index()].wake();
636 } 628 }
637 } 629 }
638 trace!("EPR after: {:04x}", unsafe { reg.read() }.0); 630 trace!("EPR after: {:04x}", reg.read().0);
639 } 631 }
640 632
641 async fn enable(&mut self) {} 633 async fn enable(&mut self) {}
@@ -685,12 +677,12 @@ impl<'d, T: Instance, D> Endpoint<'d, T, D> {
685 fn write_data(&mut self, buf: &[u8]) { 677 fn write_data(&mut self, buf: &[u8]) {
686 let index = self.info.addr.index(); 678 let index = self.info.addr.index();
687 self.buf.write(buf); 679 self.buf.write(buf);
688 unsafe { btable::write_in_len::<T>(index, self.buf.addr, buf.len() as _) } 680 btable::write_in_len::<T>(index, self.buf.addr, buf.len() as _);
689 } 681 }
690 682
691 fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> { 683 fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
692 let index = self.info.addr.index(); 684 let index = self.info.addr.index();
693 let rx_len = unsafe { btable::read_out_len::<T>(index) as usize } & 0x3FF; 685 let rx_len = btable::read_out_len::<T>(index) as usize & 0x3FF;
694 trace!("READ DONE, rx_len = {}", rx_len); 686 trace!("READ DONE, rx_len = {}", rx_len);
695 if rx_len > buf.len() { 687 if rx_len > buf.len() {
696 return Err(EndpointError::BufferOverflow); 688 return Err(EndpointError::BufferOverflow);
@@ -711,7 +703,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> {
711 poll_fn(|cx| { 703 poll_fn(|cx| {
712 EP_OUT_WAKERS[index].register(cx.waker()); 704 EP_OUT_WAKERS[index].register(cx.waker());
713 let regs = T::regs(); 705 let regs = T::regs();
714 if unsafe { regs.epr(index).read() }.stat_tx() == Stat::DISABLED { 706 if regs.epr(index).read().stat_tx() == Stat::DISABLED {
715 Poll::Pending 707 Poll::Pending
716 } else { 708 } else {
717 Poll::Ready(()) 709 Poll::Ready(())
@@ -733,7 +725,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, Out> {
733 poll_fn(|cx| { 725 poll_fn(|cx| {
734 EP_OUT_WAKERS[index].register(cx.waker()); 726 EP_OUT_WAKERS[index].register(cx.waker());
735 let regs = T::regs(); 727 let regs = T::regs();
736 if unsafe { regs.epr(index).read() }.stat_rx() == Stat::DISABLED { 728 if regs.epr(index).read().stat_rx() == Stat::DISABLED {
737 Poll::Pending 729 Poll::Pending
738 } else { 730 } else {
739 Poll::Ready(()) 731 Poll::Ready(())
@@ -751,7 +743,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
751 let stat = poll_fn(|cx| { 743 let stat = poll_fn(|cx| {
752 EP_OUT_WAKERS[index].register(cx.waker()); 744 EP_OUT_WAKERS[index].register(cx.waker());
753 let regs = T::regs(); 745 let regs = T::regs();
754 let stat = unsafe { regs.epr(index).read() }.stat_rx(); 746 let stat = regs.epr(index).read().stat_rx();
755 if matches!(stat, Stat::NAK | Stat::DISABLED) { 747 if matches!(stat, Stat::NAK | Stat::DISABLED) {
756 Poll::Ready(stat) 748 Poll::Ready(stat)
757 } else { 749 } else {
@@ -767,16 +759,14 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
767 let rx_len = self.read_data(buf)?; 759 let rx_len = self.read_data(buf)?;
768 760
769 let regs = T::regs(); 761 let regs = T::regs();
770 unsafe { 762 regs.epr(index).write(|w| {
771 regs.epr(index).write(|w| { 763 w.set_ep_type(convert_type(self.info.ep_type));
772 w.set_ep_type(convert_type(self.info.ep_type)); 764 w.set_ea(self.info.addr.index() as _);
773 w.set_ea(self.info.addr.index() as _); 765 w.set_stat_rx(Stat(Stat::NAK.0 ^ Stat::VALID.0));
774 w.set_stat_rx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); 766 w.set_stat_tx(Stat(0));
775 w.set_stat_tx(Stat(0)); 767 w.set_ctr_rx(true); // don't clear
776 w.set_ctr_rx(true); // don't clear 768 w.set_ctr_tx(true); // don't clear
777 w.set_ctr_tx(true); // don't clear 769 });
778 })
779 };
780 trace!("READ OK, rx_len = {}", rx_len); 770 trace!("READ OK, rx_len = {}", rx_len);
781 771
782 Ok(rx_len) 772 Ok(rx_len)
@@ -795,7 +785,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
795 let stat = poll_fn(|cx| { 785 let stat = poll_fn(|cx| {
796 EP_IN_WAKERS[index].register(cx.waker()); 786 EP_IN_WAKERS[index].register(cx.waker());
797 let regs = T::regs(); 787 let regs = T::regs();
798 let stat = unsafe { regs.epr(index).read() }.stat_tx(); 788 let stat = regs.epr(index).read().stat_tx();
799 if matches!(stat, Stat::NAK | Stat::DISABLED) { 789 if matches!(stat, Stat::NAK | Stat::DISABLED) {
800 Poll::Ready(stat) 790 Poll::Ready(stat)
801 } else { 791 } else {
@@ -811,16 +801,14 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
811 self.write_data(buf); 801 self.write_data(buf);
812 802
813 let regs = T::regs(); 803 let regs = T::regs();
814 unsafe { 804 regs.epr(index).write(|w| {
815 regs.epr(index).write(|w| { 805 w.set_ep_type(convert_type(self.info.ep_type));
816 w.set_ep_type(convert_type(self.info.ep_type)); 806 w.set_ea(self.info.addr.index() as _);
817 w.set_ea(self.info.addr.index() as _); 807 w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0));
818 w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); 808 w.set_stat_rx(Stat(0));
819 w.set_stat_rx(Stat(0)); 809 w.set_ctr_rx(true); // don't clear
820 w.set_ctr_rx(true); // don't clear 810 w.set_ctr_tx(true); // don't clear
821 w.set_ctr_tx(true); // don't clear 811 });
822 })
823 };
824 812
825 trace!("WRITE OK"); 813 trace!("WRITE OK");
826 814
@@ -889,22 +877,20 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
889 } 877 }
890 // Note: if this is the first AND last transfer, the above effectively 878 // Note: if this is the first AND last transfer, the above effectively
891 // changes stat_tx like NAK -> NAK, so noop. 879 // changes stat_tx like NAK -> NAK, so noop.
892 unsafe { 880 regs.epr(0).write(|w| {
893 regs.epr(0).write(|w| { 881 w.set_ep_type(EpType::CONTROL);
894 w.set_ep_type(EpType::CONTROL); 882 w.set_stat_rx(Stat(stat_rx));
895 w.set_stat_rx(Stat(stat_rx)); 883 w.set_stat_tx(Stat(stat_tx));
896 w.set_stat_tx(Stat(stat_tx)); 884 w.set_ctr_rx(true); // don't clear
897 w.set_ctr_rx(true); // don't clear 885 w.set_ctr_tx(true); // don't clear
898 w.set_ctr_tx(true); // don't clear 886 });
899 })
900 }
901 } 887 }
902 888
903 trace!("data_out WAITING, buf.len() = {}", buf.len()); 889 trace!("data_out WAITING, buf.len() = {}", buf.len());
904 poll_fn(|cx| { 890 poll_fn(|cx| {
905 EP_OUT_WAKERS[0].register(cx.waker()); 891 EP_OUT_WAKERS[0].register(cx.waker());
906 let regs = T::regs(); 892 let regs = T::regs();
907 if unsafe { regs.epr(0).read() }.stat_rx() == Stat::NAK { 893 if regs.epr(0).read().stat_rx() == Stat::NAK {
908 Poll::Ready(()) 894 Poll::Ready(())
909 } else { 895 } else {
910 Poll::Pending 896 Poll::Pending
@@ -919,19 +905,17 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
919 905
920 let rx_len = self.ep_out.read_data(buf)?; 906 let rx_len = self.ep_out.read_data(buf)?;
921 907
922 unsafe { 908 regs.epr(0).write(|w| {
923 regs.epr(0).write(|w| { 909 w.set_ep_type(EpType::CONTROL);
924 w.set_ep_type(EpType::CONTROL); 910 w.set_stat_rx(Stat(match last {
925 w.set_stat_rx(Stat(match last { 911 // If last, set STAT_RX=STALL.
926 // If last, set STAT_RX=STALL. 912 true => Stat::NAK.0 ^ Stat::STALL.0,
927 true => Stat::NAK.0 ^ Stat::STALL.0, 913 // Otherwise, set STAT_RX=VALID, to allow the host to send the next packet.
928 // Otherwise, set STAT_RX=VALID, to allow the host to send the next packet. 914 false => Stat::NAK.0 ^ Stat::VALID.0,
929 false => Stat::NAK.0 ^ Stat::VALID.0, 915 }));
930 })); 916 w.set_ctr_rx(true); // don't clear
931 w.set_ctr_rx(true); // don't clear 917 w.set_ctr_tx(true); // don't clear
932 w.set_ctr_tx(true); // don't clear 918 });
933 })
934 };
935 919
936 Ok(rx_len) 920 Ok(rx_len)
937 } 921 }
@@ -960,15 +944,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
960 } 944 }
961 // Note: if this is the first AND last transfer, the above effectively 945 // Note: if this is the first AND last transfer, the above effectively
962 // does a change of NAK -> VALID. 946 // does a change of NAK -> VALID.
963 unsafe { 947 regs.epr(0).write(|w| {
964 regs.epr(0).write(|w| { 948 w.set_ep_type(EpType::CONTROL);
965 w.set_ep_type(EpType::CONTROL); 949 w.set_stat_rx(Stat(stat_rx));
966 w.set_stat_rx(Stat(stat_rx)); 950 w.set_ep_kind(last); // set OUT_STATUS if last.
967 w.set_ep_kind(last); // set OUT_STATUS if last. 951 w.set_ctr_rx(true); // don't clear
968 w.set_ctr_rx(true); // don't clear 952 w.set_ctr_tx(true); // don't clear
969 w.set_ctr_tx(true); // don't clear 953 });
970 })
971 }
972 } 954 }
973 955
974 trace!("WRITE WAITING"); 956 trace!("WRITE WAITING");
@@ -976,7 +958,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
976 EP_IN_WAKERS[0].register(cx.waker()); 958 EP_IN_WAKERS[0].register(cx.waker());
977 EP_OUT_WAKERS[0].register(cx.waker()); 959 EP_OUT_WAKERS[0].register(cx.waker());
978 let regs = T::regs(); 960 let regs = T::regs();
979 if unsafe { regs.epr(0).read() }.stat_tx() == Stat::NAK { 961 if regs.epr(0).read().stat_tx() == Stat::NAK {
980 Poll::Ready(()) 962 Poll::Ready(())
981 } else { 963 } else {
982 Poll::Pending 964 Poll::Pending
@@ -992,15 +974,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
992 self.ep_in.write_data(data); 974 self.ep_in.write_data(data);
993 975
994 let regs = T::regs(); 976 let regs = T::regs();
995 unsafe { 977 regs.epr(0).write(|w| {
996 regs.epr(0).write(|w| { 978 w.set_ep_type(EpType::CONTROL);
997 w.set_ep_type(EpType::CONTROL); 979 w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0));
998 w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); 980 w.set_ep_kind(last); // set OUT_STATUS if last.
999 w.set_ep_kind(last); // set OUT_STATUS if last. 981 w.set_ctr_rx(true); // don't clear
1000 w.set_ctr_rx(true); // don't clear 982 w.set_ctr_tx(true); // don't clear
1001 w.set_ctr_tx(true); // don't clear 983 });
1002 })
1003 };
1004 984
1005 trace!("WRITE OK"); 985 trace!("WRITE OK");
1006 986
@@ -1014,16 +994,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
1014 self.ep_in.write_data(&[]); 994 self.ep_in.write_data(&[]);
1015 995
1016 // Set OUT=stall, IN=accept 996 // Set OUT=stall, IN=accept
1017 unsafe { 997 let epr = regs.epr(0).read();
1018 let epr = regs.epr(0).read(); 998 regs.epr(0).write(|w| {
1019 regs.epr(0).write(|w| { 999 w.set_ep_type(EpType::CONTROL);
1020 w.set_ep_type(EpType::CONTROL); 1000 w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0));
1021 w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); 1001 w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::VALID.0));
1022 w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::VALID.0)); 1002 w.set_ctr_rx(true); // don't clear
1023 w.set_ctr_rx(true); // don't clear 1003 w.set_ctr_tx(true); // don't clear
1024 w.set_ctr_tx(true); // don't clear 1004 });
1025 });
1026 }
1027 trace!("control: accept WAITING"); 1005 trace!("control: accept WAITING");
1028 1006
1029 // Wait is needed, so that we don't set the address too soon, breaking the status stage. 1007 // Wait is needed, so that we don't set the address too soon, breaking the status stage.
@@ -1031,7 +1009,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
1031 poll_fn(|cx| { 1009 poll_fn(|cx| {
1032 EP_IN_WAKERS[0].register(cx.waker()); 1010 EP_IN_WAKERS[0].register(cx.waker());
1033 let regs = T::regs(); 1011 let regs = T::regs();
1034 if unsafe { regs.epr(0).read() }.stat_tx() == Stat::NAK { 1012 if regs.epr(0).read().stat_tx() == Stat::NAK {
1035 Poll::Ready(()) 1013 Poll::Ready(())
1036 } else { 1014 } else {
1037 Poll::Pending 1015 Poll::Pending
@@ -1047,16 +1025,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
1047 trace!("control: reject"); 1025 trace!("control: reject");
1048 1026
1049 // Set IN+OUT to stall 1027 // Set IN+OUT to stall
1050 unsafe { 1028 let epr = regs.epr(0).read();
1051 let epr = regs.epr(0).read(); 1029 regs.epr(0).write(|w| {
1052 regs.epr(0).write(|w| { 1030 w.set_ep_type(EpType::CONTROL);
1053 w.set_ep_type(EpType::CONTROL); 1031 w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0));
1054 w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); 1032 w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::STALL.0));
1055 w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::STALL.0)); 1033 w.set_ctr_rx(true); // don't clear
1056 w.set_ctr_rx(true); // don't clear 1034 w.set_ctr_tx(true); // don't clear
1057 w.set_ctr_tx(true); // don't clear 1035 });
1058 });
1059 }
1060 } 1036 }
1061 1037
1062 async fn accept_set_address(&mut self, addr: u8) { 1038 async fn accept_set_address(&mut self, addr: u8) {
@@ -1064,11 +1040,9 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
1064 1040
1065 let regs = T::regs(); 1041 let regs = T::regs();
1066 trace!("setting addr: {}", addr); 1042 trace!("setting addr: {}", addr);
1067 unsafe { 1043 regs.daddr().write(|w| {
1068 regs.daddr().write(|w| { 1044 w.set_ef(true);
1069 w.set_ef(true); 1045 w.set_add(addr);
1070 w.set_add(addr); 1046 });
1071 })
1072 }
1073 } 1047 }
1074} 1048}
diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs
index 317264cbb..12e5f0e60 100644
--- a/embassy-stm32/src/usb_otg/mod.rs
+++ b/embassy-stm32/src/usb_otg/mod.rs
@@ -148,7 +148,7 @@ foreach_interrupt!(
148 148
149 fn regs() -> crate::pac::otg::Otg { 149 fn regs() -> crate::pac::otg::Otg {
150 // OTG HS registers are a superset of FS registers 150 // OTG HS registers are a superset of FS registers
151 crate::pac::otg::Otg(crate::pac::USB_OTG_HS.0) 151 unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) }
152 } 152 }
153 153
154 #[cfg(feature = "nightly")] 154 #[cfg(feature = "nightly")]
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index 16cbf1a95..8af5c7bd5 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -30,19 +30,16 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
30 let r = T::regs(); 30 let r = T::regs();
31 let state = T::state(); 31 let state = T::state();
32 32
33 // SAFETY: atomic read/write 33 let ints = r.gintsts().read();
34 let ints = unsafe { r.gintsts().read() };
35 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() { 34 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() {
36 // Mask interrupts and notify `Bus` to process them 35 // Mask interrupts and notify `Bus` to process them
37 unsafe { r.gintmsk().write(|_| {}) }; 36 r.gintmsk().write(|_| {});
38 T::state().bus_waker.wake(); 37 T::state().bus_waker.wake();
39 } 38 }
40 39
41 // Handle RX 40 // Handle RX
42 // SAFETY: atomic read with no side effects 41 while r.gintsts().read().rxflvl() {
43 while unsafe { r.gintsts().read().rxflvl() } { 42 let status = r.grxstsp().read();
44 // SAFETY: atomic "pop" register
45 let status = unsafe { r.grxstsp().read() };
46 let ep_num = status.epnum() as usize; 43 let ep_num = status.epnum() as usize;
47 let len = status.bcnt() as usize; 44 let len = status.bcnt() as usize;
48 45
@@ -57,21 +54,15 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
57 if state.ep0_setup_ready.load(Ordering::Relaxed) == false { 54 if state.ep0_setup_ready.load(Ordering::Relaxed) == false {
58 // SAFETY: exclusive access ensured by atomic bool 55 // SAFETY: exclusive access ensured by atomic bool
59 let data = unsafe { &mut *state.ep0_setup_data.get() }; 56 let data = unsafe { &mut *state.ep0_setup_data.get() };
60 // SAFETY: FIFO reads are exclusive to this IRQ 57 data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
61 unsafe { 58 data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
62 data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
63 data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
64 }
65 state.ep0_setup_ready.store(true, Ordering::Release); 59 state.ep0_setup_ready.store(true, Ordering::Release);
66 state.ep_out_wakers[0].wake(); 60 state.ep_out_wakers[0].wake();
67 } else { 61 } else {
68 error!("received SETUP before previous finished processing"); 62 error!("received SETUP before previous finished processing");
69 // discard FIFO 63 // discard FIFO
70 // SAFETY: FIFO reads are exclusive to IRQ 64 r.fifo(0).read();
71 unsafe { 65 r.fifo(0).read();
72 r.fifo(0).read();
73 r.fifo(0).read();
74 }
75 } 66 }
76 } 67 }
77 vals::Pktstsd::OUT_DATA_RX => { 68 vals::Pktstsd::OUT_DATA_RX => {
@@ -84,8 +75,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
84 75
85 for chunk in buf.chunks_mut(4) { 76 for chunk in buf.chunks_mut(4) {
86 // RX FIFO is shared so always read from fifo(0) 77 // RX FIFO is shared so always read from fifo(0)
87 // SAFETY: FIFO reads are exclusive to IRQ 78 let data = r.fifo(0).read().0;
88 let data = unsafe { r.fifo(0).read().0 };
89 chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]); 79 chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]);
90 } 80 }
91 81
@@ -97,8 +87,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
97 // discard FIFO data 87 // discard FIFO data
98 let len_words = (len + 3) / 4; 88 let len_words = (len + 3) / 4;
99 for _ in 0..len_words { 89 for _ in 0..len_words {
100 // SAFETY: FIFO reads are exclusive to IRQ 90 r.fifo(0).read().data();
101 unsafe { r.fifo(0).read().data() };
102 } 91 }
103 } 92 }
104 } 93 }
@@ -114,24 +103,20 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
114 103
115 // IN endpoint interrupt 104 // IN endpoint interrupt
116 if ints.iepint() { 105 if ints.iepint() {
117 // SAFETY: atomic read with no side effects 106 let mut ep_mask = r.daint().read().iepint();
118 let mut ep_mask = unsafe { r.daint().read().iepint() };
119 let mut ep_num = 0; 107 let mut ep_num = 0;
120 108
121 // Iterate over endpoints while there are non-zero bits in the mask 109 // Iterate over endpoints while there are non-zero bits in the mask
122 while ep_mask != 0 { 110 while ep_mask != 0 {
123 if ep_mask & 1 != 0 { 111 if ep_mask & 1 != 0 {
124 // SAFETY: atomic read with no side effects 112 let ep_ints = r.diepint(ep_num).read();
125 let ep_ints = unsafe { r.diepint(ep_num).read() };
126 113
127 // clear all 114 // clear all
128 // SAFETY: DIEPINT is exclusive to IRQ 115 r.diepint(ep_num).write_value(ep_ints);
129 unsafe { r.diepint(ep_num).write_value(ep_ints) };
130 116
131 // TXFE is cleared in DIEPEMPMSK 117 // TXFE is cleared in DIEPEMPMSK
132 if ep_ints.txfe() { 118 if ep_ints.txfe() {
133 // SAFETY: DIEPEMPMSK is shared with `Endpoint` so critical section is needed for RMW 119 critical_section::with(|_| {
134 critical_section::with(|_| unsafe {
135 r.diepempmsk().modify(|w| { 120 r.diepempmsk().modify(|w| {
136 w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num)); 121 w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num));
137 }); 122 });
@@ -172,8 +157,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
172macro_rules! config_ulpi_pins { 157macro_rules! config_ulpi_pins {
173 ($($pin:ident),*) => { 158 ($($pin:ident),*) => {
174 into_ref!($($pin),*); 159 into_ref!($($pin),*);
175 // NOTE(unsafe) Exclusive access to the registers 160 critical_section::with(|_| {
176 critical_section::with(|_| unsafe {
177 $( 161 $(
178 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); 162 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
179 #[cfg(gpio_v2)] 163 #[cfg(gpio_v2)]
@@ -298,10 +282,8 @@ impl<'d, T: Instance> Driver<'d, T> {
298 ) -> Self { 282 ) -> Self {
299 into_ref!(dp, dm); 283 into_ref!(dp, dm);
300 284
301 unsafe { 285 dp.set_as_af(dp.af_num(), AFType::OutputPushPull);
302 dp.set_as_af(dp.af_num(), AFType::OutputPushPull); 286 dm.set_as_af(dm.af_num(), AFType::OutputPushPull);
303 dm.set_as_af(dm.af_num(), AFType::OutputPushPull);
304 }
305 287
306 Self { 288 Self {
307 phantom: PhantomData, 289 phantom: PhantomData,
@@ -508,18 +490,15 @@ pub struct Bus<'d, T: Instance> {
508 490
509impl<'d, T: Instance> Bus<'d, T> { 491impl<'d, T: Instance> Bus<'d, T> {
510 fn restore_irqs() { 492 fn restore_irqs() {
511 // SAFETY: atomic write 493 T::regs().gintmsk().write(|w| {
512 unsafe { 494 w.set_usbrst(true);
513 T::regs().gintmsk().write(|w| { 495 w.set_enumdnem(true);
514 w.set_usbrst(true); 496 w.set_usbsuspm(true);
515 w.set_enumdnem(true); 497 w.set_wuim(true);
516 w.set_usbsuspm(true); 498 w.set_iepint(true);
517 w.set_wuim(true); 499 w.set_oepint(true);
518 w.set_iepint(true); 500 w.set_rxflvlm(true);
519 w.set_oepint(true); 501 });
520 w.set_rxflvlm(true);
521 });
522 }
523 } 502 }
524} 503}
525 504
@@ -533,8 +512,7 @@ impl<'d, T: Instance> Bus<'d, T> {
533 let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out); 512 let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out);
534 trace!("configuring rx fifo size={}", rx_fifo_size_words); 513 trace!("configuring rx fifo size={}", rx_fifo_size_words);
535 514
536 // SAFETY: register is exclusive to `Bus` with `&mut self` 515 r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
537 unsafe { r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)) };
538 516
539 // Configure TX (USB in direction) fifo size for each endpoint 517 // Configure TX (USB in direction) fifo size for each endpoint
540 let mut fifo_top = rx_fifo_size_words; 518 let mut fifo_top = rx_fifo_size_words;
@@ -549,13 +527,10 @@ impl<'d, T: Instance> Bus<'d, T> {
549 527
550 let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) }; 528 let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) };
551 529
552 // SAFETY: register is exclusive to `Bus` with `&mut self` 530 dieptxf.write(|w| {
553 unsafe { 531 w.set_fd(ep.fifo_size_words);
554 dieptxf.write(|w| { 532 w.set_sa(fifo_top);
555 w.set_fd(ep.fifo_size_words); 533 });
556 w.set_sa(fifo_top);
557 });
558 }
559 534
560 fifo_top += ep.fifo_size_words; 535 fifo_top += ep.fifo_size_words;
561 } 536 }
@@ -575,8 +550,7 @@ impl<'d, T: Instance> Bus<'d, T> {
575 // Configure IN endpoints 550 // Configure IN endpoints
576 for (index, ep) in self.ep_in.iter().enumerate() { 551 for (index, ep) in self.ep_in.iter().enumerate() {
577 if let Some(ep) = ep { 552 if let Some(ep) = ep {
578 // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW 553 critical_section::with(|_| {
579 critical_section::with(|_| unsafe {
580 r.diepctl(index).write(|w| { 554 r.diepctl(index).write(|w| {
581 if index == 0 { 555 if index == 0 {
582 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); 556 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
@@ -593,8 +567,7 @@ impl<'d, T: Instance> Bus<'d, T> {
593 // Configure OUT endpoints 567 // Configure OUT endpoints
594 for (index, ep) in self.ep_out.iter().enumerate() { 568 for (index, ep) in self.ep_out.iter().enumerate() {
595 if let Some(ep) = ep { 569 if let Some(ep) = ep {
596 // SAFETY: DOEPCTL/DOEPTSIZ is shared with `Endpoint` so critical section is needed for RMW 570 critical_section::with(|_| {
597 critical_section::with(|_| unsafe {
598 r.doepctl(index).write(|w| { 571 r.doepctl(index).write(|w| {
599 if index == 0 { 572 if index == 0 {
600 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); 573 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
@@ -618,14 +591,11 @@ impl<'d, T: Instance> Bus<'d, T> {
618 } 591 }
619 592
620 // Enable IRQs for allocated endpoints 593 // Enable IRQs for allocated endpoints
621 // SAFETY: register is exclusive to `Bus` with `&mut self` 594 r.daintmsk().modify(|w| {
622 unsafe { 595 w.set_iepm(ep_irq_mask(&self.ep_in));
623 r.daintmsk().modify(|w| { 596 // OUT interrupts not used, handled in RXFLVL
624 w.set_iepm(ep_irq_mask(&self.ep_in)); 597 // w.set_oepm(ep_irq_mask(&self.ep_out));
625 // OUT interrupts not used, handled in RXFLVL 598 });
626 // w.set_oepm(ep_irq_mask(&self.ep_out));
627 });
628 }
629 } 599 }
630 600
631 fn disable(&mut self) { 601 fn disable(&mut self) {
@@ -634,10 +604,8 @@ impl<'d, T: Instance> Bus<'d, T> {
634 <T as RccPeripheral>::disable(); 604 <T as RccPeripheral>::disable();
635 605
636 #[cfg(stm32l4)] 606 #[cfg(stm32l4)]
637 unsafe { 607 crate::pac::PWR.cr2().modify(|w| w.set_usv(false));
638 crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); 608 // Cannot disable PWR, because other peripherals might be using it
639 // Cannot disable PWR, because other peripherals might be using it
640 }
641 } 609 }
642} 610}
643 611
@@ -653,7 +621,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
653 621
654 T::state().bus_waker.register(cx.waker()); 622 T::state().bus_waker.register(cx.waker());
655 623
656 let ints = unsafe { r.gintsts().read() }; 624 let ints = r.gintsts().read();
657 if ints.usbrst() { 625 if ints.usbrst() {
658 trace!("reset"); 626 trace!("reset");
659 627
@@ -661,34 +629,27 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
661 self.configure_endpoints(); 629 self.configure_endpoints();
662 630
663 // Reset address 631 // Reset address
664 // SAFETY: DCFG is shared with `ControlPipe` so critical section is needed for RMW 632 critical_section::with(|_| {
665 critical_section::with(|_| unsafe {
666 r.dcfg().modify(|w| { 633 r.dcfg().modify(|w| {
667 w.set_dad(0); 634 w.set_dad(0);
668 }); 635 });
669 }); 636 });
670 637
671 // SAFETY: atomic clear on rc_w1 register 638 r.gintsts().write(|w| w.set_usbrst(true)); // clear
672 unsafe { r.gintsts().write(|w| w.set_usbrst(true)) }; // clear
673 Self::restore_irqs(); 639 Self::restore_irqs();
674 } 640 }
675 641
676 if ints.enumdne() { 642 if ints.enumdne() {
677 trace!("enumdne"); 643 trace!("enumdne");
678 644
679 // SAFETY: atomic read with no side effects 645 let speed = r.dsts().read().enumspd();
680 let speed = unsafe { r.dsts().read().enumspd() };
681 trace!(" speed={}", speed.0); 646 trace!(" speed={}", speed.0);
682 647
683 // SAFETY: register is only accessed by `Bus` under `&mut self` 648 r.gusbcfg().modify(|w| {
684 unsafe { 649 w.set_trdt(calculate_trdt(speed, T::frequency()));
685 r.gusbcfg().modify(|w| { 650 });
686 w.set_trdt(calculate_trdt(speed, T::frequency()));
687 })
688 };
689 651
690 // SAFETY: atomic clear on rc_w1 register 652 r.gintsts().write(|w| w.set_enumdne(true)); // clear
691 unsafe { r.gintsts().write(|w| w.set_enumdne(true)) }; // clear
692 Self::restore_irqs(); 653 Self::restore_irqs();
693 654
694 return Poll::Ready(Event::Reset); 655 return Poll::Ready(Event::Reset);
@@ -696,16 +657,14 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
696 657
697 if ints.usbsusp() { 658 if ints.usbsusp() {
698 trace!("suspend"); 659 trace!("suspend");
699 // SAFETY: atomic clear on rc_w1 register 660 r.gintsts().write(|w| w.set_usbsusp(true)); // clear
700 unsafe { r.gintsts().write(|w| w.set_usbsusp(true)) }; // clear
701 Self::restore_irqs(); 661 Self::restore_irqs();
702 return Poll::Ready(Event::Suspend); 662 return Poll::Ready(Event::Suspend);
703 } 663 }
704 664
705 if ints.wkupint() { 665 if ints.wkupint() {
706 trace!("resume"); 666 trace!("resume");
707 // SAFETY: atomic clear on rc_w1 register 667 r.gintsts().write(|w| w.set_wkupint(true)); // clear
708 unsafe { r.gintsts().write(|w| w.set_wkupint(true)) }; // clear
709 Self::restore_irqs(); 668 Self::restore_irqs();
710 return Poll::Ready(Event::Resume); 669 return Poll::Ready(Event::Resume);
711 } 670 }
@@ -727,8 +686,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
727 let regs = T::regs(); 686 let regs = T::regs();
728 match ep_addr.direction() { 687 match ep_addr.direction() {
729 Direction::Out => { 688 Direction::Out => {
730 // SAFETY: DOEPCTL is shared with `Endpoint` so critical section is needed for RMW 689 critical_section::with(|_| {
731 critical_section::with(|_| unsafe {
732 regs.doepctl(ep_addr.index()).modify(|w| { 690 regs.doepctl(ep_addr.index()).modify(|w| {
733 w.set_stall(stalled); 691 w.set_stall(stalled);
734 }); 692 });
@@ -737,8 +695,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
737 T::state().ep_out_wakers[ep_addr.index()].wake(); 695 T::state().ep_out_wakers[ep_addr.index()].wake();
738 } 696 }
739 Direction::In => { 697 Direction::In => {
740 // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW 698 critical_section::with(|_| {
741 critical_section::with(|_| unsafe {
742 regs.diepctl(ep_addr.index()).modify(|w| { 699 regs.diepctl(ep_addr.index()).modify(|w| {
743 w.set_stall(stalled); 700 w.set_stall(stalled);
744 }); 701 });
@@ -758,10 +715,9 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
758 715
759 let regs = T::regs(); 716 let regs = T::regs();
760 717
761 // SAFETY: atomic read with no side effects
762 match ep_addr.direction() { 718 match ep_addr.direction() {
763 Direction::Out => unsafe { regs.doepctl(ep_addr.index()).read().stall() }, 719 Direction::Out => regs.doepctl(ep_addr.index()).read().stall(),
764 Direction::In => unsafe { regs.diepctl(ep_addr.index()).read().stall() }, 720 Direction::In => regs.diepctl(ep_addr.index()).read().stall(),
765 } 721 }
766 } 722 }
767 723
@@ -777,8 +733,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
777 let r = T::regs(); 733 let r = T::regs();
778 match ep_addr.direction() { 734 match ep_addr.direction() {
779 Direction::Out => { 735 Direction::Out => {
780 // SAFETY: DOEPCTL is shared with `Endpoint` so critical section is needed for RMW 736 critical_section::with(|_| {
781 critical_section::with(|_| unsafe {
782 // cancel transfer if active 737 // cancel transfer if active
783 if !enabled && r.doepctl(ep_addr.index()).read().epena() { 738 if !enabled && r.doepctl(ep_addr.index()).read().epena() {
784 r.doepctl(ep_addr.index()).modify(|w| { 739 r.doepctl(ep_addr.index()).modify(|w| {
@@ -796,8 +751,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
796 T::state().ep_out_wakers[ep_addr.index()].wake(); 751 T::state().ep_out_wakers[ep_addr.index()].wake();
797 } 752 }
798 Direction::In => { 753 Direction::In => {
799 // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW 754 critical_section::with(|_| {
800 critical_section::with(|_| unsafe {
801 // cancel transfer if active 755 // cancel transfer if active
802 if !enabled && r.diepctl(ep_addr.index()).read().epena() { 756 if !enabled && r.diepctl(ep_addr.index()).read().epena() {
803 r.diepctl(ep_addr.index()).modify(|w| { 757 r.diepctl(ep_addr.index()).modify(|w| {
@@ -820,195 +774,192 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
820 async fn enable(&mut self) { 774 async fn enable(&mut self) {
821 trace!("enable"); 775 trace!("enable");
822 776
823 // SAFETY: registers are only accessed by `Bus` under `&mut self` 777 #[cfg(stm32l4)]
824 unsafe { 778 {
825 #[cfg(stm32l4)] 779 crate::peripherals::PWR::enable();
826 { 780 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
827 crate::peripherals::PWR::enable(); 781 }
828 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
829 }
830 782
831 #[cfg(stm32f7)] 783 #[cfg(stm32f7)]
832 { 784 {
833 // Enable ULPI clock if external PHY is used 785 // Enable ULPI clock if external PHY is used
834 let ulpien = !self.phy_type.internal(); 786 let ulpien = !self.phy_type.internal();
835 critical_section::with(|_| { 787 critical_section::with(|_| {
836 crate::pac::RCC.ahb1enr().modify(|w| { 788 crate::pac::RCC.ahb1enr().modify(|w| {
837 if T::HIGH_SPEED { 789 if T::HIGH_SPEED {
838 w.set_usb_otg_hsulpien(ulpien); 790 w.set_usb_otg_hsulpien(ulpien);
839 } else { 791 } else {
840 w.set_usb_otg_hsen(ulpien); 792 w.set_usb_otg_hsen(ulpien);
841 } 793 }
842 }); 794 });
843 795
844 // Low power mode 796 // Low power mode
845 crate::pac::RCC.ahb1lpenr().modify(|w| { 797 crate::pac::RCC.ahb1lpenr().modify(|w| {
846 if T::HIGH_SPEED { 798 if T::HIGH_SPEED {
847 w.set_usb_otg_hsulpilpen(ulpien); 799 w.set_usb_otg_hsulpilpen(ulpien);
848 } else { 800 } else {
849 w.set_usb_otg_hslpen(ulpien); 801 w.set_usb_otg_hslpen(ulpien);
850 } 802 }
851 });
852 }); 803 });
853 } 804 });
805 }
854 806
855 #[cfg(stm32h7)] 807 #[cfg(stm32h7)]
856 { 808 {
857 // If true, VDD33USB is generated by internal regulator from VDD50USB 809 // If true, VDD33USB is generated by internal regulator from VDD50USB
858 // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) 810 // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
859 // TODO: unhardcode 811 // TODO: unhardcode
860 let internal_regulator = false; 812 let internal_regulator = false;
813
814 // Enable USB power
815 critical_section::with(|_| {
816 crate::pac::PWR.cr3().modify(|w| {
817 w.set_usb33den(true);
818 w.set_usbregen(internal_regulator);
819 })
820 });
861 821
862 // Enable USB power 822 // Wait for USB power to stabilize
863 critical_section::with(|_| { 823 while !crate::pac::PWR.cr3().read().usb33rdy() {}
864 crate::pac::PWR.cr3().modify(|w| {
865 w.set_usb33den(true);
866 w.set_usbregen(internal_regulator);
867 })
868 });
869 824
870 // Wait for USB power to stabilize 825 // Use internal 48MHz HSI clock. Should be enabled in RCC by default.
871 while !crate::pac::PWR.cr3().read().usb33rdy() {} 826 critical_section::with(|_| {
827 crate::pac::RCC
828 .d2ccip2r()
829 .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48))
830 });
872 831
873 // Use internal 48MHz HSI clock. Should be enabled in RCC by default. 832 // Enable ULPI clock if external PHY is used
874 critical_section::with(|_| { 833 let ulpien = !self.phy_type.internal();
875 crate::pac::RCC 834 critical_section::with(|_| {
876 .d2ccip2r() 835 crate::pac::RCC.ahb1enr().modify(|w| {
877 .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48)) 836 if T::HIGH_SPEED {
837 w.set_usb_otg_hs_ulpien(ulpien);
838 } else {
839 w.set_usb_otg_fs_ulpien(ulpien);
840 }
878 }); 841 });
879 842 crate::pac::RCC.ahb1lpenr().modify(|w| {
880 // Enable ULPI clock if external PHY is used 843 if T::HIGH_SPEED {
881 let ulpien = !self.phy_type.internal(); 844 w.set_usb_otg_hs_ulpilpen(ulpien);
882 critical_section::with(|_| { 845 } else {
883 crate::pac::RCC.ahb1enr().modify(|w| { 846 w.set_usb_otg_fs_ulpilpen(ulpien);
884 if T::HIGH_SPEED { 847 }
885 w.set_usb_otg_hs_ulpien(ulpien);
886 } else {
887 w.set_usb_otg_fs_ulpien(ulpien);
888 }
889 });
890 crate::pac::RCC.ahb1lpenr().modify(|w| {
891 if T::HIGH_SPEED {
892 w.set_usb_otg_hs_ulpilpen(ulpien);
893 } else {
894 w.set_usb_otg_fs_ulpilpen(ulpien);
895 }
896 });
897 }); 848 });
898 } 849 });
850 }
899 851
900 #[cfg(stm32u5)] 852 #[cfg(stm32u5)]
901 { 853 {
902 // Enable USB power 854 // Enable USB power
903 critical_section::with(|_| { 855 critical_section::with(|_| {
904 crate::pac::RCC.ahb3enr().modify(|w| { 856 crate::pac::RCC.ahb3enr().modify(|w| {
905 w.set_pwren(true); 857 w.set_pwren(true);
906 }); 858 });
907 cortex_m::asm::delay(2); 859 cortex_m::asm::delay(2);
908 860
909 crate::pac::PWR.svmcr().modify(|w| { 861 crate::pac::PWR.svmcr().modify(|w| {
910 w.set_usv(true); 862 w.set_usv(true);
911 w.set_uvmen(true); 863 w.set_uvmen(true);
912 });
913 }); 864 });
865 });
914 866
915 // Wait for USB power to stabilize 867 // Wait for USB power to stabilize
916 while !crate::pac::PWR.svmsr().read().vddusbrdy() {} 868 while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
917 869
918 // Select HSI48 as USB clock source. 870 // Select HSI48 as USB clock source.
919 critical_section::with(|_| { 871 critical_section::with(|_| {
920 crate::pac::RCC.ccipr1().modify(|w| { 872 crate::pac::RCC.ccipr1().modify(|w| {
921 w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48); 873 w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48);
922 }) 874 })
923 }); 875 });
924 } 876 }
925 877
926 <T as RccPeripheral>::enable(); 878 <T as RccPeripheral>::enable();
927 <T as RccPeripheral>::reset(); 879 <T as RccPeripheral>::reset();
928 880
929 T::Interrupt::unpend(); 881 T::Interrupt::unpend();
930 T::Interrupt::enable(); 882 unsafe { T::Interrupt::enable() };
931 883
932 let r = T::regs(); 884 let r = T::regs();
933 let core_id = r.cid().read().0; 885 let core_id = r.cid().read().0;
934 info!("Core id {:08x}", core_id); 886 info!("Core id {:08x}", core_id);
935 887
936 // Wait for AHB ready. 888 // Wait for AHB ready.
937 while !r.grstctl().read().ahbidl() {} 889 while !r.grstctl().read().ahbidl() {}
938 890
939 // Configure as device. 891 // Configure as device.
940 r.gusbcfg().write(|w| { 892 r.gusbcfg().write(|w| {
941 // Force device mode 893 // Force device mode
942 w.set_fdmod(true); 894 w.set_fdmod(true);
943 // Enable internal full-speed PHY 895 // Enable internal full-speed PHY
944 w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed()); 896 w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed());
945 }); 897 });
946 898
947 // Configuring Vbus sense and SOF output 899 // Configuring Vbus sense and SOF output
948 match core_id { 900 match core_id {
949 0x0000_1200 | 0x0000_1100 => { 901 0x0000_1200 | 0x0000_1100 => {
950 assert!(self.phy_type != PhyType::InternalHighSpeed); 902 assert!(self.phy_type != PhyType::InternalHighSpeed);
951 903
952 r.gccfg_v1().modify(|w| { 904 r.gccfg_v1().modify(|w| {
953 // Enable internal full-speed PHY, logic is inverted 905 // Enable internal full-speed PHY, logic is inverted
954 w.set_pwrdwn(self.phy_type.internal()); 906 w.set_pwrdwn(self.phy_type.internal());
955 }); 907 });
956 908
957 // F429-like chips have the GCCFG.NOVBUSSENS bit 909 // F429-like chips have the GCCFG.NOVBUSSENS bit
958 r.gccfg_v1().modify(|w| { 910 r.gccfg_v1().modify(|w| {
959 w.set_novbussens(true); 911 w.set_novbussens(true);
960 w.set_vbusasen(false); 912 w.set_vbusasen(false);
961 w.set_vbusbsen(false); 913 w.set_vbusbsen(false);
962 w.set_sofouten(false); 914 w.set_sofouten(false);
963 }); 915 });
964 } 916 }
965 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => { 917 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => {
966 // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning 918 // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning
967 r.gccfg_v2().modify(|w| { 919 r.gccfg_v2().modify(|w| {
968 // Enable internal full-speed PHY, logic is inverted 920 // Enable internal full-speed PHY, logic is inverted
969 w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed()); 921 w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed());
970 w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed()); 922 w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed());
971 }); 923 });
972 924
973 r.gccfg_v2().modify(|w| { 925 r.gccfg_v2().modify(|w| {
974 w.set_vbden(false); 926 w.set_vbden(false);
975 }); 927 });
976 928
977 // Force B-peripheral session 929 // Force B-peripheral session
978 r.gotgctl().modify(|w| { 930 r.gotgctl().modify(|w| {
979 w.set_bvaloen(true); 931 w.set_bvaloen(true);
980 w.set_bvaloval(true); 932 w.set_bvaloval(true);
981 }); 933 });
982 }
983 _ => unimplemented!("Unknown USB core id {:X}", core_id),
984 } 934 }
935 _ => unimplemented!("Unknown USB core id {:X}", core_id),
936 }
985 937
986 // Soft disconnect. 938 // Soft disconnect.
987 r.dctl().write(|w| w.set_sdis(true)); 939 r.dctl().write(|w| w.set_sdis(true));
988 940
989 // Set speed. 941 // Set speed.
990 r.dcfg().write(|w| { 942 r.dcfg().write(|w| {
991 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80); 943 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80);
992 w.set_dspd(self.phy_type.to_dspd()); 944 w.set_dspd(self.phy_type.to_dspd());
993 }); 945 });
994 946
995 // Unmask transfer complete EP interrupt 947 // Unmask transfer complete EP interrupt
996 r.diepmsk().write(|w| { 948 r.diepmsk().write(|w| {
997 w.set_xfrcm(true); 949 w.set_xfrcm(true);
998 }); 950 });
999 951
1000 // Unmask and clear core interrupts 952 // Unmask and clear core interrupts
1001 Bus::<T>::restore_irqs(); 953 Bus::<T>::restore_irqs();
1002 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF)); 954 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
1003 955
1004 // Unmask global interrupt 956 // Unmask global interrupt
1005 r.gahbcfg().write(|w| { 957 r.gahbcfg().write(|w| {
1006 w.set_gint(true); // unmask global interrupt 958 w.set_gint(true); // unmask global interrupt
1007 }); 959 });
1008 960
1009 // Connect 961 // Connect
1010 r.dctl().write(|w| w.set_sdis(false)); 962 r.dctl().write(|w| w.set_sdis(false));
1011 }
1012 963
1013 self.enabled = true; 964 self.enabled = true;
1014 } 965 }
@@ -1066,8 +1017,7 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, In> {
1066 1017
1067 T::state().ep_in_wakers[ep_index].register(cx.waker()); 1018 T::state().ep_in_wakers[ep_index].register(cx.waker());
1068 1019
1069 // SAFETY: atomic read without side effects 1020 if T::regs().diepctl(ep_index).read().usbaep() {
1070 if unsafe { T::regs().diepctl(ep_index).read().usbaep() } {
1071 Poll::Ready(()) 1021 Poll::Ready(())
1072 } else { 1022 } else {
1073 Poll::Pending 1023 Poll::Pending
@@ -1088,8 +1038,7 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, Out> {
1088 1038
1089 T::state().ep_out_wakers[ep_index].register(cx.waker()); 1039 T::state().ep_out_wakers[ep_index].register(cx.waker());
1090 1040
1091 // SAFETY: atomic read without side effects 1041 if T::regs().doepctl(ep_index).read().usbaep() {
1092 if unsafe { T::regs().doepctl(ep_index).read().usbaep() } {
1093 Poll::Ready(()) 1042 Poll::Ready(())
1094 } else { 1043 } else {
1095 Poll::Pending 1044 Poll::Pending
@@ -1124,8 +1073,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> {
1124 // Release buffer 1073 // Release buffer
1125 state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release); 1074 state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release);
1126 1075
1127 // SAFETY: DOEPCTL/DOEPTSIZ is shared with `Bus` so a critical section is needed for RMW 1076 critical_section::with(|_| {
1128 critical_section::with(|_| unsafe {
1129 // Receive 1 packet 1077 // Receive 1 packet
1130 T::regs().doeptsiz(index).modify(|w| { 1078 T::regs().doeptsiz(index).modify(|w| {
1131 w.set_xfrsiz(self.info.max_packet_size as _); 1079 w.set_xfrsiz(self.info.max_packet_size as _);
@@ -1163,8 +1111,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1163 poll_fn(|cx| { 1111 poll_fn(|cx| {
1164 state.ep_in_wakers[index].register(cx.waker()); 1112 state.ep_in_wakers[index].register(cx.waker());
1165 1113
1166 // SAFETY: atomic read with no side effects 1114 let diepctl = r.diepctl(index).read();
1167 let diepctl = unsafe { r.diepctl(index).read() };
1168 if !diepctl.usbaep() { 1115 if !diepctl.usbaep() {
1169 Poll::Ready(Err(EndpointError::Disabled)) 1116 Poll::Ready(Err(EndpointError::Disabled))
1170 } else if !diepctl.epena() { 1117 } else if !diepctl.epena() {
@@ -1181,12 +1128,10 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1181 1128
1182 let size_words = (buf.len() + 3) / 4; 1129 let size_words = (buf.len() + 3) / 4;
1183 1130
1184 // SAFETY: atomic read with no side effects 1131 let fifo_space = r.dtxfsts(index).read().ineptfsav() as usize;
1185 let fifo_space = unsafe { r.dtxfsts(index).read().ineptfsav() as usize };
1186 if size_words > fifo_space { 1132 if size_words > fifo_space {
1187 // Not enough space in fifo, enable tx fifo empty interrupt 1133 // Not enough space in fifo, enable tx fifo empty interrupt
1188 // SAFETY: DIEPEMPMSK is shared with IRQ so critical section is needed for RMW 1134 critical_section::with(|_| {
1189 critical_section::with(|_| unsafe {
1190 r.diepempmsk().modify(|w| { 1135 r.diepempmsk().modify(|w| {
1191 w.set_ineptxfem(w.ineptxfem() | (1 << index)); 1136 w.set_ineptxfem(w.ineptxfem() | (1 << index));
1192 }); 1137 });
@@ -1202,18 +1147,14 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1202 .await 1147 .await
1203 } 1148 }
1204 1149
1205 // SAFETY: DIEPTSIZ is exclusive to this endpoint under `&mut self` 1150 // Setup transfer size
1206 unsafe { 1151 r.dieptsiz(index).write(|w| {
1207 // Setup transfer size 1152 w.set_mcnt(1);
1208 r.dieptsiz(index).write(|w| { 1153 w.set_pktcnt(1);
1209 w.set_mcnt(1); 1154 w.set_xfrsiz(buf.len() as _);
1210 w.set_pktcnt(1); 1155 });
1211 w.set_xfrsiz(buf.len() as _);
1212 });
1213 }
1214 1156
1215 // SAFETY: DIEPCTL is shared with `Bus` so a critical section is needed for RMW 1157 critical_section::with(|_| {
1216 critical_section::with(|_| unsafe {
1217 // Enable endpoint 1158 // Enable endpoint
1218 r.diepctl(index).modify(|w| { 1159 r.diepctl(index).modify(|w| {
1219 w.set_cnak(true); 1160 w.set_cnak(true);
@@ -1225,8 +1166,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1225 for chunk in buf.chunks(4) { 1166 for chunk in buf.chunks(4) {
1226 let mut tmp = [0u8; 4]; 1167 let mut tmp = [0u8; 4];
1227 tmp[0..chunk.len()].copy_from_slice(chunk); 1168 tmp[0..chunk.len()].copy_from_slice(chunk);
1228 // SAFETY: FIFO is exclusive to this endpoint under `&mut self` 1169 r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp)));
1229 unsafe { r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))) };
1230 } 1170 }
1231 1171
1232 trace!("write done ep={:?}", self.info.addr); 1172 trace!("write done ep={:?}", self.info.addr);
@@ -1258,17 +1198,15 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> {
1258 state.ep0_setup_ready.store(false, Ordering::Release); 1198 state.ep0_setup_ready.store(false, Ordering::Release);
1259 1199
1260 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section 1200 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section
1261 unsafe { 1201 // Receive 1 SETUP packet
1262 // Receive 1 SETUP packet 1202 T::regs().doeptsiz(self.ep_out.info.addr.index()).modify(|w| {
1263 T::regs().doeptsiz(self.ep_out.info.addr.index()).modify(|w| { 1203 w.set_rxdpid_stupcnt(1);
1264 w.set_rxdpid_stupcnt(1); 1204 });
1265 });
1266 1205
1267 // Clear NAK to indicate we are ready to receive more data 1206 // Clear NAK to indicate we are ready to receive more data
1268 T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| { 1207 T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| {
1269 w.set_cnak(true); 1208 w.set_cnak(true);
1270 }); 1209 });
1271 }
1272 1210
1273 trace!("SETUP received: {:?}", data); 1211 trace!("SETUP received: {:?}", data);
1274 Poll::Ready(data) 1212 Poll::Ready(data)
@@ -1313,20 +1251,18 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> {
1313 trace!("control: reject"); 1251 trace!("control: reject");
1314 1252
1315 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section 1253 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section
1316 unsafe { 1254 let regs = T::regs();
1317 let regs = T::regs(); 1255 regs.diepctl(self.ep_in.info.addr.index()).modify(|w| {
1318 regs.diepctl(self.ep_in.info.addr.index()).modify(|w| { 1256 w.set_stall(true);
1319 w.set_stall(true); 1257 });
1320 }); 1258 regs.doepctl(self.ep_out.info.addr.index()).modify(|w| {
1321 regs.doepctl(self.ep_out.info.addr.index()).modify(|w| { 1259 w.set_stall(true);
1322 w.set_stall(true); 1260 });
1323 });
1324 }
1325 } 1261 }
1326 1262
1327 async fn accept_set_address(&mut self, addr: u8) { 1263 async fn accept_set_address(&mut self, addr: u8) {
1328 trace!("setting addr: {}", addr); 1264 trace!("setting addr: {}", addr);
1329 critical_section::with(|_| unsafe { 1265 critical_section::with(|_| {
1330 T::regs().dcfg().modify(|w| { 1266 T::regs().dcfg().modify(|w| {
1331 w.set_dad(addr); 1267 w.set_dad(addr);
1332 }); 1268 });
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index 18ebf97d8..5907a4e54 100644
--- a/embassy-stm32/src/wdg/mod.rs
+++ b/embassy-stm32/src/wdg/mod.rs
@@ -48,11 +48,9 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
48 let rl = reload_value(psc, timeout_us); 48 let rl = reload_value(psc, timeout_us);
49 49
50 let wdg = T::regs(); 50 let wdg = T::regs();
51 unsafe { 51 wdg.kr().write(|w| w.set_key(Key::ENABLE));
52 wdg.kr().write(|w| w.set_key(Key::ENABLE)); 52 wdg.pr().write(|w| w.set_pr(Pr(pr)));
53 wdg.pr().write(|w| w.set_pr(Pr(pr))); 53 wdg.rlr().write(|w| w.set_rl(rl));
54 wdg.rlr().write(|w| w.set_rl(rl));
55 }
56 54
57 trace!( 55 trace!(
58 "Watchdog configured with {}us timeout, desired was {}us (PR={}, RL={})", 56 "Watchdog configured with {}us timeout, desired was {}us (PR={}, RL={})",
@@ -67,11 +65,11 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
67 } 65 }
68 } 66 }
69 67
70 pub unsafe fn unleash(&mut self) { 68 pub fn unleash(&mut self) {
71 T::regs().kr().write(|w| w.set_key(Key::START)); 69 T::regs().kr().write(|w| w.set_key(Key::START));
72 } 70 }
73 71
74 pub unsafe fn pet(&mut self) { 72 pub fn pet(&mut self) {
75 T::regs().kr().write(|w| w.set_key(Key::RESET)); 73 T::regs().kr().write(|w| w.set_key(Key::RESET));
76 } 74 }
77} 75}
diff --git a/examples/stm32f0/src/bin/wdg.rs b/examples/stm32f0/src/bin/wdg.rs
index 80e76f901..a44b17528 100644
--- a/examples/stm32f0/src/bin/wdg.rs
+++ b/examples/stm32f0/src/bin/wdg.rs
@@ -16,10 +16,10 @@ async fn main(_spawner: Spawner) {
16 let mut wdg = IndependentWatchdog::new(p.IWDG, 20_000_00); 16 let mut wdg = IndependentWatchdog::new(p.IWDG, 20_000_00);
17 17
18 info!("Watchdog start"); 18 info!("Watchdog start");
19 unsafe { wdg.unleash() }; 19 wdg.unleash();
20 20
21 loop { 21 loop {
22 Timer::after(Duration::from_secs(1)).await; 22 Timer::after(Duration::from_secs(1)).await;
23 unsafe { wdg.pet() }; 23 wdg.pet();
24 } 24 }
25} 25}
diff --git a/examples/stm32f4/src/bin/wdt.rs b/examples/stm32f4/src/bin/wdt.rs
index b2c587fa1..e5d122af7 100644
--- a/examples/stm32f4/src/bin/wdt.rs
+++ b/examples/stm32f4/src/bin/wdt.rs
@@ -17,9 +17,7 @@ async fn main(_spawner: Spawner) {
17 let mut led = Output::new(p.PB7, Level::High, Speed::Low); 17 let mut led = Output::new(p.PB7, Level::High, Speed::Low);
18 18
19 let mut wdt = IndependentWatchdog::new(p.IWDG, 1_000_000); 19 let mut wdt = IndependentWatchdog::new(p.IWDG, 1_000_000);
20 unsafe { 20 wdt.unleash();
21 wdt.unleash();
22 }
23 21
24 let mut i = 0; 22 let mut i = 0;
25 23
@@ -36,9 +34,7 @@ async fn main(_spawner: Spawner) {
36 // MCU should restart in 1 second after the last pet. 34 // MCU should restart in 1 second after the last pet.
37 if i < 5 { 35 if i < 5 {
38 info!("Petting watchdog"); 36 info!("Petting watchdog");
39 unsafe { 37 wdt.pet();
40 wdt.pet();
41 }
42 } 38 }
43 39
44 i += 1; 40 i += 1;
diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs
index ecbe3a6e6..c111a9787 100644
--- a/examples/stm32g4/src/bin/usb_serial.rs
+++ b/examples/stm32g4/src/bin/usb_serial.rs
@@ -38,9 +38,7 @@ async fn main(_spawner: Spawner) {
38 let p = embassy_stm32::init(config); 38 let p = embassy_stm32::init(config);
39 info!("Hello World!"); 39 info!("Hello World!");
40 40
41 unsafe { 41 pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10));
42 pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10));
43 }
44 42
45 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); 43 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
46 44
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs
index 3912327e2..336eed644 100644
--- a/examples/stm32h5/src/bin/usb_serial.rs
+++ b/examples/stm32h5/src/bin/usb_serial.rs
@@ -45,11 +45,9 @@ async fn main(_spawner: Spawner) {
45 45
46 info!("Hello World!"); 46 info!("Hello World!");
47 47
48 unsafe { 48 pac::RCC.ccipr4().write(|w| {
49 pac::RCC.ccipr4().write(|w| { 49 w.set_usbsel(pac::rcc::vals::Usbsel::HSI48);
50 w.set_usbsel(pac::rcc::vals::Usbsel::HSI48); 50 });
51 });
52 }
53 51
54 // Create the driver, from the HAL. 52 // Create the driver, from the HAL.
55 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); 53 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index 1972f8ff2..d360df085 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -62,49 +62,39 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
62 T::enable(); 62 T::enable();
63 <T as embassy_stm32::rcc::low_level::RccPeripheral>::reset(); 63 <T as embassy_stm32::rcc::low_level::RccPeripheral>::reset();
64 64
65 unsafe { 65 ch1.set_speed(Speed::VeryHigh);
66 ch1.set_speed(Speed::VeryHigh); 66 ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull);
67 ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); 67 ch2.set_speed(Speed::VeryHigh);
68 ch2.set_speed(Speed::VeryHigh); 68 ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull);
69 ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); 69 ch3.set_speed(Speed::VeryHigh);
70 ch3.set_speed(Speed::VeryHigh); 70 ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull);
71 ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); 71 ch4.set_speed(Speed::VeryHigh);
72 ch4.set_speed(Speed::VeryHigh); 72 ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull);
73 ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull);
74 }
75 73
76 let mut this = Self { inner: tim }; 74 let mut this = Self { inner: tim };
77 75
78 this.set_freq(freq); 76 this.set_freq(freq);
79 this.inner.start(); 77 this.inner.start();
80 78
81 unsafe { 79 let r = T::regs_gp32();
82 T::regs_gp32() 80 r.ccmr_output(0)
83 .ccmr_output(0) 81 .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into()));
84 .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); 82 r.ccmr_output(0)
85 T::regs_gp32() 83 .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into()));
86 .ccmr_output(0) 84 r.ccmr_output(1)
87 .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); 85 .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into()));
88 T::regs_gp32() 86 r.ccmr_output(1)
89 .ccmr_output(1) 87 .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into()));
90 .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); 88
91 T::regs_gp32()
92 .ccmr_output(1)
93 .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into()));
94 }
95 this 89 this
96 } 90 }
97 91
98 pub fn enable(&mut self, channel: Channel) { 92 pub fn enable(&mut self, channel: Channel) {
99 unsafe { 93 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true));
100 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true));
101 }
102 } 94 }
103 95
104 pub fn disable(&mut self, channel: Channel) { 96 pub fn disable(&mut self, channel: Channel) {
105 unsafe { 97 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false));
106 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false));
107 }
108 } 98 }
109 99
110 pub fn set_freq(&mut self, freq: Hertz) { 100 pub fn set_freq(&mut self, freq: Hertz) {
@@ -112,11 +102,11 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
112 } 102 }
113 103
114 pub fn get_max_duty(&self) -> u32 { 104 pub fn get_max_duty(&self) -> u32 {
115 unsafe { T::regs_gp32().arr().read().arr() } 105 T::regs_gp32().arr().read().arr()
116 } 106 }
117 107
118 pub fn set_duty(&mut self, channel: Channel, duty: u32) { 108 pub fn set_duty(&mut self, channel: Channel, duty: u32) {
119 defmt::assert!(duty < self.get_max_duty()); 109 defmt::assert!(duty < self.get_max_duty());
120 unsafe { T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty)) } 110 T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty))
121 } 111 }
122} 112}
diff --git a/examples/stm32h7/src/bin/wdg.rs b/examples/stm32h7/src/bin/wdg.rs
index 2b0301aad..9181dfd67 100644
--- a/examples/stm32h7/src/bin/wdg.rs
+++ b/examples/stm32h7/src/bin/wdg.rs
@@ -15,10 +15,10 @@ async fn main(_spawner: Spawner) {
15 15
16 let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000); 16 let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000);
17 17
18 unsafe { wdg.unleash() }; 18 wdg.unleash();
19 19
20 loop { 20 loop {
21 Timer::after(Duration::from_secs(1)).await; 21 Timer::after(Duration::from_secs(1)).await;
22 unsafe { wdg.pet() }; 22 wdg.pet();
23 } 23 }
24} 24}
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs
index 281346e5f..1771e5202 100644
--- a/examples/stm32l4/src/bin/adc.rs
+++ b/examples/stm32l4/src/bin/adc.rs
@@ -12,12 +12,10 @@ use {defmt_rtt as _, panic_probe as _};
12fn main() -> ! { 12fn main() -> ! {
13 info!("Hello World!"); 13 info!("Hello World!");
14 14
15 unsafe { 15 pac::RCC.ccipr().modify(|w| {
16 pac::RCC.ccipr().modify(|w| { 16 w.set_adcsel(0b11);
17 w.set_adcsel(0b11); 17 });
18 }); 18 pac::RCC.ahb2enr().modify(|w| w.set_adcen(true));
19 pac::RCC.ahb2enr().modify(|w| w.set_adcen(true));
20 }
21 19
22 let p = embassy_stm32::init(Default::default()); 20 let p = embassy_stm32::init(Default::default());
23 21
diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs
index d6e744aa6..a36ed5d90 100644
--- a/examples/stm32l4/src/bin/dac.rs
+++ b/examples/stm32l4/src/bin/dac.rs
@@ -11,11 +11,9 @@ use {defmt_rtt as _, panic_probe as _};
11fn main() -> ! { 11fn main() -> ! {
12 info!("Hello World!"); 12 info!("Hello World!");
13 13
14 unsafe { 14 pac::RCC.apb1enr1().modify(|w| {
15 pac::RCC.apb1enr1().modify(|w| { 15 w.set_dac1en(true);
16 w.set_dac1en(true); 16 });
17 });
18 }
19 17
20 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
21 19
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
index e179c5ca1..805d21418 100644
--- a/examples/stm32wl/src/bin/lora_lorawan.rs
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -35,7 +35,7 @@ async fn main(_spawner: Spawner) {
35 config.rcc.enable_lsi = true; // enable RNG 35 config.rcc.enable_lsi = true; // enable RNG
36 let p = embassy_stm32::init(config); 36 let p = embassy_stm32::init(config);
37 37
38 unsafe { pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)) } 38 pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01));
39 39
40 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 40 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
41 41
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs
index 182c607f9..d8562fca5 100644
--- a/examples/stm32wl/src/bin/random.rs
+++ b/examples/stm32wl/src/bin/random.rs
@@ -15,11 +15,9 @@ async fn main(_spawner: Spawner) {
15 config.rcc.enable_lsi = true; //Needed for RNG to work 15 config.rcc.enable_lsi = true; //Needed for RNG to work
16 16
17 let p = embassy_stm32::init(config); 17 let p = embassy_stm32::init(config);
18 unsafe { 18 pac::RCC.ccipr().modify(|w| {
19 pac::RCC.ccipr().modify(|w| { 19 w.set_rngsel(0b01);
20 w.set_rngsel(0b01); 20 });
21 });
22 }
23 21
24 info!("Hello World!"); 22 info!("Hello World!");
25 23
diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs
index 32d35c42c..582df5753 100644
--- a/tests/stm32/src/bin/rtc.rs
+++ b/tests/stm32/src/bin/rtc.rs
@@ -24,10 +24,8 @@ async fn main(_spawner: Spawner) {
24 24
25 info!("Starting LSI"); 25 info!("Starting LSI");
26 26
27 unsafe { 27 pac::RCC.csr().modify(|w| w.set_lsion(true));
28 pac::RCC.csr().modify(|w| w.set_lsion(true)); 28 while !pac::RCC.csr().read().lsirdy() {}
29 while !pac::RCC.csr().read().lsirdy() {}
30 }
31 29
32 info!("Started LSI"); 30 info!("Started LSI");
33 31
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index 50dd2893e..c34d9574b 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -69,24 +69,27 @@ async fn main(_spawner: Spawner) {
69 const LEN: usize = 128; 69 const LEN: usize = 128;
70 let mut tx_buf = [0; LEN]; 70 let mut tx_buf = [0; LEN];
71 let mut rx_buf = [0; LEN]; 71 let mut rx_buf = [0; LEN];
72 for i in 0..LEN {
73 tx_buf[i] = i as u8;
74 }
75 72
76 let (mut tx, mut rx) = usart.split(); 73 let (mut tx, mut rx) = usart.split();
77 74
78 let tx_fut = async { 75 for n in 0..42 {
79 tx.write(&tx_buf).await.unwrap(); 76 for i in 0..LEN {
80 }; 77 tx_buf[i] = (i ^ n) as u8;
81 let rx_fut = async { 78 }
82 rx.read(&mut rx_buf).await.unwrap(); 79
83 }; 80 let tx_fut = async {
81 tx.write(&tx_buf).await.unwrap();
82 };
83 let rx_fut = async {
84 rx.read(&mut rx_buf).await.unwrap();
85 };
84 86
85 // note: rx needs to be polled first, to workaround this bug: 87 // note: rx needs to be polled first, to workaround this bug:
86 // https://github.com/embassy-rs/embassy/issues/1426 88 // https://github.com/embassy-rs/embassy/issues/1426
87 join(rx_fut, tx_fut).await; 89 join(rx_fut, tx_fut).await;
88 90
89 assert_eq!(tx_buf, rx_buf); 91 assert_eq!(tx_buf, rx_buf);
92 }
90 93
91 info!("Test OK"); 94 info!("Test OK");
92 cortex_m::asm::bkpt(); 95 cortex_m::asm::bkpt();