aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh1
-rw-r--r--cyw43/src/fmt.rs3
-rw-r--r--embassy-boot-nrf/src/fmt.rs3
-rw-r--r--embassy-boot-rp/src/fmt.rs3
-rw-r--r--embassy-boot-stm32/src/fmt.rs3
-rw-r--r--embassy-boot/src/boot_loader.rs24
-rw-r--r--embassy-boot/src/fmt.rs3
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/i2c.rs5
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/spi.rs5
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/i2c.rs21
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/spi.rs5
-rw-r--r--embassy-executor-macros/src/macros/task.rs17
-rw-r--r--embassy-executor-macros/src/util/ctxt.rs1
-rw-r--r--embassy-executor/src/fmt.rs3
-rw-r--r--embassy-executor/src/raw/mod.rs2
-rw-r--r--embassy-executor/tests/test.rs2
-rw-r--r--embassy-futures/src/fmt.rs3
-rw-r--r--embassy-hal-internal/src/fmt.rs3
-rw-r--r--embassy-hal-internal/src/interrupt.rs8
-rw-r--r--embassy-net-adin1110/src/fmt.rs29
-rw-r--r--embassy-net-driver-channel/src/fmt.rs3
-rw-r--r--embassy-net-enc28j60/src/fmt.rs3
-rw-r--r--embassy-net-enc28j60/src/lib.rs7
-rw-r--r--embassy-net-esp-hosted/src/fmt.rs3
-rw-r--r--embassy-net-ppp/src/fmt.rs3
-rw-r--r--embassy-net-tuntap/src/lib.rs2
-rw-r--r--embassy-net-wiznet/src/chip/mod.rs73
-rw-r--r--embassy-net-wiznet/src/chip/w5100s.rs2
-rw-r--r--embassy-net-wiznet/src/chip/w5500.rs2
-rw-r--r--embassy-net/src/fmt.rs3
-rw-r--r--embassy-nrf/src/fmt.rs3
-rw-r--r--embassy-nrf/src/gpio.rs2
-rw-r--r--embassy-nrf/src/gpiote.rs2
-rw-r--r--embassy-nrf/src/lib.rs39
-rw-r--r--embassy-nrf/src/timer.rs2
-rw-r--r--embassy-rp/src/dma.rs2
-rw-r--r--embassy-rp/src/flash.rs2
-rw-r--r--embassy-rp/src/float/mod.rs1
-rw-r--r--embassy-rp/src/fmt.rs3
-rw-r--r--embassy-rp/src/gpio.rs2
-rw-r--r--embassy-rp/src/lib.rs3
-rw-r--r--embassy-rp/src/relocate.rs2
-rw-r--r--embassy-rp/src/uart/buffered.rs10
-rw-r--r--embassy-rp/src/usb.rs11
-rw-r--r--embassy-stm32-wpan/src/consts.rs2
-rw-r--r--embassy-stm32-wpan/src/fmt.rs3
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/build.rs32
-rw-r--r--embassy-stm32/src/adc/f1.rs4
-rw-r--r--embassy-stm32/src/adc/f3.rs6
-rw-r--r--embassy-stm32/src/adc/f3_v1_1.rs4
-rw-r--r--embassy-stm32/src/adc/mod.rs100
-rw-r--r--embassy-stm32/src/adc/v1.rs6
-rw-r--r--embassy-stm32/src/adc/v2.rs6
-rw-r--r--embassy-stm32/src/adc/v3.rs8
-rw-r--r--embassy-stm32/src/adc/v4.rs8
-rw-r--r--embassy-stm32/src/can/bx/mod.rs2
-rw-r--r--embassy-stm32/src/can/bxcan.rs53
-rw-r--r--embassy-stm32/src/can/fd/message_ram/mod.rs20
-rw-r--r--embassy-stm32/src/can/fd/peripheral.rs61
-rw-r--r--embassy-stm32/src/can/fdcan.rs332
-rw-r--r--embassy-stm32/src/crc/v1.rs2
-rw-r--r--embassy-stm32/src/crc/v2v3.rs2
-rw-r--r--embassy-stm32/src/cryp/mod.rs13
-rw-r--r--embassy-stm32/src/dac/mod.rs17
-rw-r--r--embassy-stm32/src/dcmi.rs14
-rw-r--r--embassy-stm32/src/dma/dmamux.rs9
-rw-r--r--embassy-stm32/src/dma/mod.rs23
-rw-r--r--embassy-stm32/src/dma/word.rs9
-rw-r--r--embassy-stm32/src/eth/mod.rs11
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs23
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs29
-rw-r--r--embassy-stm32/src/exti.rs11
-rw-r--r--embassy-stm32/src/flash/f0.rs1
-rw-r--r--embassy-stm32/src/flash/f1f3.rs1
-rw-r--r--embassy-stm32/src/flash/f4.rs1
-rw-r--r--embassy-stm32/src/flash/f7.rs1
-rw-r--r--embassy-stm32/src/flash/g.rs1
-rw-r--r--embassy-stm32/src/flash/h7.rs1
-rw-r--r--embassy-stm32/src/flash/u5.rs1
-rw-r--r--embassy-stm32/src/fmc.rs18
-rw-r--r--embassy-stm32/src/fmt.rs3
-rw-r--r--embassy-stm32/src/gpio.rs311
-rw-r--r--embassy-stm32/src/hash/mod.rs15
-rw-r--r--embassy-stm32/src/hrtim/mod.rs17
-rw-r--r--embassy-stm32/src/hrtim/traits.rs128
-rw-r--r--embassy-stm32/src/i2c/mod.rs46
-rw-r--r--embassy-stm32/src/i2c/v1.rs266
-rw-r--r--embassy-stm32/src/i2c/v2.rs13
-rw-r--r--embassy-stm32/src/i2s.rs3
-rw-r--r--embassy-stm32/src/ipcc.rs83
-rw-r--r--embassy-stm32/src/lib.rs10
-rw-r--r--embassy-stm32/src/opamp.rs54
-rw-r--r--embassy-stm32/src/qspi/mod.rs16
-rw-r--r--embassy-stm32/src/rcc/hsi48.rs2
-rw-r--r--embassy-stm32/src/rcc/mco.rs27
-rw-r--r--embassy-stm32/src/rcc/mod.rs41
-rw-r--r--embassy-stm32/src/rng.rs13
-rw-r--r--embassy-stm32/src/rtc/datetime.rs7
-rw-r--r--embassy-stm32/src/rtc/mod.rs53
-rw-r--r--embassy-stm32/src/rtc/v2.rs5
-rw-r--r--embassy-stm32/src/rtc/v3.rs6
-rw-r--r--embassy-stm32/src/sai/mod.rs185
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs31
-rw-r--r--embassy-stm32/src/spi/mod.rs37
-rw-r--r--embassy-stm32/src/time_driver.rs41
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs37
-rw-r--r--embassy-stm32/src/timer/low_level.rs638
-rw-r--r--embassy-stm32/src/timer/mod.rs1005
-rw-r--r--embassy-stm32/src/timer/qei.rs36
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs45
-rw-r--r--embassy-stm32/src/ucpd.rs60
-rw-r--r--embassy-stm32/src/uid.rs2
-rw-r--r--embassy-stm32/src/usart/buffered.rs7
-rw-r--r--embassy-stm32/src/usart/mod.rs82
-rw-r--r--embassy-stm32/src/usb/mod.rs92
-rw-r--r--embassy-stm32/src/usb/otg.rs (renamed from embassy-stm32/src/usb_otg/usb.rs)204
-rw-r--r--embassy-stm32/src/usb/usb.rs60
-rw-r--r--embassy-stm32/src/usb_otg/mod.rs163
-rw-r--r--embassy-stm32/src/wdg/mod.rs11
-rw-r--r--embassy-sync/Cargo.toml2
-rw-r--r--embassy-sync/src/fmt.rs3
-rw-r--r--embassy-sync/src/lib.rs1
-rw-r--r--embassy-sync/src/once_lock.rs236
-rw-r--r--embassy-sync/src/signal.rs2
-rw-r--r--embassy-time/src/fmt.rs3
-rw-r--r--embassy-usb-dfu/src/fmt.rs3
-rw-r--r--embassy-usb-logger/src/lib.rs15
-rw-r--r--embassy-usb/src/builder.rs7
-rw-r--r--embassy-usb/src/descriptor.rs51
-rw-r--r--embassy-usb/src/fmt.rs3
-rw-r--r--embassy-usb/src/lib.rs9
-rw-r--r--embassy-usb/src/msos.rs34
-rw-r--r--examples/boot/application/stm32wb-dfu/src/main.rs2
-rw-r--r--examples/boot/bootloader/stm32wb-dfu/src/main.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_ethernet.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_hid_keyboard.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_hid_mouse.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_serial.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_serial_multitask.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_serial_winusb.rs2
-rw-r--r--examples/rp/src/bin/multicore.rs12
-rw-r--r--examples/rp/src/bin/pio_uart.rs2
-rw-r--r--examples/rp/src/bin/usb_ethernet.rs2
-rw-r--r--examples/rp/src/bin/usb_hid_keyboard.rs2
-rw-r--r--examples/rp/src/bin/usb_hid_mouse.rs2
-rw-r--r--examples/rp/src/bin/usb_midi.rs2
-rw-r--r--examples/rp/src/bin/usb_raw.rs2
-rw-r--r--examples/rp/src/bin/usb_raw_bulk.rs2
-rw-r--r--examples/rp/src/bin/usb_serial.rs2
-rw-r--r--examples/rp/src/bin/usb_serial_with_logger.rs2
-rw-r--r--examples/std/src/bin/net.rs2
-rw-r--r--examples/std/src/bin/net_dns.rs2
-rw-r--r--examples/std/src/bin/tcp_accept.rs1
-rw-r--r--examples/stm32f1/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32f2/src/bin/pll.rs2
-rw-r--r--examples/stm32f3/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32f4/src/bin/usb_ethernet.rs11
-rw-r--r--examples/stm32f4/src/bin/usb_hid_keyboard.rs11
-rw-r--r--examples/stm32f4/src/bin/usb_hid_mouse.rs11
-rw-r--r--examples/stm32f4/src/bin/usb_raw.rs11
-rw-r--r--examples/stm32f4/src/bin/usb_serial.rs11
-rw-r--r--examples/stm32f4/src/bin/ws2812_pwm.rs5
-rw-r--r--examples/stm32f7/src/bin/usb_serial.rs11
-rw-r--r--examples/stm32g0/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32g4/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32h5/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32h7/src/bin/camera.rs4
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs40
-rw-r--r--examples/stm32h7/src/bin/eth.rs20
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs71
-rw-r--r--examples/stm32h7/src/bin/usb_serial.rs11
-rw-r--r--examples/stm32l1/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs40
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs2
-rw-r--r--examples/stm32l4/src/bin/usb_serial.rs38
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs30
-rw-r--r--examples/stm32l5/src/bin/usb_hid_mouse.rs30
-rw-r--r--examples/stm32l5/src/bin/usb_serial.rs30
-rw-r--r--examples/stm32u5/src/bin/usb_serial.rs11
-rw-r--r--rust-toolchain-nightly.toml2
-rw-r--r--rust-toolchain.toml2
-rw-r--r--tests/rp/src/bin/gpio_multicore.rs12
-rw-r--r--tests/rp/src/bin/i2c.rs12
-rw-r--r--tests/rp/src/bin/multicore.rs12
185 files changed, 3071 insertions, 2824 deletions
diff --git a/ci.sh b/ci.sh
index cd82af2f1..d17f4e13e 100755
--- a/ci.sh
+++ b/ci.sh
@@ -124,6 +124,7 @@ cargo batch \
124 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \ 124 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \
125 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \ 125 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \
126 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \ 126 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \
127 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \
127 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ 128 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \
128 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ 129 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \
129 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \ 130 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \
diff --git a/cyw43/src/fmt.rs b/cyw43/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/cyw43/src/fmt.rs
+++ b/cyw43/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-boot-nrf/src/fmt.rs b/embassy-boot-nrf/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-boot-nrf/src/fmt.rs
+++ b/embassy-boot-nrf/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-boot-rp/src/fmt.rs b/embassy-boot-rp/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-boot-rp/src/fmt.rs
+++ b/embassy-boot-rp/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-boot-stm32/src/fmt.rs b/embassy-boot-stm32/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-boot-stm32/src/fmt.rs
+++ b/embassy-boot-stm32/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-boot/src/boot_loader.rs b/embassy-boot/src/boot_loader.rs
index ca1a1b10c..a38558056 100644
--- a/embassy-boot/src/boot_loader.rs
+++ b/embassy-boot/src/boot_loader.rs
@@ -183,29 +183,29 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash> BootLoader<ACTIVE, DFU, S
183 /// | Partition | Swap Index | Page 0 | Page 1 | Page 3 | Page 4 | 183 /// | Partition | Swap Index | Page 0 | Page 1 | Page 3 | Page 4 |
184 /// |-----------|------------|--------|--------|--------|--------| 184 /// |-----------|------------|--------|--------|--------|--------|
185 /// | Active | 0 | 1 | 2 | 3 | - | 185 /// | Active | 0 | 1 | 2 | 3 | - |
186 /// | DFU | 0 | 3 | 2 | 1 | X | 186 /// | DFU | 0 | 4 | 5 | 6 | X |
187 /// 187 ///
188 /// The algorithm starts by copying 'backwards', and after the first step, the layout is 188 /// The algorithm starts by copying 'backwards', and after the first step, the layout is
189 /// as follows: 189 /// as follows:
190 /// 190 ///
191 /// | Partition | Swap Index | Page 0 | Page 1 | Page 3 | Page 4 | 191 /// | Partition | Swap Index | Page 0 | Page 1 | Page 3 | Page 4 |
192 /// |-----------|------------|--------|--------|--------|--------| 192 /// |-----------|------------|--------|--------|--------|--------|
193 /// | Active | 1 | 1 | 2 | 1 | - | 193 /// | Active | 1 | 1 | 2 | 6 | - |
194 /// | DFU | 1 | 3 | 2 | 1 | 3 | 194 /// | DFU | 1 | 4 | 5 | 6 | 3 |
195 /// 195 ///
196 /// The next iteration performs the same steps 196 /// The next iteration performs the same steps
197 /// 197 ///
198 /// | Partition | Swap Index | Page 0 | Page 1 | Page 3 | Page 4 | 198 /// | Partition | Swap Index | Page 0 | Page 1 | Page 3 | Page 4 |
199 /// |-----------|------------|--------|--------|--------|--------| 199 /// |-----------|------------|--------|--------|--------|--------|
200 /// | Active | 2 | 1 | 2 | 1 | - | 200 /// | Active | 2 | 1 | 5 | 6 | - |
201 /// | DFU | 2 | 3 | 2 | 2 | 3 | 201 /// | DFU | 2 | 4 | 5 | 2 | 3 |
202 /// 202 ///
203 /// And again until we're done 203 /// And again until we're done
204 /// 204 ///
205 /// | Partition | Swap Index | Page 0 | Page 1 | Page 3 | Page 4 | 205 /// | Partition | Swap Index | Page 0 | Page 1 | Page 3 | Page 4 |
206 /// |-----------|------------|--------|--------|--------|--------| 206 /// |-----------|------------|--------|--------|--------|--------|
207 /// | Active | 3 | 3 | 2 | 1 | - | 207 /// | Active | 3 | 4 | 5 | 6 | - |
208 /// | DFU | 3 | 3 | 1 | 2 | 3 | 208 /// | DFU | 3 | 4 | 1 | 2 | 3 |
209 /// 209 ///
210 /// ## REVERTING 210 /// ## REVERTING
211 /// 211 ///
@@ -220,19 +220,19 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash> BootLoader<ACTIVE, DFU, S
220 /// 220 ///
221 /// | Partition | Revert Index | Page 0 | Page 1 | Page 3 | Page 4 | 221 /// | Partition | Revert Index | Page 0 | Page 1 | Page 3 | Page 4 |
222 /// |-----------|--------------|--------|--------|--------|--------| 222 /// |-----------|--------------|--------|--------|--------|--------|
223 /// | Active | 3 | 1 | 2 | 1 | - | 223 /// | Active | 3 | 1 | 5 | 6 | - |
224 /// | DFU | 3 | 3 | 1 | 2 | 3 | 224 /// | DFU | 3 | 4 | 1 | 2 | 3 |
225 /// 225 ///
226 /// 226 ///
227 /// | Partition | Revert Index | Page 0 | Page 1 | Page 3 | Page 4 | 227 /// | Partition | Revert Index | Page 0 | Page 1 | Page 3 | Page 4 |
228 /// |-----------|--------------|--------|--------|--------|--------| 228 /// |-----------|--------------|--------|--------|--------|--------|
229 /// | Active | 3 | 1 | 2 | 1 | - | 229 /// | Active | 3 | 1 | 2 | 6 | - |
230 /// | DFU | 3 | 3 | 2 | 2 | 3 | 230 /// | DFU | 3 | 4 | 5 | 2 | 3 |
231 /// 231 ///
232 /// | Partition | Revert Index | Page 0 | Page 1 | Page 3 | Page 4 | 232 /// | Partition | Revert Index | Page 0 | Page 1 | Page 3 | Page 4 |
233 /// |-----------|--------------|--------|--------|--------|--------| 233 /// |-----------|--------------|--------|--------|--------|--------|
234 /// | Active | 3 | 1 | 2 | 3 | - | 234 /// | Active | 3 | 1 | 2 | 3 | - |
235 /// | DFU | 3 | 3 | 2 | 1 | 3 | 235 /// | DFU | 3 | 4 | 5 | 6 | 3 |
236 /// 236 ///
237 pub fn prepare_boot(&mut self, aligned_buf: &mut [u8]) -> Result<State, BootError> { 237 pub fn prepare_boot(&mut self, aligned_buf: &mut [u8]) -> Result<State, BootError> {
238 // Ensure we have enough progress pages to store copy progress 238 // Ensure we have enough progress pages to store copy progress
diff --git a/embassy-boot/src/fmt.rs b/embassy-boot/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-boot/src/fmt.rs
+++ b/embassy-boot/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
index 779c04263..71ce09def 100644
--- a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
+++ b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
@@ -106,6 +106,11 @@ impl<'a, M: RawMutex, BUS: SetConfig> I2cDeviceWithConfig<'a, M, BUS> {
106 pub fn new(bus: &'a Mutex<M, BUS>, config: BUS::Config) -> Self { 106 pub fn new(bus: &'a Mutex<M, BUS>, config: BUS::Config) -> Self {
107 Self { bus, config } 107 Self { bus, config }
108 } 108 }
109
110 /// Change the device's config at runtime
111 pub fn set_config(&mut self, config: BUS::Config) {
112 self.config = config;
113 }
109} 114}
110 115
111impl<'a, M, BUS> i2c::ErrorType for I2cDeviceWithConfig<'a, M, BUS> 116impl<'a, M, BUS> i2c::ErrorType for I2cDeviceWithConfig<'a, M, BUS>
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
index 62b2c92a0..9890f218d 100644
--- a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
@@ -122,6 +122,11 @@ impl<'a, M: RawMutex, BUS: SetConfig, CS> SpiDeviceWithConfig<'a, M, BUS, CS> {
122 pub fn new(bus: &'a Mutex<M, BUS>, cs: CS, config: BUS::Config) -> Self { 122 pub fn new(bus: &'a Mutex<M, BUS>, cs: CS, config: BUS::Config) -> Self {
123 Self { bus, cs, config } 123 Self { bus, cs, config }
124 } 124 }
125
126 /// Change the device's config at runtime
127 pub fn set_config(&mut self, config: BUS::Config) {
128 self.config = config;
129 }
125} 130}
126 131
127impl<'a, M, BUS, CS> spi::ErrorType for SpiDeviceWithConfig<'a, M, BUS, CS> 132impl<'a, M, BUS, CS> spi::ErrorType for SpiDeviceWithConfig<'a, M, BUS, CS>
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
index 233c9e1fd..627767c8a 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
@@ -67,9 +67,11 @@ where
67 } 67 }
68 68
69 fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> { 69 fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> {
70 let _ = address; 70 self.bus.lock(|bus| {
71 let _ = operations; 71 bus.borrow_mut()
72 todo!() 72 .transaction(address, operations)
73 .map_err(I2cDeviceError::I2c)
74 })
73 } 75 }
74} 76}
75 77
@@ -130,6 +132,11 @@ impl<'a, M: RawMutex, BUS: SetConfig> I2cDeviceWithConfig<'a, M, BUS> {
130 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, config: BUS::Config) -> Self { 132 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, config: BUS::Config) -> Self {
131 Self { bus, config } 133 Self { bus, config }
132 } 134 }
135
136 /// Change the device's config at runtime
137 pub fn set_config(&mut self, config: BUS::Config) {
138 self.config = config;
139 }
133} 140}
134 141
135impl<'a, M, BUS> ErrorType for I2cDeviceWithConfig<'a, M, BUS> 142impl<'a, M, BUS> ErrorType for I2cDeviceWithConfig<'a, M, BUS>
@@ -171,8 +178,10 @@ where
171 } 178 }
172 179
173 fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> { 180 fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> {
174 let _ = address; 181 self.bus.lock(|bus| {
175 let _ = operations; 182 let mut bus = bus.borrow_mut();
176 todo!() 183 bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
184 bus.transaction(address, operations).map_err(I2cDeviceError::I2c)
185 })
177 } 186 }
178} 187}
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
index 59b65bfbd..801899f9f 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
@@ -147,6 +147,11 @@ impl<'a, M: RawMutex, BUS: SetConfig, CS> SpiDeviceWithConfig<'a, M, BUS, CS> {
147 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, cs: CS, config: BUS::Config) -> Self { 147 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, cs: CS, config: BUS::Config) -> Self {
148 Self { bus, cs, config } 148 Self { bus, cs, config }
149 } 149 }
150
151 /// Change the device's config at runtime
152 pub fn set_config(&mut self, config: BUS::Config) {
153 self.config = config;
154 }
150} 155}
151 156
152impl<'a, M, BUS, CS> spi::ErrorType for SpiDeviceWithConfig<'a, M, BUS, CS> 157impl<'a, M, BUS, CS> spi::ErrorType for SpiDeviceWithConfig<'a, M, BUS, CS>
diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs
index 1efb2788b..96c6267b2 100644
--- a/embassy-executor-macros/src/macros/task.rs
+++ b/embassy-executor-macros/src/macros/task.rs
@@ -93,10 +93,21 @@ pub fn run(args: &[NestedMeta], f: syn::ItemFn) -> Result<TokenStream, TokenStre
93 #[cfg(feature = "nightly")] 93 #[cfg(feature = "nightly")]
94 let mut task_outer: ItemFn = parse_quote! { 94 let mut task_outer: ItemFn = parse_quote! {
95 #visibility fn #task_ident(#fargs) -> ::embassy_executor::SpawnToken<impl Sized> { 95 #visibility fn #task_ident(#fargs) -> ::embassy_executor::SpawnToken<impl Sized> {
96 type Fut = impl ::core::future::Future + 'static; 96 trait _EmbassyInternalTaskTrait {
97 type Fut: ::core::future::Future + 'static;
98 fn construct(#fargs) -> Self::Fut;
99 }
100
101 impl _EmbassyInternalTaskTrait for () {
102 type Fut = impl core::future::Future + 'static;
103 fn construct(#fargs) -> Self::Fut {
104 #task_inner_ident(#(#full_args,)*)
105 }
106 }
107
97 const POOL_SIZE: usize = #pool_size; 108 const POOL_SIZE: usize = #pool_size;
98 static POOL: ::embassy_executor::raw::TaskPool<Fut, POOL_SIZE> = ::embassy_executor::raw::TaskPool::new(); 109 static POOL: ::embassy_executor::raw::TaskPool<<() as _EmbassyInternalTaskTrait>::Fut, POOL_SIZE> = ::embassy_executor::raw::TaskPool::new();
99 unsafe { POOL._spawn_async_fn(move || #task_inner_ident(#(#full_args,)*)) } 110 unsafe { POOL._spawn_async_fn(move || <() as _EmbassyInternalTaskTrait>::construct(#(#full_args,)*)) }
100 } 111 }
101 }; 112 };
102 #[cfg(not(feature = "nightly"))] 113 #[cfg(not(feature = "nightly"))]
diff --git a/embassy-executor-macros/src/util/ctxt.rs b/embassy-executor-macros/src/util/ctxt.rs
index 74c872c3c..9c78cda01 100644
--- a/embassy-executor-macros/src/util/ctxt.rs
+++ b/embassy-executor-macros/src/util/ctxt.rs
@@ -7,7 +7,6 @@ use std::thread;
7 7
8use proc_macro2::TokenStream; 8use proc_macro2::TokenStream;
9use quote::{quote, ToTokens}; 9use quote::{quote, ToTokens};
10use syn;
11 10
12/// A type to collect errors together and format them. 11/// A type to collect errors together and format them.
13/// 12///
diff --git a/embassy-executor/src/fmt.rs b/embassy-executor/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-executor/src/fmt.rs
+++ b/embassy-executor/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 3d5e3ab9f..d9ea5c005 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -30,7 +30,7 @@ use core::ptr::NonNull;
30use core::task::{Context, Poll}; 30use core::task::{Context, Poll};
31 31
32#[cfg(feature = "integrated-timers")] 32#[cfg(feature = "integrated-timers")]
33use embassy_time_driver::{self, AlarmHandle}; 33use embassy_time_driver::AlarmHandle;
34#[cfg(feature = "rtos-trace")] 34#[cfg(feature = "rtos-trace")]
35use rtos_trace::trace; 35use rtos_trace::trace;
36 36
diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs
index 2c2441dd5..348cc7dc4 100644
--- a/embassy-executor/tests/test.rs
+++ b/embassy-executor/tests/test.rs
@@ -1,4 +1,4 @@
1#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] 1#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))]
2 2
3use std::boxed::Box; 3use std::boxed::Box;
4use std::future::poll_fn; 4use std::future::poll_fn;
diff --git a/embassy-futures/src/fmt.rs b/embassy-futures/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-futures/src/fmt.rs
+++ b/embassy-futures/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-hal-internal/src/fmt.rs b/embassy-hal-internal/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-hal-internal/src/fmt.rs
+++ b/embassy-hal-internal/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-hal-internal/src/interrupt.rs b/embassy-hal-internal/src/interrupt.rs
index 19dabcf6f..5e64dce9d 100644
--- a/embassy-hal-internal/src/interrupt.rs
+++ b/embassy-hal-internal/src/interrupt.rs
@@ -30,14 +30,12 @@ macro_rules! interrupt_mod {
30 pub mod typelevel { 30 pub mod typelevel {
31 use super::InterruptExt; 31 use super::InterruptExt;
32 32
33 mod sealed { 33 trait SealedInterrupt {}
34 pub trait Interrupt {}
35 }
36 34
37 /// Type-level interrupt. 35 /// Type-level interrupt.
38 /// 36 ///
39 /// This trait is implemented for all typelevel interrupt types in this module. 37 /// This trait is implemented for all typelevel interrupt types in this module.
40 pub trait Interrupt: sealed::Interrupt { 38 pub trait Interrupt: SealedInterrupt {
41 39
42 /// Interrupt enum variant. 40 /// Interrupt enum variant.
43 /// 41 ///
@@ -105,7 +103,7 @@ macro_rules! interrupt_mod {
105 #[doc=stringify!($irqs)] 103 #[doc=stringify!($irqs)]
106 #[doc=" typelevel interrupt."] 104 #[doc=" typelevel interrupt."]
107 pub enum $irqs {} 105 pub enum $irqs {}
108 impl sealed::Interrupt for $irqs{} 106 impl SealedInterrupt for $irqs{}
109 impl Interrupt for $irqs { 107 impl Interrupt for $irqs {
110 const IRQ: super::Interrupt = super::Interrupt::$irqs; 108 const IRQ: super::Interrupt = super::Interrupt::$irqs;
111 } 109 }
diff --git a/embassy-net-adin1110/src/fmt.rs b/embassy-net-adin1110/src/fmt.rs
index 12737c690..2ac42c557 100644
--- a/embassy-net-adin1110/src/fmt.rs
+++ b/embassy-net-adin1110/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -83,14 +83,17 @@ macro_rules! todo {
83 }; 83 };
84} 84}
85 85
86#[cfg(not(feature = "defmt"))]
86macro_rules! unreachable { 87macro_rules! unreachable {
87 ($($x:tt)*) => { 88 ($($x:tt)*) => {
88 { 89 ::core::unreachable!($($x)*)
89 #[cfg(not(feature = "defmt"))] 90 };
90 ::core::unreachable!($($x)*); 91}
91 #[cfg(feature = "defmt")] 92
92 ::defmt::unreachable!($($x)*); 93#[cfg(feature = "defmt")]
93 } 94macro_rules! unreachable {
95 ($($x:tt)*) => {
96 ::defmt::unreachable!($($x)*)
94 }; 97 };
95} 98}
96 99
@@ -113,7 +116,7 @@ macro_rules! trace {
113 #[cfg(feature = "defmt")] 116 #[cfg(feature = "defmt")]
114 ::defmt::trace!($s $(, $x)*); 117 ::defmt::trace!($s $(, $x)*);
115 #[cfg(not(any(feature = "log", feature="defmt")))] 118 #[cfg(not(any(feature = "log", feature="defmt")))]
116 let _ignored = ($( & $x ),*); 119 let _ = ($( & $x ),*);
117 } 120 }
118 }; 121 };
119} 122}
@@ -126,7 +129,7 @@ macro_rules! debug {
126 #[cfg(feature = "defmt")] 129 #[cfg(feature = "defmt")]
127 ::defmt::debug!($s $(, $x)*); 130 ::defmt::debug!($s $(, $x)*);
128 #[cfg(not(any(feature = "log", feature="defmt")))] 131 #[cfg(not(any(feature = "log", feature="defmt")))]
129 let _ignored = ($( & $x ),*); 132 let _ = ($( & $x ),*);
130 } 133 }
131 }; 134 };
132} 135}
@@ -139,7 +142,7 @@ macro_rules! info {
139 #[cfg(feature = "defmt")] 142 #[cfg(feature = "defmt")]
140 ::defmt::info!($s $(, $x)*); 143 ::defmt::info!($s $(, $x)*);
141 #[cfg(not(any(feature = "log", feature="defmt")))] 144 #[cfg(not(any(feature = "log", feature="defmt")))]
142 let _ignored = ($( & $x ),*); 145 let _ = ($( & $x ),*);
143 } 146 }
144 }; 147 };
145} 148}
@@ -152,7 +155,7 @@ macro_rules! warn {
152 #[cfg(feature = "defmt")] 155 #[cfg(feature = "defmt")]
153 ::defmt::warn!($s $(, $x)*); 156 ::defmt::warn!($s $(, $x)*);
154 #[cfg(not(any(feature = "log", feature="defmt")))] 157 #[cfg(not(any(feature = "log", feature="defmt")))]
155 let _ignored = ($( & $x ),*); 158 let _ = ($( & $x ),*);
156 } 159 }
157 }; 160 };
158} 161}
@@ -165,7 +168,7 @@ macro_rules! error {
165 #[cfg(feature = "defmt")] 168 #[cfg(feature = "defmt")]
166 ::defmt::error!($s $(, $x)*); 169 ::defmt::error!($s $(, $x)*);
167 #[cfg(not(any(feature = "log", feature="defmt")))] 170 #[cfg(not(any(feature = "log", feature="defmt")))]
168 let _ignored = ($( & $x ),*); 171 let _ = ($( & $x ),*);
169 } 172 }
170 }; 173 };
171} 174}
@@ -226,7 +229,7 @@ impl<T, E> Try for Result<T, E> {
226 } 229 }
227} 230}
228 231
229pub struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
230 233
231impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
232 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 235 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
diff --git a/embassy-net-driver-channel/src/fmt.rs b/embassy-net-driver-channel/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-net-driver-channel/src/fmt.rs
+++ b/embassy-net-driver-channel/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-net-enc28j60/src/fmt.rs b/embassy-net-enc28j60/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-net-enc28j60/src/fmt.rs
+++ b/embassy-net-enc28j60/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-net-enc28j60/src/lib.rs b/embassy-net-enc28j60/src/lib.rs
index f18134927..dda35f498 100644
--- a/embassy-net-enc28j60/src/lib.rs
+++ b/embassy-net-enc28j60/src/lib.rs
@@ -17,7 +17,6 @@ mod phy;
17mod traits; 17mod traits;
18 18
19use core::cmp; 19use core::cmp;
20use core::convert::TryInto;
21 20
22use embassy_net_driver::{Capabilities, HardwareAddress, LinkState}; 21use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
23use embassy_time::Duration; 22use embassy_time::Duration;
@@ -645,8 +644,8 @@ where
645 Self: 'a; 644 Self: 'a;
646 645
647 fn receive(&mut self, cx: &mut core::task::Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { 646 fn receive(&mut self, cx: &mut core::task::Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
648 let rx_buf = unsafe { &mut RX_BUF }; 647 let rx_buf = unsafe { &mut *core::ptr::addr_of_mut!(RX_BUF) };
649 let tx_buf = unsafe { &mut TX_BUF }; 648 let tx_buf = unsafe { &mut *core::ptr::addr_of_mut!(TX_BUF) };
650 if let Some(n) = self.receive(rx_buf) { 649 if let Some(n) = self.receive(rx_buf) {
651 Some((RxToken { buf: &mut rx_buf[..n] }, TxToken { buf: tx_buf, eth: self })) 650 Some((RxToken { buf: &mut rx_buf[..n] }, TxToken { buf: tx_buf, eth: self }))
652 } else { 651 } else {
@@ -656,7 +655,7 @@ where
656 } 655 }
657 656
658 fn transmit(&mut self, _cx: &mut core::task::Context) -> Option<Self::TxToken<'_>> { 657 fn transmit(&mut self, _cx: &mut core::task::Context) -> Option<Self::TxToken<'_>> {
659 let tx_buf = unsafe { &mut TX_BUF }; 658 let tx_buf = unsafe { &mut *core::ptr::addr_of_mut!(TX_BUF) };
660 Some(TxToken { buf: tx_buf, eth: self }) 659 Some(TxToken { buf: tx_buf, eth: self })
661 } 660 }
662 661
diff --git a/embassy-net-esp-hosted/src/fmt.rs b/embassy-net-esp-hosted/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-net-esp-hosted/src/fmt.rs
+++ b/embassy-net-esp-hosted/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-net-ppp/src/fmt.rs b/embassy-net-ppp/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-net-ppp/src/fmt.rs
+++ b/embassy-net-ppp/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-net-tuntap/src/lib.rs b/embassy-net-tuntap/src/lib.rs
index de30934eb..56f55fba1 100644
--- a/embassy-net-tuntap/src/lib.rs
+++ b/embassy-net-tuntap/src/lib.rs
@@ -6,7 +6,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
6use std::task::Context; 6use std::task::Context;
7 7
8use async_io::Async; 8use async_io::Async;
9use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState}; 9use embassy_net_driver::{Capabilities, Driver, HardwareAddress, LinkState};
10use log::*; 10use log::*;
11 11
12/// Get the MTU of the given interface. 12/// Get the MTU of the given interface.
diff --git a/embassy-net-wiznet/src/chip/mod.rs b/embassy-net-wiznet/src/chip/mod.rs
index b987c2b36..e1f963d95 100644
--- a/embassy-net-wiznet/src/chip/mod.rs
+++ b/embassy-net-wiznet/src/chip/mod.rs
@@ -2,49 +2,40 @@
2mod w5500; 2mod w5500;
3pub use w5500::W5500; 3pub use w5500::W5500;
4mod w5100s; 4mod w5100s;
5use embedded_hal_async::spi::SpiDevice;
5pub use w5100s::W5100S; 6pub use w5100s::W5100S;
6 7
7pub(crate) mod sealed { 8pub(crate) trait SealedChip {
8 use embedded_hal_async::spi::SpiDevice; 9 type Address;
9 10
10 pub trait Chip { 11 const COMMON_MODE: Self::Address;
11 type Address; 12 const COMMON_MAC: Self::Address;
12 13 const COMMON_SOCKET_INTR: Self::Address;
13 const COMMON_MODE: Self::Address; 14 const COMMON_PHY_CFG: Self::Address;
14 const COMMON_MAC: Self::Address; 15 const SOCKET_MODE: Self::Address;
15 const COMMON_SOCKET_INTR: Self::Address; 16 const SOCKET_COMMAND: Self::Address;
16 const COMMON_PHY_CFG: Self::Address; 17 const SOCKET_RXBUF_SIZE: Self::Address;
17 const SOCKET_MODE: Self::Address; 18 const SOCKET_TXBUF_SIZE: Self::Address;
18 const SOCKET_COMMAND: Self::Address; 19 const SOCKET_TX_FREE_SIZE: Self::Address;
19 const SOCKET_RXBUF_SIZE: Self::Address; 20 const SOCKET_TX_DATA_WRITE_PTR: Self::Address;
20 const SOCKET_TXBUF_SIZE: Self::Address; 21 const SOCKET_RECVD_SIZE: Self::Address;
21 const SOCKET_TX_FREE_SIZE: Self::Address; 22 const SOCKET_RX_DATA_READ_PTR: Self::Address;
22 const SOCKET_TX_DATA_WRITE_PTR: Self::Address; 23 const SOCKET_INTR_MASK: Self::Address;
23 const SOCKET_RECVD_SIZE: Self::Address; 24 const SOCKET_INTR: Self::Address;
24 const SOCKET_RX_DATA_READ_PTR: Self::Address; 25
25 const SOCKET_INTR_MASK: Self::Address; 26 const SOCKET_MODE_VALUE: u8;
26 const SOCKET_INTR: Self::Address; 27
27 28 const BUF_SIZE: u16;
28 const SOCKET_MODE_VALUE: u8; 29 const AUTO_WRAP: bool;
29 30
30 const BUF_SIZE: u16; 31 fn rx_addr(addr: u16) -> Self::Address;
31 const AUTO_WRAP: bool; 32 fn tx_addr(addr: u16) -> Self::Address;
32 33
33 fn rx_addr(addr: u16) -> Self::Address; 34 async fn bus_read<SPI: SpiDevice>(spi: &mut SPI, address: Self::Address, data: &mut [u8])
34 fn tx_addr(addr: u16) -> Self::Address; 35 -> Result<(), SPI::Error>;
35 36 async fn bus_write<SPI: SpiDevice>(spi: &mut SPI, address: Self::Address, data: &[u8]) -> Result<(), SPI::Error>;
36 async fn bus_read<SPI: SpiDevice>(
37 spi: &mut SPI,
38 address: Self::Address,
39 data: &mut [u8],
40 ) -> Result<(), SPI::Error>;
41 async fn bus_write<SPI: SpiDevice>(
42 spi: &mut SPI,
43 address: Self::Address,
44 data: &[u8],
45 ) -> Result<(), SPI::Error>;
46 }
47} 37}
48 38
49/// Trait for Wiznet chips. 39/// Trait for Wiznet chips.
50pub trait Chip: sealed::Chip {} 40#[allow(private_bounds)]
41pub trait Chip: SealedChip {}
diff --git a/embassy-net-wiznet/src/chip/w5100s.rs b/embassy-net-wiznet/src/chip/w5100s.rs
index 7d328bce5..23ce3ed83 100644
--- a/embassy-net-wiznet/src/chip/w5100s.rs
+++ b/embassy-net-wiznet/src/chip/w5100s.rs
@@ -8,7 +8,7 @@ const RX_BASE: u16 = 0x6000;
8pub enum W5100S {} 8pub enum W5100S {}
9 9
10impl super::Chip for W5100S {} 10impl super::Chip for W5100S {}
11impl super::sealed::Chip for W5100S { 11impl super::SealedChip for W5100S {
12 type Address = u16; 12 type Address = u16;
13 13
14 const COMMON_MODE: Self::Address = 0x00; 14 const COMMON_MODE: Self::Address = 0x00;
diff --git a/embassy-net-wiznet/src/chip/w5500.rs b/embassy-net-wiznet/src/chip/w5500.rs
index 16236126d..12e610ea2 100644
--- a/embassy-net-wiznet/src/chip/w5500.rs
+++ b/embassy-net-wiznet/src/chip/w5500.rs
@@ -12,7 +12,7 @@ pub enum RegisterBlock {
12pub enum W5500 {} 12pub enum W5500 {}
13 13
14impl super::Chip for W5500 {} 14impl super::Chip for W5500 {}
15impl super::sealed::Chip for W5500 { 15impl super::SealedChip for W5500 {
16 type Address = (RegisterBlock, u16); 16 type Address = (RegisterBlock, u16);
17 17
18 const COMMON_MODE: Self::Address = (RegisterBlock::Common, 0x00); 18 const COMMON_MODE: Self::Address = (RegisterBlock::Common, 0x00);
diff --git a/embassy-net/src/fmt.rs b/embassy-net/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-net/src/fmt.rs
+++ b/embassy-net/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-nrf/src/fmt.rs b/embassy-nrf/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-nrf/src/fmt.rs
+++ b/embassy-nrf/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 3649ea61a..f2353f21d 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -473,10 +473,12 @@ impl sealed::Pin for AnyPin {
473 473
474// ==================== 474// ====================
475 475
476#[cfg(not(feature = "_nrf51"))]
476pub(crate) trait PselBits { 477pub(crate) trait PselBits {
477 fn psel_bits(&self) -> u32; 478 fn psel_bits(&self) -> u32;
478} 479}
479 480
481#[cfg(not(feature = "_nrf51"))]
480impl<'a, P: Pin> PselBits for Option<PeripheralRef<'a, P>> { 482impl<'a, P: Pin> PselBits for Option<PeripheralRef<'a, P>> {
481 #[inline] 483 #[inline]
482 fn psel_bits(&self) -> u32 { 484 fn psel_bits(&self) -> u32 {
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 12f4ed0a0..4a28279a9 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -167,8 +167,10 @@ unsafe fn handle_gpiote_interrupt() {
167 } 167 }
168} 168}
169 169
170#[cfg(not(feature = "_nrf51"))]
170struct BitIter(u32); 171struct BitIter(u32);
171 172
173#[cfg(not(feature = "_nrf51"))]
172impl Iterator for BitIter { 174impl Iterator for BitIter {
173 type Item = u32; 175 type Item = u32;
174 176
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 718f229a3..3457dd933 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -225,10 +225,31 @@ pub mod config {
225 /// Config for the first stage DCDC (VDDH -> VDD), if disabled LDO will be used. 225 /// Config for the first stage DCDC (VDDH -> VDD), if disabled LDO will be used.
226 #[cfg(feature = "nrf52840")] 226 #[cfg(feature = "nrf52840")]
227 pub reg0: bool, 227 pub reg0: bool,
228 /// Configure the voltage of the first stage DCDC. It is stored in non-volatile memory (UICR.REGOUT0 register); pass None to not touch it.
229 #[cfg(feature = "nrf52840")]
230 pub reg0_voltage: Option<Reg0Voltage>,
228 /// Config for the second stage DCDC (VDD -> DEC4), if disabled LDO will be used. 231 /// Config for the second stage DCDC (VDD -> DEC4), if disabled LDO will be used.
229 pub reg1: bool, 232 pub reg1: bool,
230 } 233 }
231 234
235 /// Output voltage setting for REG0 regulator stage.
236 #[cfg(feature = "nrf52840")]
237 pub enum Reg0Voltage {
238 /// 1.8 V
239 _1V8 = 0,
240 /// 2.1 V
241 _2V1 = 1,
242 /// 2.4 V
243 _2V4 = 2,
244 /// 2.7 V
245 _2V7 = 3,
246 /// 3.0 V
247 _3V0 = 4,
248 /// 3.3 V
249 _3v3 = 5,
250 //ERASED = 7, means 1.8V
251 }
252
232 /// Settings for enabling the built in DCDC converters. 253 /// Settings for enabling the built in DCDC converters.
233 #[cfg(feature = "_nrf5340-app")] 254 #[cfg(feature = "_nrf5340-app")]
234 pub struct DcdcConfig { 255 pub struct DcdcConfig {
@@ -279,6 +300,8 @@ pub mod config {
279 dcdc: DcdcConfig { 300 dcdc: DcdcConfig {
280 #[cfg(feature = "nrf52840")] 301 #[cfg(feature = "nrf52840")]
281 reg0: false, 302 reg0: false,
303 #[cfg(feature = "nrf52840")]
304 reg0_voltage: None,
282 reg1: false, 305 reg1: false,
283 }, 306 },
284 #[cfg(feature = "_nrf5340-app")] 307 #[cfg(feature = "_nrf5340-app")]
@@ -337,6 +360,7 @@ mod consts {
337 pub const UICR_PSELRESET2: *mut u32 = 0x10001204 as *mut u32; 360 pub const UICR_PSELRESET2: *mut u32 = 0x10001204 as *mut u32;
338 pub const UICR_NFCPINS: *mut u32 = 0x1000120C as *mut u32; 361 pub const UICR_NFCPINS: *mut u32 = 0x1000120C as *mut u32;
339 pub const UICR_APPROTECT: *mut u32 = 0x10001208 as *mut u32; 362 pub const UICR_APPROTECT: *mut u32 = 0x10001208 as *mut u32;
363 pub const UICR_REGOUT0: *mut u32 = 0x10001304 as *mut u32;
340 pub const APPROTECT_ENABLED: u32 = 0x0000_0000; 364 pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
341 pub const APPROTECT_DISABLED: u32 = 0x0000_005a; 365 pub const APPROTECT_DISABLED: u32 = 0x0000_005a;
342} 366}
@@ -493,6 +517,21 @@ pub fn init(config: config::Config) -> Peripherals {
493 } 517 }
494 } 518 }
495 519
520 #[cfg(feature = "nrf52840")]
521 unsafe {
522 if let Some(value) = config.dcdc.reg0_voltage {
523 let value = value as u32;
524 let res = uicr_write_masked(consts::UICR_REGOUT0, value, 0b00000000_00000000_00000000_00000111);
525 needs_reset |= res == WriteResult::Written;
526 if res == WriteResult::Failed {
527 warn!(
528 "Failed to set regulator voltage, as UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
529 To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`."
530 );
531 }
532 }
533 }
534
496 if needs_reset { 535 if needs_reset {
497 cortex_m::peripheral::SCB::sys_reset(); 536 cortex_m::peripheral::SCB::sys_reset();
498 } 537 }
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index 3c35baee5..2970ad3f2 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -21,8 +21,6 @@ pub(crate) mod sealed {
21 fn regs() -> &'static pac::timer0::RegisterBlock; 21 fn regs() -> &'static pac::timer0::RegisterBlock;
22 } 22 }
23 pub trait ExtendedInstance {} 23 pub trait ExtendedInstance {}
24
25 pub trait TimerType {}
26} 24}
27 25
28/// Basic Timer instance. 26/// Basic Timer instance.
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 088a842a1..44aabce6b 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -96,7 +96,7 @@ pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
96) -> Transfer<'a, C> { 96) -> Transfer<'a, C> {
97 copy_inner( 97 copy_inner(
98 ch, 98 ch,
99 &mut DUMMY as *const u32, 99 core::ptr::addr_of_mut!(DUMMY) as *const u32,
100 to as *mut u32, 100 to as *mut u32,
101 len, 101 len,
102 W::size(), 102 W::size(),
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
index 8bac93684..422b77400 100644
--- a/embassy-rp/src/flash.rs
+++ b/embassy-rp/src/flash.rs
@@ -420,8 +420,6 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> embedded_storage_async::nor_flash
420 420
421#[allow(dead_code)] 421#[allow(dead_code)]
422mod ram_helpers { 422mod ram_helpers {
423 use core::marker::PhantomData;
424
425 use super::*; 423 use super::*;
426 use crate::rom_data; 424 use crate::rom_data;
427 425
diff --git a/embassy-rp/src/float/mod.rs b/embassy-rp/src/float/mod.rs
index 945afff90..3ad6f1c50 100644
--- a/embassy-rp/src/float/mod.rs
+++ b/embassy-rp/src/float/mod.rs
@@ -89,6 +89,7 @@ pub(crate) trait Float:
89 } 89 }
90 90
91 /// Returns true if `self` is infinity 91 /// Returns true if `self` is infinity
92 #[allow(unused)]
92 fn is_infinity(self) -> bool { 93 fn is_infinity(self) -> bool {
93 (self.repr() & (Self::EXPONENT_MASK | Self::SIGNIFICAND_MASK)) == Self::EXPONENT_MASK 94 (self.repr() & (Self::EXPONENT_MASK | Self::SIGNIFICAND_MASK)) == Self::EXPONENT_MASK
94 } 95 }
diff --git a/embassy-rp/src/fmt.rs b/embassy-rp/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-rp/src/fmt.rs
+++ b/embassy-rp/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 405bddfd8..a84c00a2c 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -976,8 +976,6 @@ impl_pin!(PIN_QSPI_SD3, Bank::Qspi, 5);
976// ==================== 976// ====================
977 977
978mod eh02 { 978mod eh02 {
979 use core::convert::Infallible;
980
981 use super::*; 979 use super::*;
982 980
983 impl<'d> embedded_hal_02::digital::v2::InputPin for Input<'d> { 981 impl<'d> embedded_hal_02::digital::v2::InputPin for Input<'d> {
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 7092b3fab..d91cea410 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -274,7 +274,7 @@ pub fn install_core0_stack_guard() -> Result<(), ()> {
274 extern "C" { 274 extern "C" {
275 static mut _stack_end: usize; 275 static mut _stack_end: usize;
276 } 276 }
277 unsafe { install_stack_guard(&mut _stack_end as *mut usize) } 277 unsafe { install_stack_guard(core::ptr::addr_of_mut!(_stack_end)) }
278} 278}
279 279
280#[inline(always)] 280#[inline(always)]
@@ -354,6 +354,7 @@ pub fn init(config: config::Config) -> Peripherals {
354 354
355/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. 355/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes.
356trait RegExt<T: Copy> { 356trait RegExt<T: Copy> {
357 #[allow(unused)]
357 fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; 358 fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
358 fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; 359 fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
359 fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; 360 fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
diff --git a/embassy-rp/src/relocate.rs b/embassy-rp/src/relocate.rs
index 40cb2667b..34487819f 100644
--- a/embassy-rp/src/relocate.rs
+++ b/embassy-rp/src/relocate.rs
@@ -1,5 +1,3 @@
1use core::iter::Iterator;
2
3use pio::{Program, SideSet, Wrap}; 1use pio::{Program, SideSet, Wrap};
4 2
5pub struct CodeIterator<'a, I> 3pub struct CodeIterator<'a, I>
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index 7622539f1..da1157984 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -1,17 +1,11 @@
1//! Buffered UART driver. 1//! Buffered UART driver.
2use core::future::{poll_fn, Future}; 2use core::future::Future;
3use core::slice; 3use core::slice;
4use core::task::Poll;
5 4
6use atomic_polyfill::{AtomicU8, Ordering}; 5use atomic_polyfill::AtomicU8;
7use embassy_hal_internal::atomic_ring_buffer::RingBuffer; 6use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
8use embassy_sync::waitqueue::AtomicWaker;
9use embassy_time::Timer;
10 7
11use super::*; 8use super::*;
12use crate::clocks::clk_peri_freq;
13use crate::interrupt::typelevel::{Binding, Interrupt};
14use crate::{interrupt, RegExt};
15 9
16pub struct State { 10pub struct State {
17 tx_waker: AtomicWaker, 11 tx_waker: AtomicWaker,
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs
index 905661d64..d68dee4a3 100644
--- a/embassy-rp/src/usb.rs
+++ b/embassy-rp/src/usb.rs
@@ -465,7 +465,6 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
465 465
466trait Dir { 466trait Dir {
467 fn dir() -> Direction; 467 fn dir() -> Direction;
468 fn waker(i: usize) -> &'static AtomicWaker;
469} 468}
470 469
471/// Type for In direction. 470/// Type for In direction.
@@ -474,11 +473,6 @@ impl Dir for In {
474 fn dir() -> Direction { 473 fn dir() -> Direction {
475 Direction::In 474 Direction::In
476 } 475 }
477
478 #[inline]
479 fn waker(i: usize) -> &'static AtomicWaker {
480 &EP_IN_WAKERS[i]
481 }
482} 476}
483 477
484/// Type for Out direction. 478/// Type for Out direction.
@@ -487,11 +481,6 @@ impl Dir for Out {
487 fn dir() -> Direction { 481 fn dir() -> Direction {
488 Direction::Out 482 Direction::Out
489 } 483 }
490
491 #[inline]
492 fn waker(i: usize) -> &'static AtomicWaker {
493 &EP_OUT_WAKERS[i]
494 }
495} 484}
496 485
497/// Endpoint for RP USB driver. 486/// Endpoint for RP USB driver.
diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs
index bd70851ea..6aaef1d35 100644
--- a/embassy-stm32-wpan/src/consts.rs
+++ b/embassy-stm32-wpan/src/consts.rs
@@ -1,5 +1,3 @@
1use core::convert::TryFrom;
2
3use crate::evt::CsEvt; 1use crate::evt::CsEvt;
4use crate::PacketHeader; 2use crate::PacketHeader;
5 3
diff --git a/embassy-stm32-wpan/src/fmt.rs b/embassy-stm32-wpan/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-stm32-wpan/src/fmt.rs
+++ b/embassy-stm32-wpan/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index d3626610e..7c6312f6c 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -70,7 +70,7 @@ rand_core = "0.6.3"
70sdio-host = "0.5.0" 70sdio-host = "0.5.0"
71critical-section = "1.1" 71critical-section = "1.1"
72#stm32-metapac = { version = "15" } 72#stm32-metapac = { version = "15" }
73stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c8b32ecae7d70cea2705095c4fc6bd5f59d238d5" } 73stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f84633553331c2d154ee72de779a40cbb10fd1bd" }
74vcell = "0.1.3" 74vcell = "0.1.3"
75nb = "1.0.0" 75nb = "1.0.0"
76stm32-fmc = "0.3.0" 76stm32-fmc = "0.3.0"
@@ -94,7 +94,7 @@ critical-section = { version = "1.1", features = ["std"] }
94proc-macro2 = "1.0.36" 94proc-macro2 = "1.0.36"
95quote = "1.0.15" 95quote = "1.0.15"
96#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} 96#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
97stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c8b32ecae7d70cea2705095c4fc6bd5f59d238d5", default-features = false, features = ["metadata"]} 97stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f84633553331c2d154ee72de779a40cbb10fd1bd", default-features = false, features = ["metadata"]}
98 98
99 99
100[features] 100[features]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index fe5236ed6..15bb8ea62 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -584,7 +584,7 @@ fn main() {
584 }; 584 };
585 585
586 g.extend(quote! { 586 g.extend(quote! {
587 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { 587 impl crate::rcc::SealedRccPeripheral for peripherals::#pname {
588 fn frequency() -> crate::time::Hertz { 588 fn frequency() -> crate::time::Hertz {
589 #clock_frequency 589 #clock_frequency
590 } 590 }
@@ -826,20 +826,20 @@ fn main() {
826 (("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)), 826 (("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)),
827 (("usb", "DP"), quote!(crate::usb::DpPin)), 827 (("usb", "DP"), quote!(crate::usb::DpPin)),
828 (("usb", "DM"), quote!(crate::usb::DmPin)), 828 (("usb", "DM"), quote!(crate::usb::DmPin)),
829 (("otg", "DP"), quote!(crate::usb_otg::DpPin)), 829 (("otg", "DP"), quote!(crate::usb::DpPin)),
830 (("otg", "DM"), quote!(crate::usb_otg::DmPin)), 830 (("otg", "DM"), quote!(crate::usb::DmPin)),
831 (("otg", "ULPI_CK"), quote!(crate::usb_otg::UlpiClkPin)), 831 (("otg", "ULPI_CK"), quote!(crate::usb::UlpiClkPin)),
832 (("otg", "ULPI_DIR"), quote!(crate::usb_otg::UlpiDirPin)), 832 (("otg", "ULPI_DIR"), quote!(crate::usb::UlpiDirPin)),
833 (("otg", "ULPI_NXT"), quote!(crate::usb_otg::UlpiNxtPin)), 833 (("otg", "ULPI_NXT"), quote!(crate::usb::UlpiNxtPin)),
834 (("otg", "ULPI_STP"), quote!(crate::usb_otg::UlpiStpPin)), 834 (("otg", "ULPI_STP"), quote!(crate::usb::UlpiStpPin)),
835 (("otg", "ULPI_D0"), quote!(crate::usb_otg::UlpiD0Pin)), 835 (("otg", "ULPI_D0"), quote!(crate::usb::UlpiD0Pin)),
836 (("otg", "ULPI_D1"), quote!(crate::usb_otg::UlpiD1Pin)), 836 (("otg", "ULPI_D1"), quote!(crate::usb::UlpiD1Pin)),
837 (("otg", "ULPI_D2"), quote!(crate::usb_otg::UlpiD2Pin)), 837 (("otg", "ULPI_D2"), quote!(crate::usb::UlpiD2Pin)),
838 (("otg", "ULPI_D3"), quote!(crate::usb_otg::UlpiD3Pin)), 838 (("otg", "ULPI_D3"), quote!(crate::usb::UlpiD3Pin)),
839 (("otg", "ULPI_D4"), quote!(crate::usb_otg::UlpiD4Pin)), 839 (("otg", "ULPI_D4"), quote!(crate::usb::UlpiD4Pin)),
840 (("otg", "ULPI_D5"), quote!(crate::usb_otg::UlpiD5Pin)), 840 (("otg", "ULPI_D5"), quote!(crate::usb::UlpiD5Pin)),
841 (("otg", "ULPI_D6"), quote!(crate::usb_otg::UlpiD6Pin)), 841 (("otg", "ULPI_D6"), quote!(crate::usb::UlpiD6Pin)),
842 (("otg", "ULPI_D7"), quote!(crate::usb_otg::UlpiD7Pin)), 842 (("otg", "ULPI_D7"), quote!(crate::usb::UlpiD7Pin)),
843 (("can", "TX"), quote!(crate::can::TxPin)), 843 (("can", "TX"), quote!(crate::can::TxPin)),
844 (("can", "RX"), quote!(crate::can::RxPin)), 844 (("can", "RX"), quote!(crate::can::RxPin)),
845 (("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)), 845 (("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)),
@@ -1486,7 +1486,7 @@ fn main() {
1486 #[crate::interrupt] 1486 #[crate::interrupt]
1487 unsafe fn #irq () { 1487 unsafe fn #irq () {
1488 #( 1488 #(
1489 <crate::peripherals::#channels as crate::dma::sealed::ChannelInterrupt>::on_irq(); 1489 <crate::peripherals::#channels as crate::dma::ChannelInterrupt>::on_irq();
1490 )* 1490 )*
1491 } 1491 }
1492 } 1492 }
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index b27b99827..cecf67947 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -33,7 +33,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
33 33
34pub struct Vref; 34pub struct Vref;
35impl<T: Instance> AdcPin<T> for Vref {} 35impl<T: Instance> AdcPin<T> for Vref {}
36impl<T: Instance> super::sealed::AdcPin<T> for Vref { 36impl<T: Instance> super::SealedAdcPin<T> for Vref {
37 fn channel(&self) -> u8 { 37 fn channel(&self) -> u8 {
38 17 38 17
39 } 39 }
@@ -41,7 +41,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Vref {
41 41
42pub struct Temperature; 42pub struct Temperature;
43impl<T: Instance> AdcPin<T> for Temperature {} 43impl<T: Instance> AdcPin<T> for Temperature {}
44impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 44impl<T: Instance> super::SealedAdcPin<T> for Temperature {
45 fn channel(&self) -> u8 { 45 fn channel(&self) -> u8 {
46 16 46 16
47 } 47 }
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs
index efade1f64..c5581dba1 100644
--- a/embassy-stm32/src/adc/f3.rs
+++ b/embassy-stm32/src/adc/f3.rs
@@ -33,7 +33,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
33 33
34pub struct Vref; 34pub struct Vref;
35impl<T: Instance> AdcPin<T> for Vref {} 35impl<T: Instance> AdcPin<T> for Vref {}
36impl<T: Instance> super::sealed::AdcPin<T> for Vref { 36impl<T: Instance> super::SealedAdcPin<T> for Vref {
37 fn channel(&self) -> u8 { 37 fn channel(&self) -> u8 {
38 18 38 18
39 } 39 }
@@ -48,7 +48,7 @@ impl Vref {
48 48
49pub struct Temperature; 49pub struct Temperature;
50impl<T: Instance> AdcPin<T> for Temperature {} 50impl<T: Instance> AdcPin<T> for Temperature {}
51impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 51impl<T: Instance> super::SealedAdcPin<T> for Temperature {
52 fn channel(&self) -> u8 { 52 fn channel(&self) -> u8 {
53 16 53 16
54 } 54 }
@@ -102,7 +102,7 @@ impl<'d, T: Instance> Adc<'d, T> {
102 } 102 }
103 103
104 fn freq() -> Hertz { 104 fn freq() -> Hertz {
105 <T as crate::rcc::sealed::RccPeripheral>::frequency() 105 <T as crate::rcc::SealedRccPeripheral>::frequency()
106 } 106 }
107 107
108 pub fn sample_time_for_us(&self, us: u32) -> SampleTime { 108 pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
diff --git a/embassy-stm32/src/adc/f3_v1_1.rs b/embassy-stm32/src/adc/f3_v1_1.rs
index f842893fa..672ace04f 100644
--- a/embassy-stm32/src/adc/f3_v1_1.rs
+++ b/embassy-stm32/src/adc/f3_v1_1.rs
@@ -65,7 +65,7 @@ fn update_vref<T: Instance>(op: i8) {
65 65
66pub struct Vref<T: Instance>(core::marker::PhantomData<T>); 66pub struct Vref<T: Instance>(core::marker::PhantomData<T>);
67impl<T: Instance> AdcPin<T> for Vref<T> {} 67impl<T: Instance> AdcPin<T> for Vref<T> {}
68impl<T: Instance> super::sealed::AdcPin<T> for Vref<T> { 68impl<T: Instance> super::SealedAdcPin<T> for Vref<T> {
69 fn channel(&self) -> u8 { 69 fn channel(&self) -> u8 {
70 17 70 17
71 } 71 }
@@ -124,7 +124,7 @@ impl<T: Instance> Drop for Vref<T> {
124 124
125pub struct Temperature<T: Instance>(core::marker::PhantomData<T>); 125pub struct Temperature<T: Instance>(core::marker::PhantomData<T>);
126impl<T: Instance> AdcPin<T> for Temperature<T> {} 126impl<T: Instance> AdcPin<T> for Temperature<T> {}
127impl<T: Instance> super::sealed::AdcPin<T> for Temperature<T> { 127impl<T: Instance> super::SealedAdcPin<T> for Temperature<T> {
128 fn channel(&self) -> u8 { 128 fn channel(&self) -> u8 {
129 16 129 16
130 } 130 }
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 0d0d40549..ead2357ce 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -17,6 +17,8 @@ mod _version;
17#[allow(unused)] 17#[allow(unused)]
18#[cfg(not(adc_f3_v2))] 18#[cfg(not(adc_f3_v2))]
19pub use _version::*; 19pub use _version::*;
20#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
21use embassy_sync::waitqueue::AtomicWaker;
20 22
21#[cfg(not(any(adc_f1, adc_f3_v2)))] 23#[cfg(not(any(adc_f1, adc_f3_v2)))]
22pub use crate::pac::adc::vals::Res as Resolution; 24pub use crate::pac::adc::vals::Res as Resolution;
@@ -31,63 +33,65 @@ pub struct Adc<'d, T: Instance> {
31 sample_time: SampleTime, 33 sample_time: SampleTime,
32} 34}
33 35
34pub(crate) mod sealed { 36#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
35 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] 37pub struct State {
36 use embassy_sync::waitqueue::AtomicWaker; 38 pub waker: AtomicWaker,
37 39}
38 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
39 pub struct State {
40 pub waker: AtomicWaker,
41 }
42 40
43 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] 41#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
44 impl State { 42impl State {
45 pub const fn new() -> Self { 43 pub const fn new() -> Self {
46 Self { 44 Self {
47 waker: AtomicWaker::new(), 45 waker: AtomicWaker::new(),
48 }
49 } 46 }
50 } 47 }
48}
51 49
52 pub trait InterruptableInstance { 50trait SealedInstance {
53 type Interrupt: crate::interrupt::typelevel::Interrupt; 51 #[allow(unused)]
54 } 52 fn regs() -> crate::pac::adc::Adc;
55 53 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
56 pub trait Instance: InterruptableInstance { 54 fn common_regs() -> crate::pac::adccommon::AdcCommon;
57 fn regs() -> crate::pac::adc::Adc; 55 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
58 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] 56 fn state() -> &'static State;
59 fn common_regs() -> crate::pac::adccommon::AdcCommon; 57}
60 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
61 fn state() -> &'static State;
62 }
63 58
64 pub trait AdcPin<T: Instance> { 59pub(crate) trait SealedAdcPin<T: Instance> {
65 #[cfg(any(adc_v1, adc_l0, adc_v2))] 60 #[cfg(any(adc_v1, adc_l0, adc_v2))]
66 fn set_as_analog(&mut self) {} 61 fn set_as_analog(&mut self) {}
67 62
68 fn channel(&self) -> u8; 63 #[allow(unused)]
69 } 64 fn channel(&self) -> u8;
65}
70 66
71 pub trait InternalChannel<T> { 67trait SealedInternalChannel<T> {
72 fn channel(&self) -> u8; 68 #[allow(unused)]
73 } 69 fn channel(&self) -> u8;
74} 70}
75 71
76/// ADC instance. 72/// ADC instance.
77#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5)))] 73#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5)))]
78pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} 74#[allow(private_bounds)]
75pub trait Instance: SealedInstance + crate::Peripheral<P = Self> {
76 type Interrupt: crate::interrupt::typelevel::Interrupt;
77}
79/// ADC instance. 78/// ADC instance.
80#[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5))] 79#[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5))]
81pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} 80#[allow(private_bounds)]
81pub trait Instance: SealedInstance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {
82 type Interrupt: crate::interrupt::typelevel::Interrupt;
83}
82 84
83/// ADC pin. 85/// ADC pin.
84pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} 86#[allow(private_bounds)]
87pub trait AdcPin<T: Instance>: SealedAdcPin<T> {}
85/// ADC internal channel. 88/// ADC internal channel.
86pub trait InternalChannel<T>: sealed::InternalChannel<T> {} 89#[allow(private_bounds)]
90pub trait InternalChannel<T>: SealedInternalChannel<T> {}
87 91
88foreach_adc!( 92foreach_adc!(
89 ($inst:ident, $common_inst:ident, $clock:ident) => { 93 ($inst:ident, $common_inst:ident, $clock:ident) => {
90 impl crate::adc::sealed::Instance for peripherals::$inst { 94 impl crate::adc::SealedInstance for peripherals::$inst {
91 fn regs() -> crate::pac::adc::Adc { 95 fn regs() -> crate::pac::adc::Adc {
92 crate::pac::$inst 96 crate::pac::$inst
93 } 97 }
@@ -98,21 +102,15 @@ foreach_adc!(
98 } 102 }
99 103
100 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] 104 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
101 fn state() -> &'static sealed::State { 105 fn state() -> &'static State {
102 static STATE: sealed::State = sealed::State::new(); 106 static STATE: State = State::new();
103 &STATE 107 &STATE
104 } 108 }
105 } 109 }
106 110
107 foreach_interrupt!( 111 impl crate::adc::Instance for peripherals::$inst {
108 ($inst,adc,ADC,GLOBAL,$irq:ident) => { 112 type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
109 impl sealed::InterruptableInstance for peripherals::$inst { 113 }
110 type Interrupt = crate::interrupt::typelevel::$irq;
111 }
112 };
113 );
114
115 impl crate::adc::Instance for peripherals::$inst {}
116 }; 114 };
117); 115);
118 116
@@ -120,10 +118,10 @@ macro_rules! impl_adc_pin {
120 ($inst:ident, $pin:ident, $ch:expr) => { 118 ($inst:ident, $pin:ident, $ch:expr) => {
121 impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {} 119 impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {}
122 120
123 impl crate::adc::sealed::AdcPin<peripherals::$inst> for crate::peripherals::$pin { 121 impl crate::adc::SealedAdcPin<peripherals::$inst> for crate::peripherals::$pin {
124 #[cfg(any(adc_v1, adc_l0, adc_v2))] 122 #[cfg(any(adc_v1, adc_l0, adc_v2))]
125 fn set_as_analog(&mut self) { 123 fn set_as_analog(&mut self) {
126 <Self as crate::gpio::sealed::Pin>::set_as_analog(self); 124 <Self as crate::gpio::SealedPin>::set_as_analog(self);
127 } 125 }
128 126
129 fn channel(&self) -> u8 { 127 fn channel(&self) -> u8 {
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index a8dc6ce98..e9b46be80 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -39,7 +39,7 @@ pub struct Vbat;
39impl AdcPin<ADC> for Vbat {} 39impl AdcPin<ADC> for Vbat {}
40 40
41#[cfg(not(adc_l0))] 41#[cfg(not(adc_l0))]
42impl super::sealed::AdcPin<ADC> for Vbat { 42impl super::SealedAdcPin<ADC> for Vbat {
43 fn channel(&self) -> u8 { 43 fn channel(&self) -> u8 {
44 18 44 18
45 } 45 }
@@ -47,7 +47,7 @@ impl super::sealed::AdcPin<ADC> for Vbat {
47 47
48pub struct Vref; 48pub struct Vref;
49impl AdcPin<ADC> for Vref {} 49impl AdcPin<ADC> for Vref {}
50impl super::sealed::AdcPin<ADC> for Vref { 50impl super::SealedAdcPin<ADC> for Vref {
51 fn channel(&self) -> u8 { 51 fn channel(&self) -> u8 {
52 17 52 17
53 } 53 }
@@ -55,7 +55,7 @@ impl super::sealed::AdcPin<ADC> for Vref {
55 55
56pub struct Temperature; 56pub struct Temperature;
57impl AdcPin<ADC> for Temperature {} 57impl AdcPin<ADC> for Temperature {}
58impl super::sealed::AdcPin<ADC> for Temperature { 58impl super::SealedAdcPin<ADC> for Temperature {
59 fn channel(&self) -> u8 { 59 fn channel(&self) -> u8 {
60 16 60 16
61 } 61 }
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index f6f7dbfcc..a43eb72db 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -16,7 +16,7 @@ pub const ADC_POWERUP_TIME_US: u32 = 3;
16 16
17pub struct VrefInt; 17pub struct VrefInt;
18impl AdcPin<ADC1> for VrefInt {} 18impl AdcPin<ADC1> for VrefInt {}
19impl super::sealed::AdcPin<ADC1> for VrefInt { 19impl super::SealedAdcPin<ADC1> for VrefInt {
20 fn channel(&self) -> u8 { 20 fn channel(&self) -> u8 {
21 17 21 17
22 } 22 }
@@ -31,7 +31,7 @@ impl VrefInt {
31 31
32pub struct Temperature; 32pub struct Temperature;
33impl AdcPin<ADC1> for Temperature {} 33impl AdcPin<ADC1> for Temperature {}
34impl super::sealed::AdcPin<ADC1> for Temperature { 34impl super::SealedAdcPin<ADC1> for Temperature {
35 fn channel(&self) -> u8 { 35 fn channel(&self) -> u8 {
36 cfg_if::cfg_if! { 36 cfg_if::cfg_if! {
37 if #[cfg(any(stm32f2, stm32f40, stm32f41))] { 37 if #[cfg(any(stm32f2, stm32f40, stm32f41))] {
@@ -52,7 +52,7 @@ impl Temperature {
52 52
53pub struct Vbat; 53pub struct Vbat;
54impl AdcPin<ADC1> for Vbat {} 54impl AdcPin<ADC1> for Vbat {}
55impl super::sealed::AdcPin<ADC1> for Vbat { 55impl super::SealedAdcPin<ADC1> for Vbat {
56 fn channel(&self) -> u8 { 56 fn channel(&self) -> u8 {
57 18 57 18
58 } 58 }
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 5f3512cad..8c9b47197 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 12
13pub struct VrefInt; 13pub struct VrefInt;
14impl<T: Instance> AdcPin<T> for VrefInt {} 14impl<T: Instance> AdcPin<T> for VrefInt {}
15impl<T: Instance> super::sealed::AdcPin<T> for VrefInt { 15impl<T: Instance> super::SealedAdcPin<T> for VrefInt {
16 fn channel(&self) -> u8 { 16 fn channel(&self) -> u8 {
17 cfg_if! { 17 cfg_if! {
18 if #[cfg(adc_g0)] { 18 if #[cfg(adc_g0)] {
@@ -29,7 +29,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
29 29
30pub struct Temperature; 30pub struct Temperature;
31impl<T: Instance> AdcPin<T> for Temperature {} 31impl<T: Instance> AdcPin<T> for Temperature {}
32impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 32impl<T: Instance> super::SealedAdcPin<T> for Temperature {
33 fn channel(&self) -> u8 { 33 fn channel(&self) -> u8 {
34 cfg_if! { 34 cfg_if! {
35 if #[cfg(adc_g0)] { 35 if #[cfg(adc_g0)] {
@@ -46,7 +46,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
46 46
47pub struct Vbat; 47pub struct Vbat;
48impl<T: Instance> AdcPin<T> for Vbat {} 48impl<T: Instance> AdcPin<T> for Vbat {}
49impl<T: Instance> super::sealed::AdcPin<T> for Vbat { 49impl<T: Instance> super::SealedAdcPin<T> for Vbat {
50 fn channel(&self) -> u8 { 50 fn channel(&self) -> u8 {
51 cfg_if! { 51 cfg_if! {
52 if #[cfg(adc_g0)] { 52 if #[cfg(adc_g0)] {
@@ -65,7 +65,7 @@ cfg_if! {
65 if #[cfg(adc_h5)] { 65 if #[cfg(adc_h5)] {
66 pub struct VddCore; 66 pub struct VddCore;
67 impl<T: Instance> AdcPin<T> for VddCore {} 67 impl<T: Instance> AdcPin<T> for VddCore {}
68 impl<T: Instance> super::sealed::AdcPin<T> for VddCore { 68 impl<T: Instance> super::SealedAdcPin<T> for VddCore {
69 fn channel(&self) -> u8 { 69 fn channel(&self) -> u8 {
70 6 70 6
71 } 71 }
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index 3fd047375..1ae25bea2 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -35,7 +35,7 @@ const VBAT_CHANNEL: u8 = 17;
35/// Internal voltage reference channel. 35/// Internal voltage reference channel.
36pub struct VrefInt; 36pub struct VrefInt;
37impl<T: Instance> InternalChannel<T> for VrefInt {} 37impl<T: Instance> InternalChannel<T> for VrefInt {}
38impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { 38impl<T: Instance> super::SealedInternalChannel<T> for VrefInt {
39 fn channel(&self) -> u8 { 39 fn channel(&self) -> u8 {
40 VREF_CHANNEL 40 VREF_CHANNEL
41 } 41 }
@@ -44,7 +44,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt {
44/// Internal temperature channel. 44/// Internal temperature channel.
45pub struct Temperature; 45pub struct Temperature;
46impl<T: Instance> InternalChannel<T> for Temperature {} 46impl<T: Instance> InternalChannel<T> for Temperature {}
47impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { 47impl<T: Instance> super::SealedInternalChannel<T> for Temperature {
48 fn channel(&self) -> u8 { 48 fn channel(&self) -> u8 {
49 TEMP_CHANNEL 49 TEMP_CHANNEL
50 } 50 }
@@ -53,7 +53,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for Temperature {
53/// Internal battery voltage channel. 53/// Internal battery voltage channel.
54pub struct Vbat; 54pub struct Vbat;
55impl<T: Instance> InternalChannel<T> for Vbat {} 55impl<T: Instance> InternalChannel<T> for Vbat {}
56impl<T: Instance> super::sealed::InternalChannel<T> for Vbat { 56impl<T: Instance> super::SealedInternalChannel<T> for Vbat {
57 fn channel(&self) -> u8 { 57 fn channel(&self) -> u8 {
58 VBAT_CHANNEL 58 VBAT_CHANNEL
59 } 59 }
@@ -276,7 +276,7 @@ impl<'d, T: Instance> Adc<'d, T> {
276 pub fn read<P>(&mut self, pin: &mut P) -> u16 276 pub fn read<P>(&mut self, pin: &mut P) -> u16
277 where 277 where
278 P: AdcPin<T>, 278 P: AdcPin<T>,
279 P: crate::gpio::sealed::Pin, 279 P: crate::gpio::Pin,
280 { 280 {
281 pin.set_as_analog(); 281 pin.set_as_analog();
282 282
diff --git a/embassy-stm32/src/can/bx/mod.rs b/embassy-stm32/src/can/bx/mod.rs
index 33e702c6e..a369ae6fd 100644
--- a/embassy-stm32/src/can/bx/mod.rs
+++ b/embassy-stm32/src/can/bx/mod.rs
@@ -28,7 +28,7 @@ pub mod filter;
28 28
29#[allow(clippy::all)] // generated code 29#[allow(clippy::all)] // generated code
30use core::cmp::{Ord, Ordering}; 30use core::cmp::{Ord, Ordering};
31use core::convert::{Infallible, Into, TryInto}; 31use core::convert::Infallible;
32use core::marker::PhantomData; 32use core::marker::PhantomData;
33use core::mem; 33use core::mem;
34 34
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index bb7cc3d7f..017c5110d 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -1,4 +1,3 @@
1use core::convert::AsMut;
2use core::future::poll_fn; 1use core::future::poll_fn;
3use core::marker::PhantomData; 2use core::marker::PhantomData;
4use core::ops::{Deref, DerefMut}; 3use core::ops::{Deref, DerefMut};
@@ -8,9 +7,12 @@ pub mod bx;
8 7
9pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId}; 8pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId};
10use embassy_hal_internal::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
11use embassy_sync::channel::Channel;
12use embassy_sync::waitqueue::AtomicWaker;
11use futures::FutureExt; 13use futures::FutureExt;
12 14
13use crate::gpio::sealed::AFType; 15use crate::gpio::AFType;
14use crate::interrupt::typelevel::Interrupt; 16use crate::interrupt::typelevel::Interrupt;
15use crate::pac::can::vals::{Ide, Lec}; 17use crate::pac::can::vals::{Ide, Lec};
16use crate::rcc::RccPeripheral; 18use crate::rcc::RccPeripheral;
@@ -486,37 +488,30 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> {
486 } 488 }
487} 489}
488 490
489pub(crate) mod sealed { 491struct State {
490 use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 492 pub tx_waker: AtomicWaker,
491 use embassy_sync::channel::Channel; 493 pub err_waker: AtomicWaker,
492 use embassy_sync::waitqueue::AtomicWaker; 494 pub rx_queue: Channel<CriticalSectionRawMutex, Envelope, 32>,
493 495}
494 use super::Envelope;
495
496 pub struct State {
497 pub tx_waker: AtomicWaker,
498 pub err_waker: AtomicWaker,
499 pub rx_queue: Channel<CriticalSectionRawMutex, Envelope, 32>,
500 }
501 496
502 impl State { 497impl State {
503 pub const fn new() -> Self { 498 pub const fn new() -> Self {
504 Self { 499 Self {
505 tx_waker: AtomicWaker::new(), 500 tx_waker: AtomicWaker::new(),
506 err_waker: AtomicWaker::new(), 501 err_waker: AtomicWaker::new(),
507 rx_queue: Channel::new(), 502 rx_queue: Channel::new(),
508 }
509 } 503 }
510 } 504 }
505}
511 506
512 pub trait Instance { 507trait SealedInstance {
513 fn regs() -> crate::pac::can::Can; 508 fn regs() -> crate::pac::can::Can;
514 fn state() -> &'static State; 509 fn state() -> &'static State;
515 }
516} 510}
517 511
518/// CAN instance trait. 512/// CAN instance trait.
519pub trait Instance: sealed::Instance + RccPeripheral + 'static { 513#[allow(private_bounds)]
514pub trait Instance: SealedInstance + RccPeripheral + 'static {
520 /// TX interrupt for this instance. 515 /// TX interrupt for this instance.
521 type TXInterrupt: crate::interrupt::typelevel::Interrupt; 516 type TXInterrupt: crate::interrupt::typelevel::Interrupt;
522 /// RX0 interrupt for this instance. 517 /// RX0 interrupt for this instance.
@@ -534,14 +529,14 @@ unsafe impl<'d, T: Instance> crate::can::bx::Instance for BxcanInstance<'d, T> {
534 529
535foreach_peripheral!( 530foreach_peripheral!(
536 (can, $inst:ident) => { 531 (can, $inst:ident) => {
537 impl sealed::Instance for peripherals::$inst { 532 impl SealedInstance for peripherals::$inst {
538 533
539 fn regs() -> crate::pac::can::Can { 534 fn regs() -> crate::pac::can::Can {
540 crate::pac::$inst 535 crate::pac::$inst
541 } 536 }
542 537
543 fn state() -> &'static sealed::State { 538 fn state() -> &'static State {
544 static STATE: sealed::State = sealed::State::new(); 539 static STATE: State = State::new();
545 &STATE 540 &STATE
546 } 541 }
547 } 542 }
diff --git a/embassy-stm32/src/can/fd/message_ram/mod.rs b/embassy-stm32/src/can/fd/message_ram/mod.rs
index 830edf3bb..040a999b4 100644
--- a/embassy-stm32/src/can/fd/message_ram/mod.rs
+++ b/embassy-stm32/src/can/fd/message_ram/mod.rs
@@ -140,26 +140,6 @@ pub(crate) struct _TxBufferElement;
140impl generic::Readable for TxBufferElementHeader {} 140impl generic::Readable for TxBufferElementHeader {}
141impl generic::Writable for TxBufferElementHeader {} 141impl generic::Writable for TxBufferElementHeader {}
142 142
143/// FdCan Message RAM instance.
144///
145/// # Safety
146///
147/// It is only safe to implement this trait, when:
148///
149/// * The implementing type has ownership of the Message RAM, preventing any
150/// other accesses to the register block.
151/// * `MSG_RAM` is a pointer to the Message RAM block and can be safely accessed
152/// for as long as ownership or a borrow of the implementing type is present.
153pub unsafe trait Instance {
154 const MSG_RAM: *mut RegisterBlock;
155 fn msg_ram(&self) -> &RegisterBlock {
156 unsafe { &*Self::MSG_RAM }
157 }
158 fn msg_ram_mut(&mut self) -> &mut RegisterBlock {
159 unsafe { &mut *Self::MSG_RAM }
160 }
161}
162
163// Ensure the RegisterBlock is the same size as on pg 1957 of RM0440. 143// Ensure the RegisterBlock is the same size as on pg 1957 of RM0440.
164static_assertions::assert_eq_size!(Filters, [u32; 28 + 16]); 144static_assertions::assert_eq_size!(Filters, [u32; 28 + 16]);
165static_assertions::assert_eq_size!(Receive, [u32; 54]); 145static_assertions::assert_eq_size!(Receive, [u32; 54]);
diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs
index 682e13f4b..76b76afe1 100644
--- a/embassy-stm32/src/can/fd/peripheral.rs
+++ b/embassy-stm32/src/can/fd/peripheral.rs
@@ -325,17 +325,6 @@ impl Registers {
325 */ 325 */
326 } 326 }
327 327
328 /// Disables the CAN interface and returns back the raw peripheral it was created from.
329 #[inline]
330 pub fn free(mut self) {
331 //self.disable_interrupts(Interrupts::all());
332
333 //TODO check this!
334 self.enter_init_mode();
335 self.set_power_down_mode(true);
336 //self.control.instance
337 }
338
339 /// Applies the settings of a new FdCanConfig See [`FdCanConfig`] 328 /// Applies the settings of a new FdCanConfig See [`FdCanConfig`]
340 #[inline] 329 #[inline]
341 pub fn apply_config(&mut self, config: FdCanConfig) { 330 pub fn apply_config(&mut self, config: FdCanConfig) {
@@ -419,55 +408,6 @@ impl Registers {
419 self.leave_init_mode(config); 408 self.leave_init_mode(config);
420 } 409 }
421 410
422 /// Moves out of ConfigMode and into InternalLoopbackMode
423 #[inline]
424 pub fn into_internal_loopback(mut self, config: FdCanConfig) {
425 self.set_loopback_mode(LoopbackMode::Internal);
426 self.leave_init_mode(config);
427 }
428
429 /// Moves out of ConfigMode and into ExternalLoopbackMode
430 #[inline]
431 pub fn into_external_loopback(mut self, config: FdCanConfig) {
432 self.set_loopback_mode(LoopbackMode::External);
433 self.leave_init_mode(config);
434 }
435
436 /// Moves out of ConfigMode and into RestrictedOperationMode
437 #[inline]
438 pub fn into_restricted(mut self, config: FdCanConfig) {
439 self.set_restricted_operations(true);
440 self.leave_init_mode(config);
441 }
442
443 /// Moves out of ConfigMode and into NormalOperationMode
444 #[inline]
445 pub fn into_normal(mut self, config: FdCanConfig) {
446 self.set_normal_operations(true);
447 self.leave_init_mode(config);
448 }
449
450 /// Moves out of ConfigMode and into BusMonitoringMode
451 #[inline]
452 pub fn into_bus_monitoring(mut self, config: FdCanConfig) {
453 self.set_bus_monitoring_mode(true);
454 self.leave_init_mode(config);
455 }
456
457 /// Moves out of ConfigMode and into Testmode
458 #[inline]
459 pub fn into_test_mode(mut self, config: FdCanConfig) {
460 self.set_test_mode(true);
461 self.leave_init_mode(config);
462 }
463
464 /// Moves out of ConfigMode and into PoweredDownmode
465 #[inline]
466 pub fn into_powered_down(mut self, config: FdCanConfig) {
467 self.set_power_down_mode(true);
468 self.leave_init_mode(config);
469 }
470
471 /// Configures the bit timings. 411 /// Configures the bit timings.
472 /// 412 ///
473 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter 413 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
@@ -565,6 +505,7 @@ impl Registers {
565 505
566 /// Configures and resets the timestamp counter 506 /// Configures and resets the timestamp counter
567 #[inline] 507 #[inline]
508 #[allow(unused)]
568 pub fn set_timestamp_counter_source(&mut self, select: TimestampSource) { 509 pub fn set_timestamp_counter_source(&mut self, select: TimestampSource) {
569 #[cfg(stm32h7)] 510 #[cfg(stm32h7)]
570 let (tcp, tss) = match select { 511 let (tcp, tss) = match select {
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index fe8969a5a..4ea036ab4 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -5,10 +5,11 @@ use core::task::Poll;
5 5
6use embassy_hal_internal::{into_ref, PeripheralRef}; 6use embassy_hal_internal::{into_ref, PeripheralRef};
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::channel::Channel; 8use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender};
9use embassy_sync::waitqueue::AtomicWaker;
9 10
10use crate::can::fd::peripheral::Registers; 11use crate::can::fd::peripheral::Registers;
11use crate::gpio::sealed::AFType; 12use crate::gpio::AFType;
12use crate::interrupt::typelevel::Interrupt; 13use crate::interrupt::typelevel::Interrupt;
13use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
14use crate::{interrupt, peripherals, Peripheral}; 15use crate::{interrupt, peripherals, Peripheral};
@@ -53,8 +54,8 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup
53 } 54 }
54 55
55 match &T::state().tx_mode { 56 match &T::state().tx_mode {
56 sealed::TxMode::NonBuffered(waker) => waker.wake(), 57 TxMode::NonBuffered(waker) => waker.wake(),
57 sealed::TxMode::ClassicBuffered(buf) => { 58 TxMode::ClassicBuffered(buf) => {
58 if !T::registers().tx_queue_is_full() { 59 if !T::registers().tx_queue_is_full() {
59 match buf.tx_receiver.try_receive() { 60 match buf.tx_receiver.try_receive() {
60 Ok(frame) => { 61 Ok(frame) => {
@@ -64,7 +65,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup
64 } 65 }
65 } 66 }
66 } 67 }
67 sealed::TxMode::FdBuffered(buf) => { 68 TxMode::FdBuffered(buf) => {
68 if !T::registers().tx_queue_is_full() { 69 if !T::registers().tx_queue_is_full() {
69 match buf.tx_receiver.try_receive() { 70 match buf.tx_receiver.try_receive() {
70 Ok(frame) => { 71 Ok(frame) => {
@@ -467,14 +468,14 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
467 fn setup(self) -> Self { 468 fn setup(self) -> Self {
468 // We don't want interrupts being processed while we change modes. 469 // We don't want interrupts being processed while we change modes.
469 critical_section::with(|_| unsafe { 470 critical_section::with(|_| unsafe {
470 let rx_inner = sealed::ClassicBufferedRxInner { 471 let rx_inner = ClassicBufferedRxInner {
471 rx_sender: self.rx_buf.sender().into(), 472 rx_sender: self.rx_buf.sender().into(),
472 }; 473 };
473 let tx_inner = sealed::ClassicBufferedTxInner { 474 let tx_inner = ClassicBufferedTxInner {
474 tx_receiver: self.tx_buf.receiver().into(), 475 tx_receiver: self.tx_buf.receiver().into(),
475 }; 476 };
476 T::mut_state().rx_mode = sealed::RxMode::ClassicBuffered(rx_inner); 477 T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner);
477 T::mut_state().tx_mode = sealed::TxMode::ClassicBuffered(tx_inner); 478 T::mut_state().tx_mode = TxMode::ClassicBuffered(tx_inner);
478 }); 479 });
479 self 480 self
480 } 481 }
@@ -509,8 +510,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr
509{ 510{
510 fn drop(&mut self) { 511 fn drop(&mut self) {
511 critical_section::with(|_| unsafe { 512 critical_section::with(|_| unsafe {
512 T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); 513 T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
513 T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); 514 T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
514 }); 515 });
515 } 516 }
516} 517}
@@ -585,14 +586,14 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
585 fn setup(self) -> Self { 586 fn setup(self) -> Self {
586 // We don't want interrupts being processed while we change modes. 587 // We don't want interrupts being processed while we change modes.
587 critical_section::with(|_| unsafe { 588 critical_section::with(|_| unsafe {
588 let rx_inner = sealed::FdBufferedRxInner { 589 let rx_inner = FdBufferedRxInner {
589 rx_sender: self.rx_buf.sender().into(), 590 rx_sender: self.rx_buf.sender().into(),
590 }; 591 };
591 let tx_inner = sealed::FdBufferedTxInner { 592 let tx_inner = FdBufferedTxInner {
592 tx_receiver: self.tx_buf.receiver().into(), 593 tx_receiver: self.tx_buf.receiver().into(),
593 }; 594 };
594 T::mut_state().rx_mode = sealed::RxMode::FdBuffered(rx_inner); 595 T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner);
595 T::mut_state().tx_mode = sealed::TxMode::FdBuffered(tx_inner); 596 T::mut_state().tx_mode = TxMode::FdBuffered(tx_inner);
596 }); 597 });
597 self 598 self
598 } 599 }
@@ -627,8 +628,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr
627{ 628{
628 fn drop(&mut self) { 629 fn drop(&mut self) {
629 critical_section::with(|_| unsafe { 630 critical_section::with(|_| unsafe {
630 T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); 631 T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
631 T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); 632 T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
632 }); 633 });
633 } 634 }
634} 635}
@@ -677,192 +678,180 @@ impl<'c, 'd, T: Instance> FdcanRx<'d, T> {
677 } 678 }
678} 679}
679 680
680pub(crate) mod sealed { 681struct ClassicBufferedRxInner {
681 use core::future::poll_fn; 682 rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>,
682 use core::task::Poll; 683}
683 684struct ClassicBufferedTxInner {
684 use embassy_sync::channel::{DynamicReceiver, DynamicSender}; 685 tx_receiver: DynamicReceiver<'static, ClassicFrame>,
685 use embassy_sync::waitqueue::AtomicWaker; 686}
686
687 use super::CanHeader;
688 use crate::can::_version::{BusError, Timestamp};
689 use crate::can::frame::{ClassicFrame, FdFrame};
690
691 pub struct ClassicBufferedRxInner {
692 pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>,
693 }
694 pub struct ClassicBufferedTxInner {
695 pub tx_receiver: DynamicReceiver<'static, ClassicFrame>,
696 }
697 687
698 pub struct FdBufferedRxInner { 688struct FdBufferedRxInner {
699 pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, 689 rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>,
700 } 690}
701 pub struct FdBufferedTxInner { 691struct FdBufferedTxInner {
702 pub tx_receiver: DynamicReceiver<'static, FdFrame>, 692 tx_receiver: DynamicReceiver<'static, FdFrame>,
703 } 693}
704 694
705 pub enum RxMode { 695enum RxMode {
706 NonBuffered(AtomicWaker), 696 NonBuffered(AtomicWaker),
707 ClassicBuffered(ClassicBufferedRxInner), 697 ClassicBuffered(ClassicBufferedRxInner),
708 FdBuffered(FdBufferedRxInner), 698 FdBuffered(FdBufferedRxInner),
709 } 699}
710 700
711 impl RxMode { 701impl RxMode {
712 pub fn register(&self, arg: &core::task::Waker) { 702 fn register(&self, arg: &core::task::Waker) {
713 match self { 703 match self {
714 RxMode::NonBuffered(waker) => waker.register(arg), 704 RxMode::NonBuffered(waker) => waker.register(arg),
715 _ => { 705 _ => {
716 panic!("Bad Mode") 706 panic!("Bad Mode")
717 }
718 } 707 }
719 } 708 }
709 }
720 710
721 pub fn on_interrupt<T: Instance>(&self, fifonr: usize) { 711 fn on_interrupt<T: Instance>(&self, fifonr: usize) {
722 T::regs().ir().write(|w| w.set_rfn(fifonr, true)); 712 T::regs().ir().write(|w| w.set_rfn(fifonr, true));
723 match self { 713 match self {
724 RxMode::NonBuffered(waker) => { 714 RxMode::NonBuffered(waker) => {
725 waker.wake(); 715 waker.wake();
726 } 716 }
727 RxMode::ClassicBuffered(buf) => { 717 RxMode::ClassicBuffered(buf) => {
728 if let Some(result) = self.read::<T, _>() { 718 if let Some(result) = self.read::<T, _>() {
729 let _ = buf.rx_sender.try_send(result); 719 let _ = buf.rx_sender.try_send(result);
730 }
731 }
732 RxMode::FdBuffered(buf) => {
733 if let Some(result) = self.read::<T, _>() {
734 let _ = buf.rx_sender.try_send(result);
735 }
736 } 720 }
737 } 721 }
738 } 722 RxMode::FdBuffered(buf) => {
739 723 if let Some(result) = self.read::<T, _>() {
740 fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> { 724 let _ = buf.rx_sender.try_send(result);
741 if let Some((msg, ts)) = T::registers().read(0) { 725 }
742 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
743 Some(Ok((msg, ts)))
744 } else if let Some((msg, ts)) = T::registers().read(1) {
745 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
746 Some(Ok((msg, ts)))
747 } else if let Some(err) = T::registers().curr_error() {
748 // TODO: this is probably wrong
749 Some(Err(err))
750 } else {
751 None
752 } 726 }
753 } 727 }
728 }
754 729
755 async fn read_async<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> { 730 fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> {
756 poll_fn(|cx| { 731 if let Some((msg, ts)) = T::registers().read(0) {
757 T::state().err_waker.register(cx.waker()); 732 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
758 self.register(cx.waker()); 733 Some(Ok((msg, ts)))
759 match self.read::<T, _>() { 734 } else if let Some((msg, ts)) = T::registers().read(1) {
760 Some(result) => Poll::Ready(result), 735 let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts);
761 None => Poll::Pending, 736 Some(Ok((msg, ts)))
762 } 737 } else if let Some(err) = T::registers().curr_error() {
763 }) 738 // TODO: this is probably wrong
764 .await 739 Some(Err(err))
740 } else {
741 None
765 } 742 }
743 }
766 744
767 pub async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { 745 async fn read_async<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> {
768 self.read_async::<T, _>().await 746 poll_fn(|cx| {
769 } 747 T::state().err_waker.register(cx.waker());
748 self.register(cx.waker());
749 match self.read::<T, _>() {
750 Some(result) => Poll::Ready(result),
751 None => Poll::Pending,
752 }
753 })
754 .await
755 }
770 756
771 pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { 757 async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> {
772 self.read_async::<T, _>().await 758 self.read_async::<T, _>().await
773 }
774 } 759 }
775 760
776 pub enum TxMode { 761 async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> {
777 NonBuffered(AtomicWaker), 762 self.read_async::<T, _>().await
778 ClassicBuffered(ClassicBufferedTxInner),
779 FdBuffered(FdBufferedTxInner),
780 } 763 }
764}
781 765
782 impl TxMode { 766enum TxMode {
783 pub fn register(&self, arg: &core::task::Waker) { 767 NonBuffered(AtomicWaker),
784 match self { 768 ClassicBuffered(ClassicBufferedTxInner),
785 TxMode::NonBuffered(waker) => { 769 FdBuffered(FdBufferedTxInner),
786 waker.register(arg); 770}
787 } 771
788 _ => { 772impl TxMode {
789 panic!("Bad mode"); 773 fn register(&self, arg: &core::task::Waker) {
790 } 774 match self {
775 TxMode::NonBuffered(waker) => {
776 waker.register(arg);
777 }
778 _ => {
779 panic!("Bad mode");
791 } 780 }
792 } 781 }
782 }
793 783
794 /// Queues the message to be sent but exerts backpressure. If a lower-priority 784 /// Queues the message to be sent but exerts backpressure. If a lower-priority
795 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames 785 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
796 /// can be replaced, this call asynchronously waits for a frame to be successfully 786 /// can be replaced, this call asynchronously waits for a frame to be successfully
797 /// transmitted, then tries again. 787 /// transmitted, then tries again.
798 async fn write_generic<T: Instance, F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> Option<F> { 788 async fn write_generic<T: Instance, F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> Option<F> {
799 poll_fn(|cx| { 789 poll_fn(|cx| {
800 self.register(cx.waker()); 790 self.register(cx.waker());
801 791
802 if let Ok(dropped) = T::registers().write(frame) { 792 if let Ok(dropped) = T::registers().write(frame) {
803 return Poll::Ready(dropped); 793 return Poll::Ready(dropped);
804 } 794 }
805 795
806 // Couldn't replace any lower priority frames. Need to wait for some mailboxes 796 // Couldn't replace any lower priority frames. Need to wait for some mailboxes
807 // to clear. 797 // to clear.
808 Poll::Pending 798 Poll::Pending
809 }) 799 })
810 .await 800 .await
811 } 801 }
812 802
813 /// Queues the message to be sent but exerts backpressure. If a lower-priority 803 /// Queues the message to be sent but exerts backpressure. If a lower-priority
814 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames 804 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
815 /// can be replaced, this call asynchronously waits for a frame to be successfully 805 /// can be replaced, this call asynchronously waits for a frame to be successfully
816 /// transmitted, then tries again. 806 /// transmitted, then tries again.
817 pub async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> { 807 async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> {
818 self.write_generic::<T, _>(frame).await 808 self.write_generic::<T, _>(frame).await
819 } 809 }
820 810
821 /// Queues the message to be sent but exerts backpressure. If a lower-priority 811 /// Queues the message to be sent but exerts backpressure. If a lower-priority
822 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames 812 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
823 /// can be replaced, this call asynchronously waits for a frame to be successfully 813 /// can be replaced, this call asynchronously waits for a frame to be successfully
824 /// transmitted, then tries again. 814 /// transmitted, then tries again.
825 pub async fn write_fd<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> { 815 async fn write_fd<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> {
826 self.write_generic::<T, _>(frame).await 816 self.write_generic::<T, _>(frame).await
827 }
828 } 817 }
818}
829 819
830 pub struct State { 820struct State {
831 pub rx_mode: RxMode, 821 pub rx_mode: RxMode,
832 pub tx_mode: TxMode, 822 pub tx_mode: TxMode,
833 pub ns_per_timer_tick: u64, 823 pub ns_per_timer_tick: u64,
834 824
835 pub err_waker: AtomicWaker, 825 pub err_waker: AtomicWaker,
836 } 826}
837 827
838 impl State { 828impl State {
839 pub const fn new() -> Self { 829 const fn new() -> Self {
840 Self { 830 Self {
841 rx_mode: RxMode::NonBuffered(AtomicWaker::new()), 831 rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
842 tx_mode: TxMode::NonBuffered(AtomicWaker::new()), 832 tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
843 ns_per_timer_tick: 0, 833 ns_per_timer_tick: 0,
844 err_waker: AtomicWaker::new(), 834 err_waker: AtomicWaker::new(),
845 }
846 } 835 }
847 } 836 }
837}
848 838
849 pub trait Instance { 839trait SealedInstance {
850 const MSG_RAM_OFFSET: usize; 840 const MSG_RAM_OFFSET: usize;
851 841
852 fn regs() -> &'static crate::pac::can::Fdcan; 842 fn regs() -> &'static crate::pac::can::Fdcan;
853 fn registers() -> crate::can::fd::peripheral::Registers; 843 fn registers() -> crate::can::fd::peripheral::Registers;
854 fn ram() -> &'static crate::pac::fdcanram::Fdcanram; 844 fn state() -> &'static State;
855 fn state() -> &'static State; 845 unsafe fn mut_state() -> &'static mut State;
856 unsafe fn mut_state() -> &'static mut State; 846 fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp;
857 fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp;
858 }
859} 847}
860 848
861/// Instance trait 849/// Instance trait
862pub trait Instance: sealed::Instance + RccPeripheral + 'static { 850#[allow(private_bounds)]
851pub trait Instance: SealedInstance + RccPeripheral + 'static {
863 /// Interrupt 0 852 /// Interrupt 0
864 type IT0Interrupt: crate::interrupt::typelevel::Interrupt; 853 type IT0Interrupt: crate::interrupt::typelevel::Interrupt;
865 /// Interrupt 0 854 /// Interrupt 1
866 type IT1Interrupt: crate::interrupt::typelevel::Interrupt; 855 type IT1Interrupt: crate::interrupt::typelevel::Interrupt;
867} 856}
868 857
@@ -871,7 +860,7 @@ pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>);
871 860
872macro_rules! impl_fdcan { 861macro_rules! impl_fdcan {
873 ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => { 862 ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => {
874 impl sealed::Instance for peripherals::$inst { 863 impl SealedInstance for peripherals::$inst {
875 const MSG_RAM_OFFSET: usize = $msg_ram_offset; 864 const MSG_RAM_OFFSET: usize = $msg_ram_offset;
876 865
877 fn regs() -> &'static crate::pac::can::Fdcan { 866 fn regs() -> &'static crate::pac::can::Fdcan {
@@ -880,14 +869,11 @@ macro_rules! impl_fdcan {
880 fn registers() -> Registers { 869 fn registers() -> Registers {
881 Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} 870 Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET}
882 } 871 }
883 fn ram() -> &'static crate::pac::fdcanram::Fdcanram { 872 unsafe fn mut_state() -> &'static mut State {
884 &crate::pac::$msg_ram_inst 873 static mut STATE: State = State::new();
885 } 874 &mut *core::ptr::addr_of_mut!(STATE)
886 unsafe fn mut_state() -> & 'static mut sealed::State {
887 static mut STATE: sealed::State = sealed::State::new();
888 & mut STATE
889 } 875 }
890 fn state() -> &'static sealed::State { 876 fn state() -> &'static State {
891 unsafe { peripherals::$inst::mut_state() } 877 unsafe { peripherals::$inst::mut_state() }
892 } 878 }
893 879
diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs
index 0166ab819..f8909d438 100644
--- a/embassy-stm32/src/crc/v1.rs
+++ b/embassy-stm32/src/crc/v1.rs
@@ -2,7 +2,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
2 2
3use crate::pac::CRC as PAC_CRC; 3use crate::pac::CRC as PAC_CRC;
4use crate::peripherals::CRC; 4use crate::peripherals::CRC;
5use crate::rcc::sealed::RccPeripheral; 5use crate::rcc::SealedRccPeripheral;
6use crate::Peripheral; 6use crate::Peripheral;
7 7
8/// CRC driver. 8/// CRC driver.
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs
index 0c4ae55ce..46f5ea1be 100644
--- a/embassy-stm32/src/crc/v2v3.rs
+++ b/embassy-stm32/src/crc/v2v3.rs
@@ -3,7 +3,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
3use crate::pac::crc::vals; 3use crate::pac::crc::vals;
4use crate::pac::CRC as PAC_CRC; 4use crate::pac::CRC as PAC_CRC;
5use crate::peripherals::CRC; 5use crate::peripherals::CRC;
6use crate::rcc::sealed::RccPeripheral; 6use crate::rcc::SealedRccPeripheral;
7use crate::Peripheral; 7use crate::Peripheral;
8 8
9/// CRC driver. 9/// CRC driver.
diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs
index 74b095b6f..18b5ec918 100644
--- a/embassy-stm32/src/cryp/mod.rs
+++ b/embassy-stm32/src/cryp/mod.rs
@@ -1885,16 +1885,13 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
1885 } 1885 }
1886} 1886}
1887 1887
1888pub(crate) mod sealed { 1888trait SealedInstance {
1889 use super::*; 1889 fn regs() -> pac::cryp::Cryp;
1890
1891 pub trait Instance {
1892 fn regs() -> pac::cryp::Cryp;
1893 }
1894} 1890}
1895 1891
1896/// CRYP instance trait. 1892/// CRYP instance trait.
1897pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { 1893#[allow(private_bounds)]
1894pub trait Instance: SealedInstance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
1898 /// Interrupt for this CRYP instance. 1895 /// Interrupt for this CRYP instance.
1899 type Interrupt: interrupt::typelevel::Interrupt; 1896 type Interrupt: interrupt::typelevel::Interrupt;
1900} 1897}
@@ -1905,7 +1902,7 @@ foreach_interrupt!(
1905 type Interrupt = crate::interrupt::typelevel::$irq; 1902 type Interrupt = crate::interrupt::typelevel::$irq;
1906 } 1903 }
1907 1904
1908 impl sealed::Instance for peripherals::$inst { 1905 impl SealedInstance for peripherals::$inst {
1909 fn regs() -> crate::pac::cryp::Cryp { 1906 fn regs() -> crate::pac::cryp::Cryp {
1910 crate::pac::$inst 1907 crate::pac::$inst
1911 } 1908 }
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 60f9404c2..acfed8356 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -127,7 +127,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
127 pub fn new( 127 pub fn new(
128 _peri: impl Peripheral<P = T> + 'd, 128 _peri: impl Peripheral<P = T> + 'd,
129 dma: impl Peripheral<P = DMA> + 'd, 129 dma: impl Peripheral<P = DMA> + 'd,
130 pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::sealed::Pin> + 'd, 130 pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::Pin> + 'd,
131 ) -> Self { 131 ) -> Self {
132 into_ref!(dma, pin); 132 into_ref!(dma, pin);
133 pin.set_as_analog(); 133 pin.set_as_analog();
@@ -392,8 +392,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
392 _peri: impl Peripheral<P = T> + 'd, 392 _peri: impl Peripheral<P = T> + 'd,
393 dma_ch1: impl Peripheral<P = DMACh1> + 'd, 393 dma_ch1: impl Peripheral<P = DMACh1> + 'd,
394 dma_ch2: impl Peripheral<P = DMACh2> + 'd, 394 dma_ch2: impl Peripheral<P = DMACh2> + 'd,
395 pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::sealed::Pin> + 'd, 395 pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::Pin> + 'd,
396 pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::sealed::Pin> + 'd, 396 pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::Pin> + 'd,
397 ) -> Self { 397 ) -> Self {
398 into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); 398 into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2);
399 pin_ch1.set_as_analog(); 399 pin_ch1.set_as_analog();
@@ -488,14 +488,13 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
488 } 488 }
489} 489}
490 490
491pub(crate) mod sealed { 491trait SealedInstance {
492 pub trait Instance { 492 fn regs() -> &'static crate::pac::dac::Dac;
493 fn regs() -> &'static crate::pac::dac::Dac;
494 }
495} 493}
496 494
497/// DAC instance. 495/// DAC instance.
498pub trait Instance: sealed::Instance + RccPeripheral + 'static {} 496#[allow(private_bounds)]
497pub trait Instance: SealedInstance + RccPeripheral + 'static {}
499dma_trait!(DacDma1, Instance); 498dma_trait!(DacDma1, Instance);
500dma_trait!(DacDma2, Instance); 499dma_trait!(DacDma2, Instance);
501 500
@@ -504,7 +503,7 @@ pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
504 503
505foreach_peripheral!( 504foreach_peripheral!(
506 (dac, $inst:ident) => { 505 (dac, $inst:ident) => {
507 impl crate::dac::sealed::Instance for peripherals::$inst { 506 impl crate::dac::SealedInstance for peripherals::$inst {
508 fn regs() -> &'static crate::pac::dac::Dac { 507 fn regs() -> &'static crate::pac::dac::Dac {
509 &crate::pac::$inst 508 &crate::pac::$inst
510 } 509 }
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index 826b04a4b..646ee2ce2 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -7,8 +7,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8 8
9use crate::dma::Transfer; 9use crate::dma::Transfer;
10use crate::gpio::sealed::AFType; 10use crate::gpio::{AFType, Speed};
11use crate::gpio::Speed;
12use crate::interrupt::typelevel::Interrupt; 11use crate::interrupt::typelevel::Interrupt;
13use crate::{interrupt, Peripheral}; 12use crate::{interrupt, Peripheral};
14 13
@@ -431,14 +430,13 @@ where
431 } 430 }
432} 431}
433 432
434mod sealed { 433trait SealedInstance: crate::rcc::RccPeripheral {
435 pub trait Instance: crate::rcc::RccPeripheral { 434 fn regs(&self) -> crate::pac::dcmi::Dcmi;
436 fn regs(&self) -> crate::pac::dcmi::Dcmi;
437 }
438} 435}
439 436
440/// DCMI instance. 437/// DCMI instance.
441pub trait Instance: sealed::Instance + 'static { 438#[allow(private_bounds)]
439pub trait Instance: SealedInstance + 'static {
442 /// Interrupt for this instance. 440 /// Interrupt for this instance.
443 type Interrupt: interrupt::typelevel::Interrupt; 441 type Interrupt: interrupt::typelevel::Interrupt;
444} 442}
@@ -465,7 +463,7 @@ pin_trait!(PixClkPin, Instance);
465#[allow(unused)] 463#[allow(unused)]
466macro_rules! impl_peripheral { 464macro_rules! impl_peripheral {
467 ($inst:ident, $irq:ident) => { 465 ($inst:ident, $irq:ident) => {
468 impl sealed::Instance for crate::peripherals::$inst { 466 impl SealedInstance for crate::peripherals::$inst {
469 fn regs(&self) -> crate::pac::dcmi::Dcmi { 467 fn regs(&self) -> crate::pac::dcmi::Dcmi {
470 crate::pac::$inst 468 crate::pac::$inst
471 } 469 }
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs
index 1e9ab5944..dc7cd3a66 100644
--- a/embassy-stm32/src/dma/dmamux.rs
+++ b/embassy-stm32/src/dma/dmamux.rs
@@ -19,9 +19,7 @@ pub(crate) fn configure_dmamux(info: &DmamuxInfo, request: u8) {
19 }); 19 });
20} 20}
21 21
22pub(crate) mod dmamux_sealed { 22pub(crate) trait SealedMuxChannel {}
23 pub trait MuxChannel {}
24}
25 23
26/// DMAMUX1 instance. 24/// DMAMUX1 instance.
27pub struct DMAMUX1; 25pub struct DMAMUX1;
@@ -30,14 +28,15 @@ pub struct DMAMUX1;
30pub struct DMAMUX2; 28pub struct DMAMUX2;
31 29
32/// DMAMUX channel trait. 30/// DMAMUX channel trait.
33pub trait MuxChannel: dmamux_sealed::MuxChannel { 31#[allow(private_bounds)]
32pub trait MuxChannel: SealedMuxChannel {
34 /// DMAMUX instance this channel is on. 33 /// DMAMUX instance this channel is on.
35 type Mux; 34 type Mux;
36} 35}
37 36
38macro_rules! dmamux_channel_impl { 37macro_rules! dmamux_channel_impl {
39 ($channel_peri:ident, $dmamux:ident) => { 38 ($channel_peri:ident, $dmamux:ident) => {
40 impl crate::dma::dmamux_sealed::MuxChannel for crate::peripherals::$channel_peri {} 39 impl crate::dma::SealedMuxChannel for crate::peripherals::$channel_peri {}
41 impl crate::dma::MuxChannel for crate::peripherals::$channel_peri { 40 impl crate::dma::MuxChannel for crate::peripherals::$channel_peri {
42 type Mux = crate::dma::$dmamux; 41 type Mux = crate::dma::$dmamux;
43 } 42 }
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index d5e88a20a..7e3681469 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -39,17 +39,18 @@ pub type Request = u8;
39#[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))] 39#[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))]
40pub type Request = (); 40pub type Request = ();
41 41
42pub(crate) mod sealed { 42pub(crate) trait SealedChannel {
43 pub trait Channel { 43 fn id(&self) -> u8;
44 fn id(&self) -> u8; 44}
45 } 45
46 pub trait ChannelInterrupt { 46pub(crate) trait ChannelInterrupt {
47 unsafe fn on_irq(); 47 #[cfg_attr(not(feature = "rt"), allow(unused))]
48 } 48 unsafe fn on_irq();
49} 49}
50 50
51/// DMA channel. 51/// DMA channel.
52pub trait Channel: sealed::Channel + Peripheral<P = Self> + Into<AnyChannel> + 'static { 52#[allow(private_bounds)]
53pub trait Channel: SealedChannel + Peripheral<P = Self> + Into<AnyChannel> + 'static {
53 /// Type-erase (degrade) this pin into an `AnyChannel`. 54 /// Type-erase (degrade) this pin into an `AnyChannel`.
54 /// 55 ///
55 /// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which 56 /// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which
@@ -63,12 +64,12 @@ pub trait Channel: sealed::Channel + Peripheral<P = Self> + Into<AnyChannel> + '
63 64
64macro_rules! dma_channel_impl { 65macro_rules! dma_channel_impl {
65 ($channel_peri:ident, $index:expr) => { 66 ($channel_peri:ident, $index:expr) => {
66 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { 67 impl crate::dma::SealedChannel for crate::peripherals::$channel_peri {
67 fn id(&self) -> u8 { 68 fn id(&self) -> u8 {
68 $index 69 $index
69 } 70 }
70 } 71 }
71 impl crate::dma::sealed::ChannelInterrupt for crate::peripherals::$channel_peri { 72 impl crate::dma::ChannelInterrupt for crate::peripherals::$channel_peri {
72 unsafe fn on_irq() { 73 unsafe fn on_irq() {
73 crate::dma::AnyChannel { id: $index }.on_irq(); 74 crate::dma::AnyChannel { id: $index }.on_irq();
74 } 75 }
@@ -96,7 +97,7 @@ impl AnyChannel {
96 } 97 }
97} 98}
98 99
99impl sealed::Channel for AnyChannel { 100impl SealedChannel for AnyChannel {
100 fn id(&self) -> u8 { 101 fn id(&self) -> u8 {
101 self.id 102 self.id
102 } 103 }
diff --git a/embassy-stm32/src/dma/word.rs b/embassy-stm32/src/dma/word.rs
index a72c4b7d9..fb1bde860 100644
--- a/embassy-stm32/src/dma/word.rs
+++ b/embassy-stm32/src/dma/word.rs
@@ -20,14 +20,13 @@ impl WordSize {
20 } 20 }
21} 21}
22 22
23mod sealed { 23trait SealedWord {}
24 pub trait Word {}
25}
26 24
27/// DMA word trait. 25/// DMA word trait.
28/// 26///
29/// This is implemented for u8, u16, u32, etc. 27/// This is implemented for u8, u16, u32, etc.
30pub trait Word: sealed::Word + Default + Copy + 'static { 28#[allow(private_bounds)]
29pub trait Word: SealedWord + Default + Copy + 'static {
31 /// Word size 30 /// Word size
32 fn size() -> WordSize; 31 fn size() -> WordSize;
33 /// Amount of bits of this word size. 32 /// Amount of bits of this word size.
@@ -36,7 +35,7 @@ pub trait Word: sealed::Word + Default + Copy + 'static {
36 35
37macro_rules! impl_word { 36macro_rules! impl_word {
38 (_, $T:ident, $bits:literal, $size:ident) => { 37 (_, $T:ident, $bits:literal, $size:ident) => {
39 impl sealed::Word for $T {} 38 impl SealedWord for $T {}
40 impl Word for $T { 39 impl Word for $T {
41 fn bits() -> usize { 40 fn bits() -> usize {
42 $bits 41 $bits
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index 71fe09c3f..bfe8a60d6 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -177,16 +177,15 @@ pub unsafe trait PHY {
177 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool; 177 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool;
178} 178}
179 179
180pub(crate) mod sealed { 180trait SealedInstance {
181 pub trait Instance { 181 fn regs() -> crate::pac::eth::Eth;
182 fn regs() -> crate::pac::eth::Eth;
183 }
184} 182}
185 183
186/// Ethernet instance. 184/// Ethernet instance.
187pub trait Instance: sealed::Instance + RccPeripheral + Send + 'static {} 185#[allow(private_bounds)]
186pub trait Instance: SealedInstance + RccPeripheral + Send + 'static {}
188 187
189impl sealed::Instance for crate::peripherals::ETH { 188impl SealedInstance for crate::peripherals::ETH {
190 fn regs() -> crate::pac::eth::Eth { 189 fn regs() -> crate::pac::eth::Eth {
191 crate::pac::ETH 190 crate::pac::ETH
192 } 191 }
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index e5b7b0452..6f0174def 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -12,15 +12,14 @@ use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress
12pub(crate) use self::rx_desc::{RDes, RDesRing}; 12pub(crate) use self::rx_desc::{RDes, RDesRing};
13pub(crate) use self::tx_desc::{TDes, TDesRing}; 13pub(crate) use self::tx_desc::{TDes, TDesRing};
14use super::*; 14use super::*;
15use crate::gpio::sealed::{AFType, Pin as __GpioPin}; 15use crate::gpio::{AFType, AnyPin, SealedPin};
16use crate::gpio::AnyPin;
17use crate::interrupt::InterruptExt; 16use crate::interrupt::InterruptExt;
18#[cfg(eth_v1a)] 17#[cfg(eth_v1a)]
19use crate::pac::AFIO; 18use crate::pac::AFIO;
20#[cfg(any(eth_v1b, eth_v1c))] 19#[cfg(any(eth_v1b, eth_v1c))]
21use crate::pac::SYSCFG; 20use crate::pac::SYSCFG;
22use crate::pac::{ETH, RCC}; 21use crate::pac::{ETH, RCC};
23use crate::rcc::sealed::RccPeripheral; 22use crate::rcc::SealedRccPeripheral;
24use crate::{interrupt, Peripheral}; 23use crate::{interrupt, Peripheral};
25 24
26/// Interrupt handler. 25/// Interrupt handler.
@@ -149,8 +148,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
149 #[cfg(any(eth_v1b, eth_v1c))] 148 #[cfg(any(eth_v1b, eth_v1c))]
150 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 149 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
151 150
152 let dma = ETH.ethernet_dma(); 151 let dma = T::regs().ethernet_dma();
153 let mac = ETH.ethernet_mac(); 152 let mac = T::regs().ethernet_mac();
154 153
155 // Reset and wait 154 // Reset and wait
156 dma.dmabmr().modify(|w| w.set_sr(true)); 155 dma.dmabmr().modify(|w| w.set_sr(true));
@@ -192,7 +191,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
192 191
193 // TODO MTU size setting not found for v1 ethernet, check if correct 192 // TODO MTU size setting not found for v1 ethernet, check if correct
194 193
195 let hclk = <T as RccPeripheral>::frequency(); 194 let hclk = <T as SealedRccPeripheral>::frequency();
196 let hclk_mhz = hclk.0 / 1_000_000; 195 let hclk_mhz = hclk.0 / 1_000_000;
197 196
198 // Set the MDC clock frequency in the range 1MHz - 2.5MHz 197 // Set the MDC clock frequency in the range 1MHz - 2.5MHz
@@ -235,8 +234,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
235 234
236 fence(Ordering::SeqCst); 235 fence(Ordering::SeqCst);
237 236
238 let mac = ETH.ethernet_mac(); 237 let mac = T::regs().ethernet_mac();
239 let dma = ETH.ethernet_dma(); 238 let dma = T::regs().ethernet_dma();
240 239
241 mac.maccr().modify(|w| { 240 mac.maccr().modify(|w| {
242 w.set_re(true); 241 w.set_re(true);
@@ -275,7 +274,7 @@ pub struct EthernetStationManagement<T: Instance> {
275 274
276unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { 275unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
277 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { 276 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
278 let mac = ETH.ethernet_mac(); 277 let mac = T::regs().ethernet_mac();
279 278
280 mac.macmiiar().modify(|w| { 279 mac.macmiiar().modify(|w| {
281 w.set_pa(phy_addr); 280 w.set_pa(phy_addr);
@@ -289,7 +288,7 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
289 } 288 }
290 289
291 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { 290 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
292 let mac = ETH.ethernet_mac(); 291 let mac = T::regs().ethernet_mac();
293 292
294 mac.macmiidr().write(|w| w.set_md(val)); 293 mac.macmiidr().write(|w| w.set_md(val));
295 mac.macmiiar().modify(|w| { 294 mac.macmiiar().modify(|w| {
@@ -305,8 +304,8 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
305 304
306impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { 305impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> {
307 fn drop(&mut self) { 306 fn drop(&mut self) {
308 let dma = ETH.ethernet_dma(); 307 let dma = T::regs().ethernet_dma();
309 let mac = ETH.ethernet_mac(); 308 let mac = T::regs().ethernet_mac();
310 309
311 // Disable the TX DMA and wait for any previous transmissions to be completed 310 // Disable the TX DMA and wait for any previous transmissions to be completed
312 dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); 311 dma.dmaomr().modify(|w| w.set_st(St::STOPPED));
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 8d69561d4..c6e015022 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -7,11 +7,10 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
7 7
8pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; 8pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing};
9use super::*; 9use super::*;
10use crate::gpio::sealed::{AFType, Pin as _}; 10use crate::gpio::{AFType, AnyPin, SealedPin as _, Speed};
11use crate::gpio::{AnyPin, Speed};
12use crate::interrupt::InterruptExt; 11use crate::interrupt::InterruptExt;
13use crate::pac::ETH; 12use crate::pac::ETH;
14use crate::rcc::sealed::RccPeripheral; 13use crate::rcc::SealedRccPeripheral;
15use crate::{interrupt, Peripheral}; 14use crate::{interrupt, Peripheral};
16 15
17/// Interrupt handler. 16/// Interrupt handler.
@@ -207,9 +206,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
207 phy: P, 206 phy: P,
208 mac_addr: [u8; 6], 207 mac_addr: [u8; 6],
209 ) -> Self { 208 ) -> Self {
210 let dma = ETH.ethernet_dma(); 209 let dma = T::regs().ethernet_dma();
211 let mac = ETH.ethernet_mac(); 210 let mac = T::regs().ethernet_mac();
212 let mtl = ETH.ethernet_mtl(); 211 let mtl = T::regs().ethernet_mtl();
213 212
214 // Reset and wait 213 // Reset and wait
215 dma.dmamr().modify(|w| w.set_swr(true)); 214 dma.dmamr().modify(|w| w.set_swr(true));
@@ -265,7 +264,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
265 w.set_rbsz(RX_BUFFER_SIZE as u16); 264 w.set_rbsz(RX_BUFFER_SIZE as u16);
266 }); 265 });
267 266
268 let hclk = <T as RccPeripheral>::frequency(); 267 let hclk = <T as SealedRccPeripheral>::frequency();
269 let hclk_mhz = hclk.0 / 1_000_000; 268 let hclk_mhz = hclk.0 / 1_000_000;
270 269
271 // Set the MDC clock frequency in the range 1MHz - 2.5MHz 270 // Set the MDC clock frequency in the range 1MHz - 2.5MHz
@@ -296,9 +295,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
296 295
297 fence(Ordering::SeqCst); 296 fence(Ordering::SeqCst);
298 297
299 let mac = ETH.ethernet_mac(); 298 let mac = T::regs().ethernet_mac();
300 let mtl = ETH.ethernet_mtl(); 299 let mtl = T::regs().ethernet_mtl();
301 let dma = ETH.ethernet_dma(); 300 let dma = T::regs().ethernet_dma();
302 301
303 mac.maccr().modify(|w| { 302 mac.maccr().modify(|w| {
304 w.set_re(true); 303 w.set_re(true);
@@ -334,7 +333,7 @@ pub struct EthernetStationManagement<T: Instance> {
334 333
335unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { 334unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
336 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { 335 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
337 let mac = ETH.ethernet_mac(); 336 let mac = T::regs().ethernet_mac();
338 337
339 mac.macmdioar().modify(|w| { 338 mac.macmdioar().modify(|w| {
340 w.set_pa(phy_addr); 339 w.set_pa(phy_addr);
@@ -348,7 +347,7 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
348 } 347 }
349 348
350 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { 349 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
351 let mac = ETH.ethernet_mac(); 350 let mac = T::regs().ethernet_mac();
352 351
353 mac.macmdiodr().write(|w| w.set_md(val)); 352 mac.macmdiodr().write(|w| w.set_md(val));
354 mac.macmdioar().modify(|w| { 353 mac.macmdioar().modify(|w| {
@@ -364,9 +363,9 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
364 363
365impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { 364impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> {
366 fn drop(&mut self) { 365 fn drop(&mut self) {
367 let dma = ETH.ethernet_dma(); 366 let dma = T::regs().ethernet_dma();
368 let mac = ETH.ethernet_mac(); 367 let mac = T::regs().ethernet_mac();
369 let mtl = ETH.ethernet_mtl(); 368 let mtl = T::regs().ethernet_mtl();
370 369
371 // Disable the TX DMA and wait for any previous transmissions to be completed 370 // Disable the TX DMA and wait for any previous transmissions to be completed
372 dma.dmactx_cr().modify(|w| w.set_st(false)); 371 dma.dmactx_cr().modify(|w| w.set_st(false));
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index bd10ba158..8d5dae436 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -330,12 +330,11 @@ macro_rules! impl_irq {
330 330
331foreach_exti_irq!(impl_irq); 331foreach_exti_irq!(impl_irq);
332 332
333pub(crate) mod sealed { 333trait SealedChannel {}
334 pub trait Channel {}
335}
336 334
337/// EXTI channel trait. 335/// EXTI channel trait.
338pub trait Channel: sealed::Channel + Sized { 336#[allow(private_bounds)]
337pub trait Channel: SealedChannel + Sized {
339 /// Get the EXTI channel number. 338 /// Get the EXTI channel number.
340 fn number(&self) -> u8; 339 fn number(&self) -> u8;
341 340
@@ -359,7 +358,7 @@ pub struct AnyChannel {
359} 358}
360 359
361impl_peripheral!(AnyChannel); 360impl_peripheral!(AnyChannel);
362impl sealed::Channel for AnyChannel {} 361impl SealedChannel for AnyChannel {}
363impl Channel for AnyChannel { 362impl Channel for AnyChannel {
364 fn number(&self) -> u8 { 363 fn number(&self) -> u8 {
365 self.number 364 self.number
@@ -368,7 +367,7 @@ impl Channel for AnyChannel {
368 367
369macro_rules! impl_exti { 368macro_rules! impl_exti {
370 ($type:ident, $number:expr) => { 369 ($type:ident, $number:expr) => {
371 impl sealed::Channel for peripherals::$type {} 370 impl SealedChannel for peripherals::$type {}
372 impl Channel for peripherals::$type { 371 impl Channel for peripherals::$type {
373 fn number(&self) -> u8 { 372 fn number(&self) -> u8 {
374 $number 373 $number
diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs
index e0c76e6b2..e2f135208 100644
--- a/embassy-stm32/src/flash/f0.rs
+++ b/embassy-stm32/src/flash/f0.rs
@@ -1,4 +1,3 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile; 1use core::ptr::write_volatile;
3use core::sync::atomic::{fence, Ordering}; 2use core::sync::atomic::{fence, Ordering};
4 3
diff --git a/embassy-stm32/src/flash/f1f3.rs b/embassy-stm32/src/flash/f1f3.rs
index e7790369a..b16354a74 100644
--- a/embassy-stm32/src/flash/f1f3.rs
+++ b/embassy-stm32/src/flash/f1f3.rs
@@ -1,4 +1,3 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile; 1use core::ptr::write_volatile;
3use core::sync::atomic::{fence, Ordering}; 2use core::sync::atomic::{fence, Ordering};
4 3
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index 57447bea5..00e61f2d2 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -1,4 +1,3 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile; 1use core::ptr::write_volatile;
3use core::sync::atomic::{fence, AtomicBool, Ordering}; 2use core::sync::atomic::{fence, AtomicBool, Ordering};
4 3
diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs
index 0f512bbc4..72de0b445 100644
--- a/embassy-stm32/src/flash/f7.rs
+++ b/embassy-stm32/src/flash/f7.rs
@@ -1,4 +1,3 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile; 1use core::ptr::write_volatile;
3use core::sync::atomic::{fence, Ordering}; 2use core::sync::atomic::{fence, Ordering};
4 3
diff --git a/embassy-stm32/src/flash/g.rs b/embassy-stm32/src/flash/g.rs
index b69c4343b..6a5adc941 100644
--- a/embassy-stm32/src/flash/g.rs
+++ b/embassy-stm32/src/flash/g.rs
@@ -1,4 +1,3 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile; 1use core::ptr::write_volatile;
3use core::sync::atomic::{fence, Ordering}; 2use core::sync::atomic::{fence, Ordering};
4 3
diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs
index 743925e17..e32a82eef 100644
--- a/embassy-stm32/src/flash/h7.rs
+++ b/embassy-stm32/src/flash/h7.rs
@@ -1,4 +1,3 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile; 1use core::ptr::write_volatile;
3use core::sync::atomic::{fence, Ordering}; 2use core::sync::atomic::{fence, Ordering};
4 3
diff --git a/embassy-stm32/src/flash/u5.rs b/embassy-stm32/src/flash/u5.rs
index 3787082f9..580c490da 100644
--- a/embassy-stm32/src/flash/u5.rs
+++ b/embassy-stm32/src/flash/u5.rs
@@ -1,4 +1,3 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile; 1use core::ptr::write_volatile;
3use core::sync::atomic::{fence, Ordering}; 2use core::sync::atomic::{fence, Ordering};
4 3
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs
index 9d731a512..aced69878 100644
--- a/embassy-stm32/src/fmc.rs
+++ b/embassy-stm32/src/fmc.rs
@@ -3,8 +3,7 @@ use core::marker::PhantomData;
3 3
4use embassy_hal_internal::into_ref; 4use embassy_hal_internal::into_ref;
5 5
6use crate::gpio::sealed::AFType; 6use crate::gpio::{AFType, Pull, Speed};
7use crate::gpio::{Pull, Speed};
8use crate::Peripheral; 7use crate::Peripheral;
9 8
10/// FMC driver 9/// FMC driver
@@ -44,7 +43,7 @@ where
44 43
45 /// Get the kernel clock currently in use for this FMC instance. 44 /// Get the kernel clock currently in use for this FMC instance.
46 pub fn source_clock_hz(&self) -> u32 { 45 pub fn source_clock_hz(&self) -> u32 {
47 <T as crate::rcc::sealed::RccPeripheral>::frequency().0 46 <T as crate::rcc::SealedRccPeripheral>::frequency().0
48 } 47 }
49} 48}
50 49
@@ -69,7 +68,7 @@ where
69 } 68 }
70 69
71 fn source_clock_hz(&self) -> u32 { 70 fn source_clock_hz(&self) -> u32 {
72 <T as crate::rcc::sealed::RccPeripheral>::frequency().0 71 <T as crate::rcc::SealedRccPeripheral>::frequency().0
73 } 72 }
74} 73}
75 74
@@ -201,18 +200,17 @@ impl<'d, T: Instance> Fmc<'d, T> {
201 )); 200 ));
202} 201}
203 202
204pub(crate) mod sealed { 203trait SealedInstance: crate::rcc::SealedRccPeripheral {
205 pub trait Instance: crate::rcc::sealed::RccPeripheral { 204 const REGS: crate::pac::fmc::Fmc;
206 const REGS: crate::pac::fmc::Fmc;
207 }
208} 205}
209 206
210/// FMC instance trait. 207/// FMC instance trait.
211pub trait Instance: sealed::Instance + 'static {} 208#[allow(private_bounds)]
209pub trait Instance: SealedInstance + 'static {}
212 210
213foreach_peripheral!( 211foreach_peripheral!(
214 (fmc, $inst:ident) => { 212 (fmc, $inst:ident) => {
215 impl crate::fmc::sealed::Instance for crate::peripherals::$inst { 213 impl crate::fmc::SealedInstance for crate::peripherals::$inst {
216 const REGS: crate::pac::fmc::Fmc = crate::pac::$inst; 214 const REGS: crate::pac::fmc::Fmc = crate::pac::$inst;
217 } 215 }
218 impl crate::fmc::Instance for crate::peripherals::$inst {} 216 impl crate::fmc::Instance for crate::peripherals::$inst {}
diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-stm32/src/fmt.rs
+++ b/embassy-stm32/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 00e3e1727..33f22f676 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -6,7 +6,6 @@ use core::convert::Infallible;
6use critical_section::CriticalSection; 6use critical_section::CriticalSection;
7use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; 7use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
8 8
9use self::sealed::Pin as _;
10use crate::pac::gpio::{self, vals}; 9use crate::pac::gpio::{self, vals};
11use crate::{pac, peripherals, Peripheral}; 10use crate::{pac, peripherals, Peripheral};
12 11
@@ -129,6 +128,18 @@ impl<'d> Flex<'d> {
129 }); 128 });
130 } 129 }
131 130
131 /// Put the pin into AF mode, unchecked.
132 ///
133 /// This puts the pin into the AF mode, with the requested number, pull and speed. This is
134 /// completely unchecked, it can attach the pin to literally any peripheral, so use with care.
135 #[inline]
136 pub fn set_as_af_unchecked(&mut self, af_num: u8, af_type: AFType, pull: Pull, speed: Speed) {
137 critical_section::with(|_| {
138 self.pin.set_as_af_pull(af_num, af_type, pull);
139 self.pin.set_speed(speed);
140 });
141 }
142
132 /// Get whether the pin input level is high. 143 /// Get whether the pin input level is high.
133 #[inline] 144 #[inline]
134 pub fn is_high(&self) -> bool { 145 pub fn is_high(&self) -> bool {
@@ -508,172 +519,168 @@ pub enum OutputType {
508 OpenDrain, 519 OpenDrain,
509} 520}
510 521
511impl From<OutputType> for sealed::AFType { 522impl From<OutputType> for AFType {
512 fn from(value: OutputType) -> Self { 523 fn from(value: OutputType) -> Self {
513 match value { 524 match value {
514 OutputType::OpenDrain => sealed::AFType::OutputOpenDrain, 525 OutputType::OpenDrain => AFType::OutputOpenDrain,
515 OutputType::PushPull => sealed::AFType::OutputPushPull, 526 OutputType::PushPull => AFType::OutputPushPull,
516 } 527 }
517 } 528 }
518} 529}
519 530
520#[allow(missing_docs)] 531/// Alternate function type settings
521pub(crate) mod sealed { 532#[derive(Debug, Copy, Clone)]
522 use super::*; 533#[cfg_attr(feature = "defmt", derive(defmt::Format))]
523 534pub enum AFType {
524 /// Alternate function type settings 535 /// Input
525 #[derive(Debug, Copy, Clone)] 536 Input,
526 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 537 /// Output, drive the pin both high or low.
527 pub enum AFType { 538 OutputPushPull,
528 /// Input 539 /// Output, drive the pin low, or don't drive it at all if the output level is high.
529 Input, 540 OutputOpenDrain,
530 /// Output, drive the pin both high or low. 541}
531 OutputPushPull,
532 /// Output, drive the pin low, or don't drive it at all if the output level is high.
533 OutputOpenDrain,
534 }
535
536 pub trait Pin {
537 fn pin_port(&self) -> u8;
538
539 #[inline]
540 fn _pin(&self) -> u8 {
541 self.pin_port() % 16
542 }
543 #[inline]
544 fn _port(&self) -> u8 {
545 self.pin_port() / 16
546 }
547 542
548 #[inline] 543pub(crate) trait SealedPin {
549 fn block(&self) -> gpio::Gpio { 544 fn pin_port(&self) -> u8;
550 pac::GPIO(self._port() as _)
551 }
552 545
553 /// Set the output as high. 546 #[inline]
554 #[inline] 547 fn _pin(&self) -> u8 {
555 fn set_high(&self) { 548 self.pin_port() % 16
556 let n = self._pin() as _; 549 }
557 self.block().bsrr().write(|w| w.set_bs(n, true)); 550 #[inline]
558 } 551 fn _port(&self) -> u8 {
552 self.pin_port() / 16
553 }
559 554
560 /// Set the output as low. 555 #[inline]
561 #[inline] 556 fn block(&self) -> gpio::Gpio {
562 fn set_low(&self) { 557 pac::GPIO(self._port() as _)
563 let n = self._pin() as _; 558 }
564 self.block().bsrr().write(|w| w.set_br(n, true));
565 }
566 559
567 #[inline] 560 /// Set the output as high.
568 fn set_as_af(&self, af_num: u8, af_type: AFType) { 561 #[inline]
569 self.set_as_af_pull(af_num, af_type, Pull::None); 562 fn set_high(&self) {
570 } 563 let n = self._pin() as _;
564 self.block().bsrr().write(|w| w.set_bs(n, true));
565 }
571 566
572 #[cfg(gpio_v1)] 567 /// Set the output as low.
573 #[inline] 568 #[inline]
574 fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { 569 fn set_low(&self) {
575 // F1 uses the AFIO register for remapping. 570 let n = self._pin() as _;
576 // For now, this is not implemented, so af_num is ignored 571 self.block().bsrr().write(|w| w.set_br(n, true));
577 // _af_num should be zero here, since it is not set by stm32-data 572 }
578 let r = self.block();
579 let n = self._pin() as usize;
580 let crlh = if n < 8 { 0 } else { 1 };
581 match af_type {
582 AFType::Input => {
583 let cnf = match pull {
584 Pull::Up => {
585 r.bsrr().write(|w| w.set_bs(n, true));
586 vals::CnfIn::PULL
587 }
588 Pull::Down => {
589 r.bsrr().write(|w| w.set_br(n, true));
590 vals::CnfIn::PULL
591 }
592 Pull::None => vals::CnfIn::FLOATING,
593 };
594
595 r.cr(crlh).modify(|w| {
596 w.set_mode(n % 8, vals::Mode::INPUT);
597 w.set_cnf_in(n % 8, cnf);
598 });
599 }
600 AFType::OutputPushPull => {
601 r.cr(crlh).modify(|w| {
602 w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ);
603 w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL);
604 });
605 }
606 AFType::OutputOpenDrain => {
607 r.cr(crlh).modify(|w| {
608 w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ);
609 w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN);
610 });
611 }
612 }
613 }
614 573
615 #[cfg(gpio_v2)] 574 #[inline]
616 #[inline] 575 fn set_as_af(&self, af_num: u8, af_type: AFType) {
617 fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { 576 self.set_as_af_pull(af_num, af_type, Pull::None);
618 let pin = self._pin() as usize; 577 }
619 let block = self.block();
620 block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num));
621 match af_type {
622 AFType::Input => {}
623 AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)),
624 AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)),
625 }
626 block.pupdr().modify(|w| w.set_pupdr(pin, pull.into()));
627 578
628 block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE)); 579 #[cfg(gpio_v1)]
629 } 580 #[inline]
581 fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) {
582 // F1 uses the AFIO register for remapping.
583 // For now, this is not implemented, so af_num is ignored
584 // _af_num should be zero here, since it is not set by stm32-data
585 let r = self.block();
586 let n = self._pin() as usize;
587 let crlh = if n < 8 { 0 } else { 1 };
588 match af_type {
589 AFType::Input => {
590 let cnf = match pull {
591 Pull::Up => {
592 r.bsrr().write(|w| w.set_bs(n, true));
593 vals::CnfIn::PULL
594 }
595 Pull::Down => {
596 r.bsrr().write(|w| w.set_br(n, true));
597 vals::CnfIn::PULL
598 }
599 Pull::None => vals::CnfIn::FLOATING,
600 };
630 601
631 #[inline] 602 r.cr(crlh).modify(|w| {
632 fn set_as_analog(&self) { 603 w.set_mode(n % 8, vals::Mode::INPUT);
633 let pin = self._pin() as usize; 604 w.set_cnf_in(n % 8, cnf);
634 let block = self.block(); 605 });
635 #[cfg(gpio_v1)] 606 }
636 { 607 AFType::OutputPushPull => {
637 let crlh = if pin < 8 { 0 } else { 1 }; 608 r.cr(crlh).modify(|w| {
638 block.cr(crlh).modify(|w| { 609 w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ);
639 w.set_mode(pin % 8, vals::Mode::INPUT); 610 w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL);
640 w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG); 611 });
612 }
613 AFType::OutputOpenDrain => {
614 r.cr(crlh).modify(|w| {
615 w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ);
616 w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN);
641 }); 617 });
642 } 618 }
643 #[cfg(gpio_v2)]
644 block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG));
645 } 619 }
620 }
646 621
647 /// Set the pin as "disconnected", ie doing nothing and consuming the lowest 622 #[cfg(gpio_v2)]
648 /// amount of power possible. 623 #[inline]
649 /// 624 fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) {
650 /// This is currently the same as set_as_analog but is semantically different really. 625 let pin = self._pin() as usize;
651 /// Drivers should set_as_disconnected pins when dropped. 626 let block = self.block();
652 #[inline] 627 block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num));
653 fn set_as_disconnected(&self) { 628 match af_type {
654 self.set_as_analog(); 629 AFType::Input => {}
630 AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)),
631 AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)),
655 } 632 }
633 block.pupdr().modify(|w| w.set_pupdr(pin, pull.into()));
656 634
657 #[inline] 635 block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE));
658 fn set_speed(&self, speed: Speed) { 636 }
659 let pin = self._pin() as usize;
660 637
661 #[cfg(gpio_v1)] 638 #[inline]
662 { 639 fn set_as_analog(&self) {
663 let crlh = if pin < 8 { 0 } else { 1 }; 640 let pin = self._pin() as usize;
664 self.block().cr(crlh).modify(|w| { 641 let block = self.block();
665 w.set_mode(pin % 8, speed.into()); 642 #[cfg(gpio_v1)]
666 }); 643 {
667 } 644 let crlh = if pin < 8 { 0 } else { 1 };
645 block.cr(crlh).modify(|w| {
646 w.set_mode(pin % 8, vals::Mode::INPUT);
647 w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG);
648 });
649 }
650 #[cfg(gpio_v2)]
651 block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG));
652 }
668 653
669 #[cfg(gpio_v2)] 654 /// Set the pin as "disconnected", ie doing nothing and consuming the lowest
670 self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into())); 655 /// amount of power possible.
656 ///
657 /// This is currently the same as set_as_analog but is semantically different really.
658 /// Drivers should set_as_disconnected pins when dropped.
659 #[inline]
660 fn set_as_disconnected(&self) {
661 self.set_as_analog();
662 }
663
664 #[inline]
665 fn set_speed(&self, speed: Speed) {
666 let pin = self._pin() as usize;
667
668 #[cfg(gpio_v1)]
669 {
670 let crlh = if pin < 8 { 0 } else { 1 };
671 self.block().cr(crlh).modify(|w| {
672 w.set_mode(pin % 8, speed.into());
673 });
671 } 674 }
675
676 #[cfg(gpio_v2)]
677 self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into()));
672 } 678 }
673} 679}
674 680
675/// GPIO pin trait. 681/// GPIO pin trait.
676pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { 682#[allow(private_bounds)]
683pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + SealedPin + Sized + 'static {
677 /// EXTI channel assigned to this pin. 684 /// EXTI channel assigned to this pin.
678 /// 685 ///
679 /// For example, PC4 uses EXTI4. 686 /// For example, PC4 uses EXTI4.
@@ -737,7 +744,7 @@ impl Pin for AnyPin {
737 #[cfg(feature = "exti")] 744 #[cfg(feature = "exti")]
738 type ExtiChannel = crate::exti::AnyChannel; 745 type ExtiChannel = crate::exti::AnyChannel;
739} 746}
740impl sealed::Pin for AnyPin { 747impl SealedPin for AnyPin {
741 #[inline] 748 #[inline]
742 fn pin_port(&self) -> u8 { 749 fn pin_port(&self) -> u8 {
743 self.pin_port 750 self.pin_port
@@ -752,7 +759,7 @@ foreach_pin!(
752 #[cfg(feature = "exti")] 759 #[cfg(feature = "exti")]
753 type ExtiChannel = peripherals::$exti_ch; 760 type ExtiChannel = peripherals::$exti_ch;
754 } 761 }
755 impl sealed::Pin for peripherals::$pin_name { 762 impl SealedPin for peripherals::$pin_name {
756 #[inline] 763 #[inline]
757 fn pin_port(&self) -> u8 { 764 fn pin_port(&self) -> u8 {
758 $port_num * 16 + $pin_num 765 $port_num * 16 + $pin_num
@@ -769,7 +776,7 @@ foreach_pin!(
769 776
770pub(crate) unsafe fn init(_cs: CriticalSection) { 777pub(crate) unsafe fn init(_cs: CriticalSection) {
771 #[cfg(afio)] 778 #[cfg(afio)]
772 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs); 779 <crate::peripherals::AFIO as crate::rcc::SealedRccPeripheral>::enable_and_reset_with_cs(_cs);
773 780
774 crate::_generated::init_gpio(); 781 crate::_generated::init_gpio();
775 782
@@ -833,6 +840,18 @@ impl<'d> embedded_hal_02::digital::v2::ToggleableOutputPin for Output<'d> {
833 } 840 }
834} 841}
835 842
843impl<'d> embedded_hal_02::digital::v2::InputPin for OutputOpenDrain<'d> {
844 type Error = Infallible;
845
846 fn is_high(&self) -> Result<bool, Self::Error> {
847 Ok(self.is_high())
848 }
849
850 fn is_low(&self) -> Result<bool, Self::Error> {
851 Ok(self.is_low())
852 }
853}
854
836impl<'d> embedded_hal_02::digital::v2::OutputPin for OutputOpenDrain<'d> { 855impl<'d> embedded_hal_02::digital::v2::OutputPin for OutputOpenDrain<'d> {
837 type Error = Infallible; 856 type Error = Infallible;
838 857
@@ -1049,9 +1068,3 @@ impl<'d> embedded_hal_1::digital::StatefulOutputPin for Flex<'d> {
1049 Ok((*self).is_set_low()) 1068 Ok((*self).is_set_low())
1050 } 1069 }
1051} 1070}
1052
1053/// Low-level GPIO manipulation.
1054#[cfg(feature = "unstable-pac")]
1055pub mod low_level {
1056 pub use super::sealed::*;
1057}
diff --git a/embassy-stm32/src/hash/mod.rs b/embassy-stm32/src/hash/mod.rs
index b47814f8b..787d5b1c9 100644
--- a/embassy-stm32/src/hash/mod.rs
+++ b/embassy-stm32/src/hash/mod.rs
@@ -17,7 +17,7 @@ use crate::dma::NoDma;
17use crate::dma::Transfer; 17use crate::dma::Transfer;
18use crate::interrupt::typelevel::Interrupt; 18use crate::interrupt::typelevel::Interrupt;
19use crate::peripherals::HASH; 19use crate::peripherals::HASH;
20use crate::rcc::sealed::RccPeripheral; 20use crate::rcc::SealedRccPeripheral;
21use crate::{interrupt, pac, peripherals, Peripheral}; 21use crate::{interrupt, pac, peripherals, Peripheral};
22 22
23#[cfg(hash_v1)] 23#[cfg(hash_v1)]
@@ -561,16 +561,13 @@ impl<'d, T: Instance, D> Hash<'d, T, D> {
561 } 561 }
562} 562}
563 563
564pub(crate) mod sealed { 564trait SealedInstance {
565 use super::*; 565 fn regs() -> pac::hash::Hash;
566
567 pub trait Instance {
568 fn regs() -> pac::hash::Hash;
569 }
570} 566}
571 567
572/// HASH instance trait. 568/// HASH instance trait.
573pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { 569#[allow(private_bounds)]
570pub trait Instance: SealedInstance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
574 /// Interrupt for this HASH instance. 571 /// Interrupt for this HASH instance.
575 type Interrupt: interrupt::typelevel::Interrupt; 572 type Interrupt: interrupt::typelevel::Interrupt;
576} 573}
@@ -581,7 +578,7 @@ foreach_interrupt!(
581 type Interrupt = crate::interrupt::typelevel::$irq; 578 type Interrupt = crate::interrupt::typelevel::$irq;
582 } 579 }
583 580
584 impl sealed::Instance for peripherals::$inst { 581 impl SealedInstance for peripherals::$inst {
585 fn regs() -> crate::pac::hash::Hash { 582 fn regs() -> crate::pac::hash::Hash {
586 crate::pac::$inst 583 crate::pac::$inst
587 } 584 }
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 3ec646fc3..02e45819c 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -7,9 +7,7 @@ use core::marker::PhantomData;
7use embassy_hal_internal::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8pub use traits::Instance; 8pub use traits::Instance;
9 9
10#[allow(unused_imports)] 10use crate::gpio::{AFType, AnyPin};
11use crate::gpio::sealed::{AFType, Pin};
12use crate::gpio::AnyPin;
13use crate::time::Hertz; 11use crate::time::Hertz;
14use crate::Peripheral; 12use crate::Peripheral;
15 13
@@ -54,16 +52,13 @@ pub struct ChF<T: Instance> {
54 phantom: PhantomData<T>, 52 phantom: PhantomData<T>,
55} 53}
56 54
57mod sealed { 55trait SealedAdvancedChannel<T: Instance> {
58 use super::Instance; 56 fn raw() -> usize;
59
60 pub trait AdvancedChannel<T: Instance> {
61 fn raw() -> usize;
62 }
63} 57}
64 58
65/// Advanced channel instance trait. 59/// Advanced channel instance trait.
66pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {} 60#[allow(private_bounds)]
61pub trait AdvancedChannel<T: Instance>: SealedAdvancedChannel<T> {}
67 62
68/// HRTIM PWM pin. 63/// HRTIM PWM pin.
69pub struct PwmPin<'d, T, C> { 64pub struct PwmPin<'d, T, C> {
@@ -113,7 +108,7 @@ macro_rules! advanced_channel_impl {
113 } 108 }
114 } 109 }
115 110
116 impl<T: Instance> sealed::AdvancedChannel<T> for $channel<T> { 111 impl<T: Instance> SealedAdvancedChannel<T> for $channel<T> {
117 fn raw() -> usize { 112 fn raw() -> usize {
118 $ch_num 113 $ch_num
119 } 114 }
diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs
index dcc2b9ef4..75f9971e2 100644
--- a/embassy-stm32/src/hrtim/traits.rs
+++ b/embassy-stm32/src/hrtim/traits.rs
@@ -1,4 +1,4 @@
1use crate::rcc::sealed::RccPeripheral; 1use crate::rcc::RccPeripheral;
2use crate::time::Hertz; 2use crate::time::Hertz;
3 3
4#[repr(u8)] 4#[repr(u8)]
@@ -72,94 +72,92 @@ impl Prescaler {
72 } 72 }
73} 73}
74 74
75pub(crate) mod sealed { 75pub(crate) trait SealedInstance: RccPeripheral {
76 use super::*; 76 fn regs() -> crate::pac::hrtim::Hrtim;
77 77
78 pub trait Instance: RccPeripheral { 78 #[allow(unused)]
79 fn regs() -> crate::pac::hrtim::Hrtim; 79 fn set_master_frequency(frequency: Hertz) {
80 let f = frequency.0;
80 81
81 fn set_master_frequency(frequency: Hertz) { 82 // TODO: wire up HRTIM to the RCC mux infra.
82 let f = frequency.0; 83 //#[cfg(stm32f334)]
84 //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
85 //#[cfg(not(stm32f334))]
86 let timer_f = Self::frequency().0;
83 87
84 // TODO: wire up HRTIM to the RCC mux infra. 88 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
85 //#[cfg(stm32f334)] 89 let psc = if Self::regs().isr().read().dllrdy() {
86 //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; 90 Prescaler::compute_min_high_res(psc_min)
87 //#[cfg(not(stm32f334))] 91 } else {
88 let timer_f = Self::frequency().0; 92 Prescaler::compute_min_low_res(psc_min)
93 };
89 94
90 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); 95 let timer_f = 32 * (timer_f / psc as u32);
91 let psc = if Self::regs().isr().read().dllrdy() { 96 let per: u16 = (timer_f / f) as u16;
92 Prescaler::compute_min_high_res(psc_min)
93 } else {
94 Prescaler::compute_min_low_res(psc_min)
95 };
96 97
97 let timer_f = 32 * (timer_f / psc as u32); 98 let regs = Self::regs();
98 let per: u16 = (timer_f / f) as u16;
99 99
100 let regs = Self::regs(); 100 regs.mcr().modify(|w| w.set_ckpsc(psc.into()));
101 101 regs.mper().modify(|w| w.set_mper(per));
102 regs.mcr().modify(|w| w.set_ckpsc(psc.into())); 102 }
103 regs.mper().modify(|w| w.set_mper(per));
104 }
105 103
106 fn set_channel_frequency(channel: usize, frequency: Hertz) { 104 fn set_channel_frequency(channel: usize, frequency: Hertz) {
107 let f = frequency.0; 105 let f = frequency.0;
108 106
109 // TODO: wire up HRTIM to the RCC mux infra. 107 // TODO: wire up HRTIM to the RCC mux infra.
110 //#[cfg(stm32f334)] 108 //#[cfg(stm32f334)]
111 //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; 109 //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
112 //#[cfg(not(stm32f334))] 110 //#[cfg(not(stm32f334))]
113 let timer_f = Self::frequency().0; 111 let timer_f = Self::frequency().0;
114 112
115 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); 113 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
116 let psc = if Self::regs().isr().read().dllrdy() { 114 let psc = if Self::regs().isr().read().dllrdy() {
117 Prescaler::compute_min_high_res(psc_min) 115 Prescaler::compute_min_high_res(psc_min)
118 } else { 116 } else {
119 Prescaler::compute_min_low_res(psc_min) 117 Prescaler::compute_min_low_res(psc_min)
120 }; 118 };
121 119
122 let timer_f = 32 * (timer_f / psc as u32); 120 let timer_f = 32 * (timer_f / psc as u32);
123 let per: u16 = (timer_f / f) as u16; 121 let per: u16 = (timer_f / f) as u16;
124 122
125 let regs = Self::regs(); 123 let regs = Self::regs();
126 124
127 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); 125 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
128 regs.tim(channel).per().modify(|w| w.set_per(per)); 126 regs.tim(channel).per().modify(|w| w.set_per(per));
129 } 127 }
130 128
131 /// Set the dead time as a proportion of max_duty 129 /// Set the dead time as a proportion of max_duty
132 fn set_channel_dead_time(channel: usize, dead_time: u16) { 130 fn set_channel_dead_time(channel: usize, dead_time: u16) {
133 let regs = Self::regs(); 131 let regs = Self::regs();
134 132
135 let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); 133 let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into();
136 134
137 // The dead-time base clock runs 4 times slower than the hrtim base clock 135 // The dead-time base clock runs 4 times slower than the hrtim base clock
138 // u9::MAX = 511 136 // u9::MAX = 511
139 let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511); 137 let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511);
140 let psc = if Self::regs().isr().read().dllrdy() { 138 let psc = if Self::regs().isr().read().dllrdy() {
141 Prescaler::compute_min_high_res(psc_min) 139 Prescaler::compute_min_high_res(psc_min)
142 } else { 140 } else {
143 Prescaler::compute_min_low_res(psc_min) 141 Prescaler::compute_min_low_res(psc_min)
144 }; 142 };
145 143
146 let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32); 144 let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32);
147 145
148 regs.tim(channel).dt().modify(|w| { 146 regs.tim(channel).dt().modify(|w| {
149 w.set_dtprsc(psc.into()); 147 w.set_dtprsc(psc.into());
150 w.set_dtf(dt_val as u16); 148 w.set_dtf(dt_val as u16);
151 w.set_dtr(dt_val as u16); 149 w.set_dtr(dt_val as u16);
152 }); 150 });
153 }
154 } 151 }
155} 152}
156 153
157/// HRTIM instance trait. 154/// HRTIM instance trait.
158pub trait Instance: sealed::Instance + 'static {} 155#[allow(private_bounds)]
156pub trait Instance: SealedInstance + 'static {}
159 157
160foreach_interrupt! { 158foreach_interrupt! {
161 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { 159 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
162 impl sealed::Instance for crate::peripherals::$inst { 160 impl SealedInstance for crate::peripherals::$inst {
163 fn regs() -> crate::pac::hrtim::Hrtim { 161 fn regs() -> crate::pac::hrtim::Hrtim {
164 crate::pac::$inst 162 crate::pac::$inst
165 } 163 }
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 2416005b5..f1b11cc44 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -14,8 +14,7 @@ use embassy_sync::waitqueue::AtomicWaker;
14use embassy_time::{Duration, Instant}; 14use embassy_time::{Duration, Instant};
15 15
16use crate::dma::NoDma; 16use crate::dma::NoDma;
17use crate::gpio::sealed::AFType; 17use crate::gpio::{AFType, Pull};
18use crate::gpio::Pull;
19use crate::interrupt::typelevel::Interrupt; 18use crate::interrupt::typelevel::Interrupt;
20use crate::time::Hertz; 19use crate::time::Hertz;
21use crate::{interrupt, peripherals}; 20use crate::{interrupt, peripherals};
@@ -175,30 +174,27 @@ impl Timeout {
175 } 174 }
176} 175}
177 176
178pub(crate) mod sealed { 177struct State {
179 use super::*; 178 #[allow(unused)]
180 179 waker: AtomicWaker,
181 pub struct State { 180}
182 #[allow(unused)]
183 pub waker: AtomicWaker,
184 }
185 181
186 impl State { 182impl State {
187 pub const fn new() -> Self { 183 const fn new() -> Self {
188 Self { 184 Self {
189 waker: AtomicWaker::new(), 185 waker: AtomicWaker::new(),
190 }
191 } 186 }
192 } 187 }
188}
193 189
194 pub trait Instance: crate::rcc::RccPeripheral { 190trait SealedInstance: crate::rcc::RccPeripheral {
195 fn regs() -> crate::pac::i2c::I2c; 191 fn regs() -> crate::pac::i2c::I2c;
196 fn state() -> &'static State; 192 fn state() -> &'static State;
197 }
198} 193}
199 194
200/// I2C peripheral instance 195/// I2C peripheral instance
201pub trait Instance: sealed::Instance + 'static { 196#[allow(private_bounds)]
197pub trait Instance: SealedInstance + 'static {
202 /// Event interrupt for this instance 198 /// Event interrupt for this instance
203 type EventInterrupt: interrupt::typelevel::Interrupt; 199 type EventInterrupt: interrupt::typelevel::Interrupt;
204 /// Error interrupt for this instance 200 /// Error interrupt for this instance
@@ -234,13 +230,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInte
234 230
235foreach_peripheral!( 231foreach_peripheral!(
236 (i2c, $inst:ident) => { 232 (i2c, $inst:ident) => {
237 impl sealed::Instance for peripherals::$inst { 233 impl SealedInstance for peripherals::$inst {
238 fn regs() -> crate::pac::i2c::I2c { 234 fn regs() -> crate::pac::i2c::I2c {
239 crate::pac::$inst 235 crate::pac::$inst
240 } 236 }
241 237
242 fn state() -> &'static sealed::State { 238 fn state() -> &'static State {
243 static STATE: sealed::State = sealed::State::new(); 239 static STATE: State = State::new();
244 &STATE 240 &STATE
245 } 241 }
246 } 242 }
@@ -311,10 +307,10 @@ impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T, NoDma, NoDma> {
311 307
312 fn transaction( 308 fn transaction(
313 &mut self, 309 &mut self,
314 _address: u8, 310 address: u8,
315 _operations: &mut [embedded_hal_1::i2c::Operation<'_>], 311 operations: &mut [embedded_hal_1::i2c::Operation<'_>],
316 ) -> Result<(), Self::Error> { 312 ) -> Result<(), Self::Error> {
317 todo!(); 313 self.blocking_transaction(address, operations)
318 } 314 }
319} 315}
320 316
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index cbbc201de..9f29ed5e0 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -10,11 +10,11 @@ use core::task::Poll;
10use embassy_embedded_hal::SetConfig; 10use embassy_embedded_hal::SetConfig;
11use embassy_futures::select::{select, Either}; 11use embassy_futures::select::{select, Either};
12use embassy_hal_internal::drop::OnDrop; 12use embassy_hal_internal::drop::OnDrop;
13use embedded_hal_1::i2c::Operation;
13 14
14use super::*; 15use super::*;
15use crate::dma::Transfer; 16use crate::dma::Transfer;
16use crate::pac::i2c; 17use crate::pac::i2c;
17use crate::time::Hertz;
18 18
19// /!\ /!\ 19// /!\ /!\
20// /!\ Implementation note! /!\ 20// /!\ Implementation note! /!\
@@ -41,6 +41,68 @@ pub unsafe fn on_interrupt<T: Instance>() {
41 }); 41 });
42} 42}
43 43
44/// Frame type in I2C transaction.
45///
46/// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST
47/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an
48/// ACK or NACK after the last byte received.
49///
50/// For write operations, the following options are identical because they differ only in the (N)ACK
51/// treatment relevant for read operations:
52///
53/// - `FirstFrame` and `FirstAndNextFrame`
54/// - `NextFrame` and `LastFrameNoStop`
55///
56/// Abbreviations used below:
57///
58/// - `ST` = start condition
59/// - `SR` = repeated start condition
60/// - `SP` = stop condition
61#[derive(Copy, Clone)]
62enum FrameOptions {
63 /// `[ST/SR]+[NACK]+[SP]` First frame (of this type) in operation and last frame overall in this
64 /// transaction.
65 FirstAndLastFrame,
66 /// `[ST/SR]+[NACK]` First frame of this type in transaction, last frame in a read operation but
67 /// not the last frame overall.
68 FirstFrame,
69 /// `[ST/SR]+[ACK]` First frame of this type in transaction, neither last frame overall nor last
70 /// frame in a read operation.
71 FirstAndNextFrame,
72 /// `[ACK]` Middle frame in a read operation (neither first nor last).
73 NextFrame,
74 /// `[NACK]+[SP]` Last frame overall in this transaction but not the first frame.
75 LastFrame,
76 /// `[NACK]` Last frame in a read operation but not last frame overall in this transaction.
77 LastFrameNoStop,
78}
79
80impl FrameOptions {
81 /// Sends start or repeated start condition before transfer.
82 fn send_start(self) -> bool {
83 match self {
84 Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true,
85 Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false,
86 }
87 }
88
89 /// Sends stop condition after transfer.
90 fn send_stop(self) -> bool {
91 match self {
92 Self::FirstAndLastFrame | Self::LastFrame => true,
93 Self::FirstFrame | Self::FirstAndNextFrame | Self::NextFrame | Self::LastFrameNoStop => false,
94 }
95 }
96
97 /// Sends NACK after last byte received, indicating end of read operation.
98 fn send_nack(self) -> bool {
99 match self {
100 Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true,
101 Self::FirstAndNextFrame | Self::NextFrame => false,
102 }
103 }
104}
105
44impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 106impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
45 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { 107 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
46 T::regs().cr1().modify(|reg| { 108 T::regs().cr1().modify(|reg| {
@@ -124,46 +186,57 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
124 Ok(sr1) 186 Ok(sr1)
125 } 187 }
126 188
127 fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout) -> Result<(), Error> { 189 fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout, frame: FrameOptions) -> Result<(), Error> {
128 // Send a START condition 190 if frame.send_start() {
191 // Send a START condition
129 192
130 T::regs().cr1().modify(|reg| { 193 T::regs().cr1().modify(|reg| {
131 reg.set_start(true); 194 reg.set_start(true);
132 }); 195 });
133 196
134 // Wait until START condition was generated 197 // Wait until START condition was generated
135 while !Self::check_and_clear_error_flags()?.start() { 198 while !Self::check_and_clear_error_flags()?.start() {
136 timeout.check()?; 199 timeout.check()?;
137 } 200 }
138 201
139 // Also wait until signalled we're master and everything is waiting for us 202 // Also wait until signalled we're master and everything is waiting for us
140 while { 203 while {
141 Self::check_and_clear_error_flags()?; 204 Self::check_and_clear_error_flags()?;
142 205
143 let sr2 = T::regs().sr2().read(); 206 let sr2 = T::regs().sr2().read();
144 !sr2.msl() && !sr2.busy() 207 !sr2.msl() && !sr2.busy()
145 } { 208 } {
146 timeout.check()?; 209 timeout.check()?;
147 } 210 }
148 211
149 // Set up current address, we're trying to talk to 212 // Set up current address, we're trying to talk to
150 T::regs().dr().write(|reg| reg.set_dr(addr << 1)); 213 T::regs().dr().write(|reg| reg.set_dr(addr << 1));
151 214
152 // Wait until address was sent 215 // Wait until address was sent
153 // Wait for the address to be acknowledged 216 // Wait for the address to be acknowledged
154 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. 217 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
155 while !Self::check_and_clear_error_flags()?.addr() { 218 while !Self::check_and_clear_error_flags()?.addr() {
156 timeout.check()?; 219 timeout.check()?;
157 } 220 }
158 221
159 // Clear condition by reading SR2 222 // Clear condition by reading SR2
160 let _ = T::regs().sr2().read(); 223 let _ = T::regs().sr2().read();
224 }
161 225
162 // Send bytes 226 // Send bytes
163 for c in bytes { 227 for c in bytes {
164 self.send_byte(*c, timeout)?; 228 self.send_byte(*c, timeout)?;
165 } 229 }
166 230
231 if frame.send_stop() {
232 // Send a STOP condition
233 T::regs().cr1().modify(|reg| reg.set_stop(true));
234 // Wait for STOP condition to transmit.
235 while T::regs().cr1().read().stop() {
236 timeout.check()?;
237 }
238 }
239
167 // Fallthrough is success 240 // Fallthrough is success
168 Ok(()) 241 Ok(())
169 } 242 }
@@ -205,8 +278,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
205 Ok(value) 278 Ok(value)
206 } 279 }
207 280
208 fn blocking_read_timeout(&mut self, addr: u8, buffer: &mut [u8], timeout: Timeout) -> Result<(), Error> { 281 fn blocking_read_timeout(
209 if let Some((last, buffer)) = buffer.split_last_mut() { 282 &mut self,
283 addr: u8,
284 buffer: &mut [u8],
285 timeout: Timeout,
286 frame: FrameOptions,
287 ) -> Result<(), Error> {
288 let Some((last, buffer)) = buffer.split_last_mut() else {
289 return Err(Error::Overrun);
290 };
291
292 if frame.send_start() {
210 // Send a START condition and set ACK bit 293 // Send a START condition and set ACK bit
211 T::regs().cr1().modify(|reg| { 294 T::regs().cr1().modify(|reg| {
212 reg.set_start(true); 295 reg.set_start(true);
@@ -237,49 +320,45 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
237 320
238 // Clear condition by reading SR2 321 // Clear condition by reading SR2
239 let _ = T::regs().sr2().read(); 322 let _ = T::regs().sr2().read();
323 }
240 324
241 // Receive bytes into buffer 325 // Receive bytes into buffer
242 for c in buffer { 326 for c in buffer {
243 *c = self.recv_byte(timeout)?; 327 *c = self.recv_byte(timeout)?;
244 } 328 }
245 329
246 // Prepare to send NACK then STOP after next byte 330 // Prepare to send NACK then STOP after next byte
247 T::regs().cr1().modify(|reg| { 331 T::regs().cr1().modify(|reg| {
332 if frame.send_nack() {
248 reg.set_ack(false); 333 reg.set_ack(false);
334 }
335 if frame.send_stop() {
249 reg.set_stop(true); 336 reg.set_stop(true);
250 }); 337 }
338 });
251 339
252 // Receive last byte 340 // Receive last byte
253 *last = self.recv_byte(timeout)?; 341 *last = self.recv_byte(timeout)?;
254 342
343 if frame.send_stop() {
255 // Wait for the STOP to be sent. 344 // Wait for the STOP to be sent.
256 while T::regs().cr1().read().stop() { 345 while T::regs().cr1().read().stop() {
257 timeout.check()?; 346 timeout.check()?;
258 } 347 }
259
260 // Fallthrough is success
261 Ok(())
262 } else {
263 Err(Error::Overrun)
264 } 348 }
349
350 // Fallthrough is success
351 Ok(())
265 } 352 }
266 353
267 /// Blocking read. 354 /// Blocking read.
268 pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { 355 pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> {
269 self.blocking_read_timeout(addr, read, self.timeout()) 356 self.blocking_read_timeout(addr, read, self.timeout(), FrameOptions::FirstAndLastFrame)
270 } 357 }
271 358
272 /// Blocking write. 359 /// Blocking write.
273 pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { 360 pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> {
274 let timeout = self.timeout(); 361 self.write_bytes(addr, write, self.timeout(), FrameOptions::FirstAndLastFrame)?;
275
276 self.write_bytes(addr, write, timeout)?;
277 // Send a STOP condition
278 T::regs().cr1().modify(|reg| reg.set_stop(true));
279 // Wait for STOP condition to transmit.
280 while T::regs().cr1().read().stop() {
281 timeout.check()?;
282 }
283 362
284 // Fallthrough is success 363 // Fallthrough is success
285 Ok(()) 364 Ok(())
@@ -287,10 +366,85 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
287 366
288 /// Blocking write, restart, read. 367 /// Blocking write, restart, read.
289 pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 368 pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
369 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
370 // stop condition below.
371 if read.is_empty() {
372 return Err(Error::Overrun);
373 }
374
290 let timeout = self.timeout(); 375 let timeout = self.timeout();
291 376
292 self.write_bytes(addr, write, timeout)?; 377 self.write_bytes(addr, write, timeout, FrameOptions::FirstFrame)?;
293 self.blocking_read_timeout(addr, read, timeout)?; 378 self.blocking_read_timeout(addr, read, timeout, FrameOptions::FirstAndLastFrame)?;
379
380 Ok(())
381 }
382
383 /// Blocking transaction with operations.
384 ///
385 /// Consecutive operations of same type are merged. See [transaction contract] for details.
386 ///
387 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
388 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
389 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
390 // stop condition below.
391 if operations.iter().any(|op| match op {
392 Operation::Read(read) => read.is_empty(),
393 Operation::Write(_) => false,
394 }) {
395 return Err(Error::Overrun);
396 }
397
398 let timeout = self.timeout();
399
400 let mut operations = operations.iter_mut();
401
402 let mut prev_op: Option<&mut Operation<'_>> = None;
403 let mut next_op = operations.next();
404
405 while let Some(op) = next_op {
406 next_op = operations.next();
407
408 // Check if this is the first frame of this type. This is the case for the first overall
409 // frame in the transaction and whenever the type of operation changes.
410 let first_frame =
411 match (prev_op.as_ref(), &op) {
412 (None, _) => true,
413 (Some(Operation::Read(_)), Operation::Write(_))
414 | (Some(Operation::Write(_)), Operation::Read(_)) => true,
415 (Some(Operation::Read(_)), Operation::Read(_))
416 | (Some(Operation::Write(_)), Operation::Write(_)) => false,
417 };
418
419 let frame = match (first_frame, next_op.as_ref()) {
420 // If this is the first frame of this type, we generate a (repeated) start condition
421 // but have to consider the next operation: if it is the last, we generate the final
422 // stop condition. Otherwise, we branch on the operation: with read operations, only
423 // the last byte overall (before a write operation or the end of the transaction) is
424 // to be NACK'd, i.e. if another read operation follows, we must ACK this last byte.
425 (true, None) => FrameOptions::FirstAndLastFrame,
426 // Make sure to keep sending ACK for last byte in read operation when it is followed
427 // by another consecutive read operation. If the current operation is write, this is
428 // identical to `FirstFrame`.
429 (true, Some(Operation::Read(_))) => FrameOptions::FirstAndNextFrame,
430 // Otherwise, send NACK for last byte (in read operation). (For write, this does not
431 // matter and could also be `FirstAndNextFrame`.)
432 (true, Some(Operation::Write(_))) => FrameOptions::FirstFrame,
433
434 // If this is not the first frame of its type, we do not generate a (repeated) start
435 // condition. Otherwise, we branch the same way as above.
436 (false, None) => FrameOptions::LastFrame,
437 (false, Some(Operation::Read(_))) => FrameOptions::NextFrame,
438 (false, Some(Operation::Write(_))) => FrameOptions::LastFrameNoStop,
439 };
440
441 match op {
442 Operation::Read(read) => self.blocking_read_timeout(addr, read, timeout, frame)?,
443 Operation::Write(write) => self.write_bytes(addr, write, timeout, frame)?,
444 }
445
446 prev_op = Some(op);
447 }
294 448
295 Ok(()) 449 Ok(())
296 } 450 }
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index bd3abaac1..8baf2849d 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -4,11 +4,11 @@ use core::task::Poll;
4 4
5use embassy_embedded_hal::SetConfig; 5use embassy_embedded_hal::SetConfig;
6use embassy_hal_internal::drop::OnDrop; 6use embassy_hal_internal::drop::OnDrop;
7use embedded_hal_1::i2c::Operation;
7 8
8use super::*; 9use super::*;
9use crate::dma::Transfer; 10use crate::dma::Transfer;
10use crate::pac::i2c; 11use crate::pac::i2c;
11use crate::time::Hertz;
12 12
13pub(crate) unsafe fn on_interrupt<T: Instance>() { 13pub(crate) unsafe fn on_interrupt<T: Instance>() {
14 let regs = T::regs(); 14 let regs = T::regs();
@@ -579,6 +579,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
579 // Automatic Stop 579 // Automatic Stop
580 } 580 }
581 581
582 /// Blocking transaction with operations.
583 ///
584 /// Consecutive operations of same type are merged. See [transaction contract] for details.
585 ///
586 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
587 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
588 let _ = addr;
589 let _ = operations;
590 todo!()
591 }
592
582 /// Blocking write multiple buffers. 593 /// Blocking write multiple buffers.
583 /// 594 ///
584 /// The buffers are concatenated in a single write transaction. 595 /// The buffers are concatenated in a single write transaction.
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index fa9ec0532..c5a606b21 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -1,8 +1,7 @@
1//! Inter-IC Sound (I2S) 1//! Inter-IC Sound (I2S)
2use embassy_hal_internal::into_ref; 2use embassy_hal_internal::into_ref;
3 3
4use crate::gpio::sealed::{AFType, Pin as _}; 4use crate::gpio::{AFType, AnyPin, SealedPin};
5use crate::gpio::AnyPin;
6use crate::pac::spi::vals; 5use crate::pac::spi::vals;
7use crate::spi::{Config as SpiConfig, *}; 6use crate::spi::{Config as SpiConfig, *};
8use crate::time::Hertz; 7use crate::time::Hertz;
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index 523719bb9..4d535cce2 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -4,11 +4,12 @@ use core::future::poll_fn;
4use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll; 5use core::task::Poll;
6 6
7use self::sealed::Instance; 7use embassy_sync::waitqueue::AtomicWaker;
8
8use crate::interrupt; 9use crate::interrupt;
9use crate::interrupt::typelevel::Interrupt; 10use crate::interrupt::typelevel::Interrupt;
10use crate::peripherals::IPCC; 11use crate::peripherals::IPCC;
11use crate::rcc::sealed::RccPeripheral; 12use crate::rcc::SealedRccPeripheral;
12 13
13/// Interrupt handler. 14/// Interrupt handler.
14pub struct ReceiveInterruptHandler {} 15pub struct ReceiveInterruptHandler {}
@@ -207,7 +208,7 @@ impl Ipcc {
207 } 208 }
208} 209}
209 210
210impl sealed::Instance for crate::peripherals::IPCC { 211impl SealedInstance for crate::peripherals::IPCC {
211 fn regs() -> crate::pac::ipcc::Ipcc { 212 fn regs() -> crate::pac::ipcc::Ipcc {
212 crate::pac::IPCC 213 crate::pac::IPCC
213 } 214 }
@@ -216,58 +217,52 @@ impl sealed::Instance for crate::peripherals::IPCC {
216 crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)); 217 crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled));
217 } 218 }
218 219
219 fn state() -> &'static self::sealed::State { 220 fn state() -> &'static State {
220 static STATE: self::sealed::State = self::sealed::State::new(); 221 static STATE: State = State::new();
221 &STATE 222 &STATE
222 } 223 }
223} 224}
224 225
225pub(crate) mod sealed { 226struct State {
226 use embassy_sync::waitqueue::AtomicWaker; 227 rx_wakers: [AtomicWaker; 6],
227 228 tx_wakers: [AtomicWaker; 6],
228 use super::*; 229}
229
230 pub struct State {
231 rx_wakers: [AtomicWaker; 6],
232 tx_wakers: [AtomicWaker; 6],
233 }
234 230
235 impl State { 231impl State {
236 pub const fn new() -> Self { 232 const fn new() -> Self {
237 const WAKER: AtomicWaker = AtomicWaker::new(); 233 const WAKER: AtomicWaker = AtomicWaker::new();
238 234
239 Self { 235 Self {
240 rx_wakers: [WAKER; 6], 236 rx_wakers: [WAKER; 6],
241 tx_wakers: [WAKER; 6], 237 tx_wakers: [WAKER; 6],
242 }
243 } 238 }
239 }
244 240
245 pub const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { 241 const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker {
246 match channel { 242 match channel {
247 IpccChannel::Channel1 => &self.rx_wakers[0], 243 IpccChannel::Channel1 => &self.rx_wakers[0],
248 IpccChannel::Channel2 => &self.rx_wakers[1], 244 IpccChannel::Channel2 => &self.rx_wakers[1],
249 IpccChannel::Channel3 => &self.rx_wakers[2], 245 IpccChannel::Channel3 => &self.rx_wakers[2],
250 IpccChannel::Channel4 => &self.rx_wakers[3], 246 IpccChannel::Channel4 => &self.rx_wakers[3],
251 IpccChannel::Channel5 => &self.rx_wakers[4], 247 IpccChannel::Channel5 => &self.rx_wakers[4],
252 IpccChannel::Channel6 => &self.rx_wakers[5], 248 IpccChannel::Channel6 => &self.rx_wakers[5],
253 }
254 } 249 }
250 }
255 251
256 pub const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { 252 const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker {
257 match channel { 253 match channel {
258 IpccChannel::Channel1 => &self.tx_wakers[0], 254 IpccChannel::Channel1 => &self.tx_wakers[0],
259 IpccChannel::Channel2 => &self.tx_wakers[1], 255 IpccChannel::Channel2 => &self.tx_wakers[1],
260 IpccChannel::Channel3 => &self.tx_wakers[2], 256 IpccChannel::Channel3 => &self.tx_wakers[2],
261 IpccChannel::Channel4 => &self.tx_wakers[3], 257 IpccChannel::Channel4 => &self.tx_wakers[3],
262 IpccChannel::Channel5 => &self.tx_wakers[4], 258 IpccChannel::Channel5 => &self.tx_wakers[4],
263 IpccChannel::Channel6 => &self.tx_wakers[5], 259 IpccChannel::Channel6 => &self.tx_wakers[5],
264 }
265 } 260 }
266 } 261 }
262}
267 263
268 pub trait Instance: crate::rcc::RccPeripheral { 264trait SealedInstance: crate::rcc::RccPeripheral {
269 fn regs() -> crate::pac::ipcc::Ipcc; 265 fn regs() -> crate::pac::ipcc::Ipcc;
270 fn set_cpu2(enabled: bool); 266 fn set_cpu2(enabled: bool);
271 fn state() -> &'static State; 267 fn state() -> &'static State;
272 }
273} 268}
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index b38b5c29d..6a3d1c463 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -79,10 +79,8 @@ pub mod ucpd;
79pub mod uid; 79pub mod uid;
80#[cfg(usart)] 80#[cfg(usart)]
81pub mod usart; 81pub mod usart;
82#[cfg(usb)] 82#[cfg(any(usb, otg))]
83pub mod usb; 83pub mod usb;
84#[cfg(otg)]
85pub mod usb_otg;
86#[cfg(iwdg)] 84#[cfg(iwdg)]
87pub mod wdg; 85pub mod wdg;
88 86
@@ -107,10 +105,10 @@ pub use crate::_generated::interrupt;
107/// Example of how to bind one interrupt: 105/// Example of how to bind one interrupt:
108/// 106///
109/// ```rust,ignore 107/// ```rust,ignore
110/// use embassy_stm32::{bind_interrupts, usb_otg, peripherals}; 108/// use embassy_stm32::{bind_interrupts, usb, peripherals};
111/// 109///
112/// bind_interrupts!(struct Irqs { 110/// bind_interrupts!(struct Irqs {
113/// OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 111/// OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
114/// }); 112/// });
115/// ``` 113/// ```
116/// 114///
@@ -160,7 +158,7 @@ pub(crate) use stm32_metapac as pac;
160use crate::interrupt::Priority; 158use crate::interrupt::Priority;
161#[cfg(feature = "rt")] 159#[cfg(feature = "rt")]
162pub use crate::pac::NVIC_PRIO_BITS; 160pub use crate::pac::NVIC_PRIO_BITS;
163use crate::rcc::sealed::RccPeripheral; 161use crate::rcc::SealedRccPeripheral;
164 162
165/// `embassy-stm32` global configuration. 163/// `embassy-stm32` global configuration.
166#[non_exhaustive] 164#[non_exhaustive]
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs
index cf531e266..a3b4352c0 100644
--- a/embassy-stm32/src/opamp.rs
+++ b/embassy-stm32/src/opamp.rs
@@ -81,8 +81,8 @@ impl<'d, T: Instance> OpAmp<'d, T> {
81 /// [`OpAmpOutput`] is dropped. 81 /// [`OpAmpOutput`] is dropped.
82 pub fn buffer_ext( 82 pub fn buffer_ext(
83 &'d mut self, 83 &'d mut self,
84 in_pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::sealed::Pin>, 84 in_pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::Pin>,
85 out_pin: impl Peripheral<P = impl OutputPin<T> + crate::gpio::sealed::Pin> + 'd, 85 out_pin: impl Peripheral<P = impl OutputPin<T> + crate::gpio::Pin> + 'd,
86 gain: OpAmpGain, 86 gain: OpAmpGain,
87 ) -> OpAmpOutput<'d, T> { 87 ) -> OpAmpOutput<'d, T> {
88 into_ref!(in_pin); 88 into_ref!(in_pin);
@@ -122,7 +122,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
122 #[cfg(opamp_g4)] 122 #[cfg(opamp_g4)]
123 pub fn buffer_int( 123 pub fn buffer_int(
124 &'d mut self, 124 &'d mut self,
125 pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::sealed::Pin>, 125 pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::Pin>,
126 gain: OpAmpGain, 126 gain: OpAmpGain,
127 ) -> OpAmpInternalOutput<'d, T> { 127 ) -> OpAmpInternalOutput<'d, T> {
128 into_ref!(pin); 128 into_ref!(pin);
@@ -166,37 +166,39 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> {
166 } 166 }
167} 167}
168 168
169/// Opamp instance trait. 169pub(crate) trait SealedInstance {
170pub trait Instance: sealed::Instance + 'static {} 170 fn regs() -> crate::pac::opamp::Opamp;
171 171}
172pub(crate) mod sealed {
173 pub trait Instance {
174 fn regs() -> crate::pac::opamp::Opamp;
175 }
176
177 pub trait NonInvertingPin<T: Instance> {
178 fn channel(&self) -> u8;
179 }
180 172
181 pub trait InvertingPin<T: Instance> { 173pub(crate) trait SealedNonInvertingPin<T: Instance> {
182 fn channel(&self) -> u8; 174 fn channel(&self) -> u8;
183 } 175}
184 176
185 pub trait OutputPin<T: Instance> {} 177pub(crate) trait SealedInvertingPin<T: Instance> {
178 #[allow(unused)]
179 fn channel(&self) -> u8;
186} 180}
187 181
182pub(crate) trait SealedOutputPin<T: Instance> {}
183
184/// Opamp instance trait.
185#[allow(private_bounds)]
186pub trait Instance: SealedInstance + 'static {}
188/// Non-inverting pin trait. 187/// Non-inverting pin trait.
189pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {} 188#[allow(private_bounds)]
189pub trait NonInvertingPin<T: Instance>: SealedNonInvertingPin<T> {}
190/// Inverting pin trait. 190/// Inverting pin trait.
191pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {} 191#[allow(private_bounds)]
192pub trait InvertingPin<T: Instance>: SealedInvertingPin<T> {}
192/// Output pin trait. 193/// Output pin trait.
193pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {} 194#[allow(private_bounds)]
195pub trait OutputPin<T: Instance>: SealedOutputPin<T> {}
194 196
195macro_rules! impl_opamp_external_output { 197macro_rules! impl_opamp_external_output {
196 ($inst:ident, $adc:ident, $ch:expr) => { 198 ($inst:ident, $adc:ident, $ch:expr) => {
197 foreach_adc!( 199 foreach_adc!(
198 ($adc, $common_inst:ident, $adc_clock:ident) => { 200 ($adc, $common_inst:ident, $adc_clock:ident) => {
199 impl<'d> crate::adc::sealed::AdcPin<crate::peripherals::$adc> 201 impl<'d> crate::adc::SealedAdcPin<crate::peripherals::$adc>
200 for OpAmpOutput<'d, crate::peripherals::$inst> 202 for OpAmpOutput<'d, crate::peripherals::$inst>
201 { 203 {
202 fn channel(&self) -> u8 { 204 fn channel(&self) -> u8 {
@@ -242,7 +244,7 @@ macro_rules! impl_opamp_internal_output {
242 ($inst:ident, $adc:ident, $ch:expr) => { 244 ($inst:ident, $adc:ident, $ch:expr) => {
243 foreach_adc!( 245 foreach_adc!(
244 ($adc, $common_inst:ident, $adc_clock:ident) => { 246 ($adc, $common_inst:ident, $adc_clock:ident) => {
245 impl<'d> crate::adc::sealed::AdcPin<crate::peripherals::$adc> 247 impl<'d> crate::adc::SealedAdcPin<crate::peripherals::$adc>
246 for OpAmpInternalOutput<'d, crate::peripherals::$inst> 248 for OpAmpInternalOutput<'d, crate::peripherals::$inst>
247 { 249 {
248 fn channel(&self) -> u8 { 250 fn channel(&self) -> u8 {
@@ -291,7 +293,7 @@ foreach_peripheral!(
291 293
292foreach_peripheral! { 294foreach_peripheral! {
293 (opamp, $inst:ident) => { 295 (opamp, $inst:ident) => {
294 impl sealed::Instance for crate::peripherals::$inst { 296 impl SealedInstance for crate::peripherals::$inst {
295 fn regs() -> crate::pac::opamp::Opamp { 297 fn regs() -> crate::pac::opamp::Opamp {
296 crate::pac::$inst 298 crate::pac::$inst
297 } 299 }
@@ -306,7 +308,7 @@ foreach_peripheral! {
306macro_rules! impl_opamp_vp_pin { 308macro_rules! impl_opamp_vp_pin {
307 ($inst:ident, $pin:ident, $ch:expr) => { 309 ($inst:ident, $pin:ident, $ch:expr) => {
308 impl crate::opamp::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {} 310 impl crate::opamp::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {}
309 impl crate::opamp::sealed::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin { 311 impl crate::opamp::SealedNonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {
310 fn channel(&self) -> u8 { 312 fn channel(&self) -> u8 {
311 $ch 313 $ch
312 } 314 }
@@ -318,6 +320,6 @@ macro_rules! impl_opamp_vp_pin {
318macro_rules! impl_opamp_vout_pin { 320macro_rules! impl_opamp_vout_pin {
319 ($inst:ident, $pin:ident) => { 321 ($inst:ident, $pin:ident) => {
320 impl crate::opamp::OutputPin<peripherals::$inst> for crate::peripherals::$pin {} 322 impl crate::opamp::OutputPin<peripherals::$inst> for crate::peripherals::$pin {}
321 impl crate::opamp::sealed::OutputPin<peripherals::$inst> for crate::peripherals::$pin {} 323 impl crate::opamp::SealedOutputPin<peripherals::$inst> for crate::peripherals::$pin {}
322 }; 324 };
323} 325}
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index 8a709a89e..3c054e666 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -8,8 +8,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
8use enums::*; 8use enums::*;
9 9
10use crate::dma::Transfer; 10use crate::dma::Transfer;
11use crate::gpio::sealed::AFType; 11use crate::gpio::{AFType, AnyPin, Pull};
12use crate::gpio::{AnyPin, Pull};
13use crate::pac::quadspi::Quadspi as Regs; 12use crate::pac::quadspi::Quadspi as Regs;
14use crate::rcc::RccPeripheral; 13use crate::rcc::RccPeripheral;
15use crate::{peripherals, Peripheral}; 14use crate::{peripherals, Peripheral};
@@ -381,16 +380,13 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
381 } 380 }
382} 381}
383 382
384pub(crate) mod sealed { 383trait SealedInstance {
385 use super::*; 384 const REGS: Regs;
386
387 pub trait Instance {
388 const REGS: Regs;
389 }
390} 385}
391 386
392/// QSPI instance trait. 387/// QSPI instance trait.
393pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 388#[allow(private_bounds)]
389pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
394 390
395pin_trait!(SckPin, Instance); 391pin_trait!(SckPin, Instance);
396pin_trait!(BK1D0Pin, Instance); 392pin_trait!(BK1D0Pin, Instance);
@@ -409,7 +405,7 @@ dma_trait!(QuadDma, Instance);
409 405
410foreach_peripheral!( 406foreach_peripheral!(
411 (quadspi, $inst:ident) => { 407 (quadspi, $inst:ident) => {
412 impl sealed::Instance for peripherals::$inst { 408 impl SealedInstance for peripherals::$inst {
413 const REGS: Regs = crate::pac::$inst; 409 const REGS: Regs = crate::pac::$inst;
414 } 410 }
415 411
diff --git a/embassy-stm32/src/rcc/hsi48.rs b/embassy-stm32/src/rcc/hsi48.rs
index 19a8c8cb9..6f0d7b379 100644
--- a/embassy-stm32/src/rcc/hsi48.rs
+++ b/embassy-stm32/src/rcc/hsi48.rs
@@ -2,7 +2,7 @@
2 2
3use crate::pac::crs::vals::Syncsrc; 3use crate::pac::crs::vals::Syncsrc;
4use crate::pac::{CRS, RCC}; 4use crate::pac::{CRS, RCC};
5use crate::rcc::sealed::RccPeripheral; 5use crate::rcc::SealedRccPeripheral;
6use crate::time::Hertz; 6use crate::time::Hertz;
7 7
8/// HSI48 speed 8/// HSI48 speed
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs
index 654943bc1..d8604e07e 100644
--- a/embassy-stm32/src/rcc/mco.rs
+++ b/embassy-stm32/src/rcc/mco.rs
@@ -2,8 +2,7 @@ use core::marker::PhantomData;
2 2
3use embassy_hal_internal::into_ref; 3use embassy_hal_internal::into_ref;
4 4
5use crate::gpio::sealed::AFType; 5use crate::gpio::{AFType, Speed};
6use crate::gpio::Speed;
7#[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))] 6#[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))]
8pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; 7pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
9#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))] 8#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))]
@@ -19,23 +18,25 @@ pub enum McoPrescaler {
19 DIV1, 18 DIV1,
20} 19}
21 20
22pub(crate) mod sealed { 21pub(crate) trait SealedMcoInstance {}
23 pub trait McoInstance {
24 type Source;
25 unsafe fn apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler);
26 }
27}
28 22
29pub trait McoInstance: sealed::McoInstance + 'static {} 23#[allow(private_bounds)]
24pub trait McoInstance: SealedMcoInstance + 'static {
25 type Source;
26
27 #[doc(hidden)]
28 unsafe fn _apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler);
29}
30 30
31pin_trait!(McoPin, McoInstance); 31pin_trait!(McoPin, McoInstance);
32 32
33macro_rules! impl_peri { 33macro_rules! impl_peri {
34 ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => { 34 ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => {
35 impl sealed::McoInstance for peripherals::$peri { 35 impl SealedMcoInstance for peripherals::$peri {}
36 impl McoInstance for peripherals::$peri {
36 type Source = $source; 37 type Source = $source;
37 38
38 unsafe fn apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { 39 unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) {
39 #[cfg(not(any(stm32u5, stm32wba)))] 40 #[cfg(not(any(stm32u5, stm32wba)))]
40 let r = RCC.cfgr(); 41 let r = RCC.cfgr();
41 #[cfg(any(stm32u5, stm32wba))] 42 #[cfg(any(stm32u5, stm32wba))]
@@ -48,8 +49,6 @@ macro_rules! impl_peri {
48 }); 49 });
49 } 50 }
50 } 51 }
51
52 impl McoInstance for peripherals::$peri {}
53 }; 52 };
54} 53}
55 54
@@ -79,7 +78,7 @@ impl<'d, T: McoInstance> Mco<'d, T> {
79 into_ref!(pin); 78 into_ref!(pin);
80 79
81 critical_section::with(|_| unsafe { 80 critical_section::with(|_| unsafe {
82 T::apply_clock_settings(source, prescaler); 81 T::_apply_clock_settings(source, prescaler);
83 pin.set_as_af(pin.af_num(), AFType::OutputPushPull); 82 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
84 pin.set_speed(Speed::VeryHigh); 83 pin.set_speed(Speed::VeryHigh);
85 }); 84 });
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 910ebe205..d53d02203 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -10,6 +10,7 @@ pub use bd::*;
10 10
11#[cfg(any(mco, mco1, mco2))] 11#[cfg(any(mco, mco1, mco2))]
12mod mco; 12mod mco;
13use critical_section::CriticalSection;
13#[cfg(any(mco, mco1, mco2))] 14#[cfg(any(mco, mco1, mco2))]
14pub use mco::*; 15pub use mco::*;
15 16
@@ -32,6 +33,7 @@ mod _version;
32pub use _version::*; 33pub use _version::*;
33 34
34pub use crate::_generated::{mux, Clocks}; 35pub use crate::_generated::{mux, Clocks};
36use crate::time::Hertz;
35 37
36#[cfg(feature = "low-power")] 38#[cfg(feature = "low-power")]
37/// Must be written within a critical section 39/// Must be written within a critical section
@@ -63,29 +65,21 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks {
63 CLOCK_FREQS.assume_init_ref() 65 CLOCK_FREQS.assume_init_ref()
64} 66}
65 67
66#[cfg(feature = "unstable-pac")] 68pub(crate) trait SealedRccPeripheral {
67pub mod low_level { 69 fn frequency() -> crate::time::Hertz;
68 pub use super::sealed::*; 70 fn enable_and_reset_with_cs(cs: CriticalSection);
69} 71 fn disable_with_cs(cs: CriticalSection);
70
71pub(crate) mod sealed {
72 use critical_section::CriticalSection;
73
74 pub trait RccPeripheral {
75 fn frequency() -> crate::time::Hertz;
76 fn enable_and_reset_with_cs(cs: CriticalSection);
77 fn disable_with_cs(cs: CriticalSection);
78 72
79 fn enable_and_reset() { 73 fn enable_and_reset() {
80 critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) 74 critical_section::with(|cs| Self::enable_and_reset_with_cs(cs))
81 } 75 }
82 fn disable() { 76 fn disable() {
83 critical_section::with(|cs| Self::disable_with_cs(cs)) 77 critical_section::with(|cs| Self::disable_with_cs(cs))
84 }
85 } 78 }
86} 79}
87 80
88pub trait RccPeripheral: sealed::RccPeripheral + 'static {} 81#[allow(private_bounds)]
82pub trait RccPeripheral: SealedRccPeripheral + 'static {}
89 83
90#[allow(unused)] 84#[allow(unused)]
91mod util { 85mod util {
@@ -116,3 +110,12 @@ mod util {
116 Ok(Some(x)) 110 Ok(Some(x))
117 } 111 }
118} 112}
113
114/// Get the kernel clocok frequency of the peripheral `T`.
115///
116/// # Panics
117///
118/// Panics if the clock is not active.
119pub fn frequency<T: RccPeripheral>() -> Hertz {
120 T::frequency()
121}
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index ca641f352..7a228e4a4 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -222,16 +222,13 @@ impl<'d, T: Instance> RngCore for Rng<'d, T> {
222 222
223impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} 223impl<'d, T: Instance> CryptoRng for Rng<'d, T> {}
224 224
225pub(crate) mod sealed { 225trait SealedInstance {
226 use super::*; 226 fn regs() -> pac::rng::Rng;
227
228 pub trait Instance {
229 fn regs() -> pac::rng::Rng;
230 }
231} 227}
232 228
233/// RNG instance trait. 229/// RNG instance trait.
234pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { 230#[allow(private_bounds)]
231pub trait Instance: SealedInstance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
235 /// Interrupt for this RNG instance. 232 /// Interrupt for this RNG instance.
236 type Interrupt: interrupt::typelevel::Interrupt; 233 type Interrupt: interrupt::typelevel::Interrupt;
237} 234}
@@ -242,7 +239,7 @@ foreach_interrupt!(
242 type Interrupt = crate::interrupt::typelevel::$irq; 239 type Interrupt = crate::interrupt::typelevel::$irq;
243 } 240 }
244 241
245 impl sealed::Instance for peripherals::$inst { 242 impl SealedInstance for peripherals::$inst {
246 fn regs() -> crate::pac::rng::Rng { 243 fn regs() -> crate::pac::rng::Rng {
247 crate::pac::$inst 244 crate::pac::$inst
248 } 245 }
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs
index ef92fa4bb..bab8cf4a3 100644
--- a/embassy-stm32/src/rtc/datetime.rs
+++ b/embassy-stm32/src/rtc/datetime.rs
@@ -1,13 +1,10 @@
1#[cfg(feature = "chrono")] 1#[cfg(feature = "chrono")]
2use core::convert::From; 2use chrono::{Datelike, NaiveDate, Timelike, Weekday};
3
4#[cfg(feature = "chrono")]
5use chrono::{self, Datelike, NaiveDate, Timelike, Weekday};
6 3
7#[cfg(any(feature = "defmt", feature = "time"))] 4#[cfg(any(feature = "defmt", feature = "time"))]
8use crate::peripherals::RTC; 5use crate::peripherals::RTC;
9#[cfg(any(feature = "defmt", feature = "time"))] 6#[cfg(any(feature = "defmt", feature = "time"))]
10use crate::rtc::sealed::Instance; 7use crate::rtc::SealedInstance;
11 8
12/// Represents an instant in time that can be substracted to compute a duration 9/// Represents an instant in time that can be substracted to compute a duration
13pub struct RtcInstant { 10pub struct RtcInstant {
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 169505501..00abe9356 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -31,7 +31,6 @@ pub use _version::*;
31use embassy_hal_internal::Peripheral; 31use embassy_hal_internal::Peripheral;
32 32
33use crate::peripherals::RTC; 33use crate::peripherals::RTC;
34use crate::rtc::sealed::Instance;
35 34
36#[allow(dead_code)] 35#[allow(dead_code)]
37#[repr(u8)] 36#[repr(u8)]
@@ -212,7 +211,7 @@ impl Rtc {
212 /// Create a new RTC instance. 211 /// Create a new RTC instance.
213 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { 212 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
214 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] 213 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
215 <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset(); 214 <RTC as crate::rcc::SealedRccPeripheral>::enable_and_reset();
216 215
217 let mut this = Self { 216 let mut this = Self {
218 #[cfg(feature = "low-power")] 217 #[cfg(feature = "low-power")]
@@ -437,7 +436,7 @@ impl Rtc {
437 .fpr(0) 436 .fpr(0)
438 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); 437 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
439 438
440 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend(); 439 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
441 }); 440 });
442 } 441 }
443 442
@@ -449,8 +448,8 @@ impl Rtc {
449 use crate::interrupt::typelevel::Interrupt; 448 use crate::interrupt::typelevel::Interrupt;
450 use crate::pac::EXTI; 449 use crate::pac::EXTI;
451 450
452 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend(); 451 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
453 unsafe { <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::enable() }; 452 unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() };
454 453
455 EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); 454 EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
456 EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); 455 EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
@@ -477,34 +476,30 @@ pub(crate) fn bcd2_to_byte(bcd: (u8, u8)) -> u8 {
477 tmp + (value & 0x0F) 476 tmp + (value & 0x0F)
478} 477}
479 478
480pub(crate) mod sealed { 479trait SealedInstance {
481 use crate::pac::rtc::Rtc; 480 const BACKUP_REGISTER_COUNT: usize;
482 481
483 pub trait Instance { 482 #[cfg(feature = "low-power")]
484 const BACKUP_REGISTER_COUNT: usize; 483 const EXTI_WAKEUP_LINE: usize;
485
486 #[cfg(feature = "low-power")]
487 const EXTI_WAKEUP_LINE: usize;
488 484
489 #[cfg(feature = "low-power")] 485 #[cfg(feature = "low-power")]
490 type WakeupInterrupt: crate::interrupt::typelevel::Interrupt; 486 type WakeupInterrupt: crate::interrupt::typelevel::Interrupt;
491 487
492 fn regs() -> Rtc { 488 fn regs() -> crate::pac::rtc::Rtc {
493 crate::pac::RTC 489 crate::pac::RTC
494 } 490 }
495 491
496 /// Read content of the backup register. 492 /// Read content of the backup register.
497 /// 493 ///
498 /// The registers retain their values during wakes from standby mode or system resets. They also 494 /// The registers retain their values during wakes from standby mode or system resets. They also
499 /// retain their value when Vdd is switched off as long as V_BAT is powered. 495 /// retain their value when Vdd is switched off as long as V_BAT is powered.
500 fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32>; 496 fn read_backup_register(rtc: &crate::pac::rtc::Rtc, register: usize) -> Option<u32>;
501 497
502 /// Set content of the backup register. 498 /// Set content of the backup register.
503 /// 499 ///
504 /// The registers retain their values during wakes from standby mode or system resets. They also 500 /// The registers retain their values during wakes from standby mode or system resets. They also
505 /// retain their value when Vdd is switched off as long as V_BAT is powered. 501 /// retain their value when Vdd is switched off as long as V_BAT is powered.
506 fn write_backup_register(rtc: &Rtc, register: usize, value: u32); 502 fn write_backup_register(rtc: &crate::pac::rtc::Rtc, register: usize, value: u32);
507 503
508 // fn apply_config(&mut self, rtc_config: RtcConfig); 504 // fn apply_config(&mut self, rtc_config: RtcConfig);
509 }
510} 505}
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index 1eda097a7..92f9de846 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -1,9 +1,8 @@
1use stm32_metapac::rtc::vals::{Osel, Pol}; 1use stm32_metapac::rtc::vals::{Osel, Pol};
2 2
3use super::sealed; 3use super::SealedInstance;
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC; 5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance;
7 6
8#[allow(dead_code)] 7#[allow(dead_code)]
9impl super::Rtc { 8impl super::Rtc {
@@ -126,7 +125,7 @@ impl super::Rtc {
126 } 125 }
127} 126}
128 127
129impl sealed::Instance for crate::peripherals::RTC { 128impl SealedInstance for crate::peripherals::RTC {
130 const BACKUP_REGISTER_COUNT: usize = 20; 129 const BACKUP_REGISTER_COUNT: usize = 20;
131 130
132 #[cfg(all(feature = "low-power", stm32f4))] 131 #[cfg(all(feature = "low-power", stm32f4))]
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs
index 3d44a52ff..8a78d16e1 100644
--- a/embassy-stm32/src/rtc/v3.rs
+++ b/embassy-stm32/src/rtc/v3.rs
@@ -1,9 +1,9 @@
1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType}; 1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType};
2 2
3use super::{sealed, RtcCalibrationCyclePeriod}; 3use super::RtcCalibrationCyclePeriod;
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC; 5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance; 6use crate::rtc::SealedInstance;
7 7
8impl super::Rtc { 8impl super::Rtc {
9 /// Applies the RTC config 9 /// Applies the RTC config
@@ -126,7 +126,7 @@ impl super::Rtc {
126 } 126 }
127} 127}
128 128
129impl sealed::Instance for crate::peripherals::RTC { 129impl SealedInstance for crate::peripherals::RTC {
130 const BACKUP_REGISTER_COUNT: usize = 32; 130 const BACKUP_REGISTER_COUNT: usize = 32;
131 131
132 #[cfg(all(feature = "low-power", stm32g4))] 132 #[cfg(all(feature = "low-power", stm32g4))]
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
index 02f96f8a9..54dd81524 100644
--- a/embassy-stm32/src/sai/mod.rs
+++ b/embassy-stm32/src/sai/mod.rs
@@ -6,12 +6,10 @@ use core::marker::PhantomData;
6 6
7use embassy_hal_internal::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8 8
9use self::sealed::WhichSubBlock;
10pub use crate::dma::word; 9pub use crate::dma::word;
11#[cfg(not(gpdma))] 10#[cfg(not(gpdma))]
12use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; 11use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
13use crate::gpio::sealed::{AFType, Pin as _}; 12use crate::gpio::{AFType, AnyPin, SealedPin as _};
14use crate::gpio::AnyPin;
15use crate::pac::sai::{vals, Sai as Regs}; 13use crate::pac::sai::{vals, Sai as Regs};
16use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
17use crate::{peripherals, Peripheral}; 15use crate::{peripherals, Peripheral};
@@ -386,6 +384,7 @@ impl OutputDrive {
386/// Master clock divider. 384/// Master clock divider.
387#[derive(Copy, Clone, PartialEq)] 385#[derive(Copy, Clone, PartialEq)]
388#[allow(missing_docs)] 386#[allow(missing_docs)]
387#[cfg(any(sai_v1, sai_v2))]
389pub enum MasterClockDivider { 388pub enum MasterClockDivider {
390 MasterClockDisabled, 389 MasterClockDisabled,
391 Div1, 390 Div1,
@@ -406,8 +405,79 @@ pub enum MasterClockDivider {
406 Div30, 405 Div30,
407} 406}
408 407
408/// Master clock divider.
409#[derive(Copy, Clone, PartialEq)]
410#[allow(missing_docs)]
411#[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
412pub enum MasterClockDivider {
413 MasterClockDisabled,
414 Div1,
415 Div2,
416 Div3,
417 Div4,
418 Div5,
419 Div6,
420 Div7,
421 Div8,
422 Div9,
423 Div10,
424 Div11,
425 Div12,
426 Div13,
427 Div14,
428 Div15,
429 Div16,
430 Div17,
431 Div18,
432 Div19,
433 Div20,
434 Div21,
435 Div22,
436 Div23,
437 Div24,
438 Div25,
439 Div26,
440 Div27,
441 Div28,
442 Div29,
443 Div30,
444 Div31,
445 Div32,
446 Div33,
447 Div34,
448 Div35,
449 Div36,
450 Div37,
451 Div38,
452 Div39,
453 Div40,
454 Div41,
455 Div42,
456 Div43,
457 Div44,
458 Div45,
459 Div46,
460 Div47,
461 Div48,
462 Div49,
463 Div50,
464 Div51,
465 Div52,
466 Div53,
467 Div54,
468 Div55,
469 Div56,
470 Div57,
471 Div58,
472 Div59,
473 Div60,
474 Div61,
475 Div62,
476 Div63,
477}
478
409impl MasterClockDivider { 479impl MasterClockDivider {
410 #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] 480 #[cfg(any(sai_v1, sai_v2))]
411 const fn mckdiv(&self) -> u8 { 481 const fn mckdiv(&self) -> u8 {
412 match self { 482 match self {
413 MasterClockDivider::MasterClockDisabled => 0, 483 MasterClockDivider::MasterClockDisabled => 0,
@@ -429,6 +499,76 @@ impl MasterClockDivider {
429 MasterClockDivider::Div30 => 15, 499 MasterClockDivider::Div30 => 15,
430 } 500 }
431 } 501 }
502
503 #[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
504 const fn mckdiv(&self) -> u8 {
505 match self {
506 MasterClockDivider::MasterClockDisabled => 0,
507 MasterClockDivider::Div1 => 1,
508 MasterClockDivider::Div2 => 2,
509 MasterClockDivider::Div3 => 3,
510 MasterClockDivider::Div4 => 4,
511 MasterClockDivider::Div5 => 5,
512 MasterClockDivider::Div6 => 6,
513 MasterClockDivider::Div7 => 7,
514 MasterClockDivider::Div8 => 8,
515 MasterClockDivider::Div9 => 9,
516 MasterClockDivider::Div10 => 10,
517 MasterClockDivider::Div11 => 11,
518 MasterClockDivider::Div12 => 12,
519 MasterClockDivider::Div13 => 13,
520 MasterClockDivider::Div14 => 14,
521 MasterClockDivider::Div15 => 15,
522 MasterClockDivider::Div16 => 16,
523 MasterClockDivider::Div17 => 17,
524 MasterClockDivider::Div18 => 18,
525 MasterClockDivider::Div19 => 19,
526 MasterClockDivider::Div20 => 20,
527 MasterClockDivider::Div21 => 21,
528 MasterClockDivider::Div22 => 22,
529 MasterClockDivider::Div23 => 23,
530 MasterClockDivider::Div24 => 24,
531 MasterClockDivider::Div25 => 25,
532 MasterClockDivider::Div26 => 26,
533 MasterClockDivider::Div27 => 27,
534 MasterClockDivider::Div28 => 28,
535 MasterClockDivider::Div29 => 29,
536 MasterClockDivider::Div30 => 30,
537 MasterClockDivider::Div31 => 31,
538 MasterClockDivider::Div32 => 32,
539 MasterClockDivider::Div33 => 33,
540 MasterClockDivider::Div34 => 34,
541 MasterClockDivider::Div35 => 35,
542 MasterClockDivider::Div36 => 36,
543 MasterClockDivider::Div37 => 37,
544 MasterClockDivider::Div38 => 38,
545 MasterClockDivider::Div39 => 39,
546 MasterClockDivider::Div40 => 40,
547 MasterClockDivider::Div41 => 41,
548 MasterClockDivider::Div42 => 42,
549 MasterClockDivider::Div43 => 43,
550 MasterClockDivider::Div44 => 44,
551 MasterClockDivider::Div45 => 45,
552 MasterClockDivider::Div46 => 46,
553 MasterClockDivider::Div47 => 47,
554 MasterClockDivider::Div48 => 48,
555 MasterClockDivider::Div49 => 49,
556 MasterClockDivider::Div50 => 50,
557 MasterClockDivider::Div51 => 51,
558 MasterClockDivider::Div52 => 52,
559 MasterClockDivider::Div53 => 53,
560 MasterClockDivider::Div54 => 54,
561 MasterClockDivider::Div55 => 55,
562 MasterClockDivider::Div56 => 56,
563 MasterClockDivider::Div57 => 57,
564 MasterClockDivider::Div58 => 58,
565 MasterClockDivider::Div59 => 59,
566 MasterClockDivider::Div60 => 60,
567 MasterClockDivider::Div61 => 61,
568 MasterClockDivider::Div62 => 62,
569 MasterClockDivider::Div63 => 63,
570 }
571 }
432} 572}
433 573
434/// [`SAI`] configuration. 574/// [`SAI`] configuration.
@@ -899,43 +1039,42 @@ impl<'d, T: Instance, W: word::Word> Drop for Sai<'d, T, W> {
899 } 1039 }
900} 1040}
901 1041
902pub(crate) mod sealed { 1042trait SealedInstance {
903 use super::*; 1043 const REGS: Regs;
904 1044}
905 pub trait Instance {
906 const REGS: Regs;
907 }
908 1045
909 #[derive(Copy, Clone)] 1046#[derive(Copy, Clone)]
910 pub enum WhichSubBlock { 1047enum WhichSubBlock {
911 A = 0, 1048 A = 0,
912 B = 1, 1049 B = 1,
913 } 1050}
914 1051
915 pub trait SubBlock { 1052trait SealedSubBlock {
916 const WHICH: WhichSubBlock; 1053 const WHICH: WhichSubBlock;
917 }
918} 1054}
919 1055
920/// Sub-block instance trait. 1056/// Sub-block instance trait.
921pub trait SubBlockInstance: sealed::SubBlock {} 1057#[allow(private_bounds)]
1058pub trait SubBlockInstance: SealedSubBlock {}
922 1059
923/// Sub-block A. 1060/// Sub-block A.
924pub enum A {} 1061pub enum A {}
925impl sealed::SubBlock for A { 1062impl SealedSubBlock for A {
926 const WHICH: WhichSubBlock = WhichSubBlock::A; 1063 const WHICH: WhichSubBlock = WhichSubBlock::A;
927} 1064}
928impl SubBlockInstance for A {} 1065impl SubBlockInstance for A {}
929 1066
930/// Sub-block B. 1067/// Sub-block B.
931pub enum B {} 1068pub enum B {}
932impl sealed::SubBlock for B { 1069impl SealedSubBlock for B {
933 const WHICH: WhichSubBlock = WhichSubBlock::B; 1070 const WHICH: WhichSubBlock = WhichSubBlock::B;
934} 1071}
935impl SubBlockInstance for B {} 1072impl SubBlockInstance for B {}
936 1073
937/// SAI instance trait. 1074/// SAI instance trait.
938pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 1075#[allow(private_bounds)]
1076pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
1077
939pin_trait!(SckPin, Instance, SubBlockInstance); 1078pin_trait!(SckPin, Instance, SubBlockInstance);
940pin_trait!(FsPin, Instance, SubBlockInstance); 1079pin_trait!(FsPin, Instance, SubBlockInstance);
941pin_trait!(SdPin, Instance, SubBlockInstance); 1080pin_trait!(SdPin, Instance, SubBlockInstance);
@@ -945,7 +1084,7 @@ dma_trait!(Dma, Instance, SubBlockInstance);
945 1084
946foreach_peripheral!( 1085foreach_peripheral!(
947 (sai, $inst:ident) => { 1086 (sai, $inst:ident) => {
948 impl sealed::Instance for peripherals::$inst { 1087 impl SealedInstance for peripherals::$inst {
949 const REGS: Regs = crate::pac::$inst; 1088 const REGS: Regs = crate::pac::$inst;
950 } 1089 }
951 1090
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index fa1f710d8..f79a11606 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -13,8 +13,7 @@ use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; 13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
14 14
15use crate::dma::NoDma; 15use crate::dma::NoDma;
16use crate::gpio::sealed::{AFType, Pin}; 16use crate::gpio::{AFType, AnyPin, Pull, SealedPin, Speed};
17use crate::gpio::{AnyPin, Pull, Speed};
18use crate::interrupt::typelevel::Interrupt; 17use crate::interrupt::typelevel::Interrupt;
19use crate::pac::sdmmc::Sdmmc as RegBlock; 18use crate::pac::sdmmc::Sdmmc as RegBlock;
20use crate::rcc::RccPeripheral; 19use crate::rcc::RccPeripheral;
@@ -1418,21 +1417,17 @@ impl Cmd {
1418 1417
1419////////////////////////////////////////////////////// 1418//////////////////////////////////////////////////////
1420 1419
1421pub(crate) mod sealed { 1420trait SealedInstance {
1422 use super::*; 1421 fn regs() -> RegBlock;
1423 1422 fn state() -> &'static AtomicWaker;
1424 pub trait Instance {
1425 type Interrupt: interrupt::typelevel::Interrupt;
1426
1427 fn regs() -> RegBlock;
1428 fn state() -> &'static AtomicWaker;
1429 }
1430
1431 pub trait Pins<T: Instance> {}
1432} 1423}
1433 1424
1434/// SDMMC instance trait. 1425/// SDMMC instance trait.
1435pub trait Instance: sealed::Instance + RccPeripheral + 'static {} 1426#[allow(private_bounds)]
1427pub trait Instance: SealedInstance + RccPeripheral + 'static {
1428 /// Interrupt for this instance.
1429 type Interrupt: interrupt::typelevel::Interrupt;
1430}
1436 1431
1437pin_trait!(CkPin, Instance); 1432pin_trait!(CkPin, Instance);
1438pin_trait!(CmdPin, Instance); 1433pin_trait!(CmdPin, Instance);
@@ -1459,9 +1454,7 @@ impl<T: Instance> SdmmcDma<T> for NoDma {}
1459 1454
1460foreach_peripheral!( 1455foreach_peripheral!(
1461 (sdmmc, $inst:ident) => { 1456 (sdmmc, $inst:ident) => {
1462 impl sealed::Instance for peripherals::$inst { 1457 impl SealedInstance for peripherals::$inst {
1463 type Interrupt = crate::interrupt::typelevel::$inst;
1464
1465 fn regs() -> RegBlock { 1458 fn regs() -> RegBlock {
1466 crate::pac::$inst 1459 crate::pac::$inst
1467 } 1460 }
@@ -1472,6 +1465,8 @@ foreach_peripheral!(
1472 } 1465 }
1473 } 1466 }
1474 1467
1475 impl Instance for peripherals::$inst {} 1468 impl Instance for peripherals::$inst {
1469 type Interrupt = crate::interrupt::typelevel::$inst;
1470 }
1476 }; 1471 };
1477); 1472);
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index b517f640a..0b38c4288 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -9,8 +9,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
9pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 9pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
10 10
11use crate::dma::{slice_ptr_parts, word, Transfer}; 11use crate::dma::{slice_ptr_parts, word, Transfer};
12use crate::gpio::sealed::{AFType, Pin as _}; 12use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _};
13use crate::gpio::{AnyPin, Pull};
14use crate::pac::spi::{regs, vals, Spi as Regs}; 13use crate::pac::spi::{regs, vals, Spi as Regs};
15use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
16use crate::time::Hertz; 15use crate::time::Hertz;
@@ -210,7 +209,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
210 // see RM0453 rev 1 section 7.2.13 page 291 209 // see RM0453 rev 1 section 7.2.13 page 291
211 // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. 210 // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two.
212 // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz. 211 // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz.
213 let pclk3_freq = <peripherals::SUBGHZSPI as crate::rcc::sealed::RccPeripheral>::frequency().0; 212 let pclk3_freq = <peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::frequency().0;
214 let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000)); 213 let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000));
215 let mut config = Config::default(); 214 let mut config = Config::default();
216 config.mode = MODE_0; 215 config.mode = MODE_0;
@@ -271,13 +270,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
271 if mosi.is_none() { 270 if mosi.is_none() {
272 w.set_rxonly(vals::Rxonly::OUTPUTDISABLED); 271 w.set_rxonly(vals::Rxonly::OUTPUTDISABLED);
273 } 272 }
274 w.set_dff(<u8 as sealed::Word>::CONFIG) 273 w.set_dff(<u8 as SealedWord>::CONFIG)
275 }); 274 });
276 } 275 }
277 #[cfg(spi_v2)] 276 #[cfg(spi_v2)]
278 { 277 {
279 T::REGS.cr2().modify(|w| { 278 T::REGS.cr2().modify(|w| {
280 let (ds, frxth) = <u8 as sealed::Word>::CONFIG; 279 let (ds, frxth) = <u8 as SealedWord>::CONFIG;
281 w.set_frxth(frxth); 280 w.set_frxth(frxth);
282 w.set_ds(ds); 281 w.set_ds(ds);
283 w.set_ssoe(false); 282 w.set_ssoe(false);
@@ -317,7 +316,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
317 T::REGS.cfg1().modify(|w| { 316 T::REGS.cfg1().modify(|w| {
318 w.set_crcen(false); 317 w.set_crcen(false);
319 w.set_mbr(br); 318 w.set_mbr(br);
320 w.set_dsize(<u8 as sealed::Word>::CONFIG); 319 w.set_dsize(<u8 as SealedWord>::CONFIG);
321 w.set_fthlv(vals::Fthlv::ONEFRAME); 320 w.set_fthlv(vals::Fthlv::ONEFRAME);
322 }); 321 });
323 T::REGS.cr2().modify(|w| { 322 T::REGS.cr2().modify(|w| {
@@ -336,7 +335,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
336 miso, 335 miso,
337 txdma, 336 txdma,
338 rxdma, 337 rxdma,
339 current_word_size: <u8 as sealed::Word>::CONFIG, 338 current_word_size: <u8 as SealedWord>::CONFIG,
340 } 339 }
341 } 340 }
342 341
@@ -975,24 +974,21 @@ impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>, W: Word> embedded_hal_async::s
975 } 974 }
976} 975}
977 976
978pub(crate) mod sealed { 977pub(crate) trait SealedInstance {
979 use super::*; 978 const REGS: Regs;
980 979}
981 pub trait Instance {
982 const REGS: Regs;
983 }
984 980
985 pub trait Word { 981trait SealedWord {
986 const CONFIG: word_impl::Config; 982 const CONFIG: word_impl::Config;
987 }
988} 983}
989 984
990/// Word sizes usable for SPI. 985/// Word sizes usable for SPI.
991pub trait Word: word::Word + sealed::Word {} 986#[allow(private_bounds)]
987pub trait Word: word::Word + SealedWord {}
992 988
993macro_rules! impl_word { 989macro_rules! impl_word {
994 ($T:ty, $config:expr) => { 990 ($T:ty, $config:expr) => {
995 impl sealed::Word for $T { 991 impl SealedWord for $T {
996 const CONFIG: Config = $config; 992 const CONFIG: Config = $config;
997 } 993 }
998 impl Word for $T {} 994 impl Word for $T {}
@@ -1068,7 +1064,8 @@ mod word_impl {
1068} 1064}
1069 1065
1070/// SPI instance trait. 1066/// SPI instance trait.
1071pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 1067#[allow(private_bounds)]
1068pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
1072 1069
1073pin_trait!(SckPin, Instance); 1070pin_trait!(SckPin, Instance);
1074pin_trait!(MosiPin, Instance); 1071pin_trait!(MosiPin, Instance);
@@ -1082,7 +1079,7 @@ dma_trait!(TxDma, Instance);
1082 1079
1083foreach_peripheral!( 1080foreach_peripheral!(
1084 (spi, $inst:ident) => { 1081 (spi, $inst:ident) => {
1085 impl sealed::Instance for peripherals::$inst { 1082 impl SealedInstance for peripherals::$inst {
1086 const REGS: Regs = crate::pac::$inst; 1083 const REGS: Regs = crate::pac::$inst;
1087 } 1084 }
1088 1085
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 37b2e7526..cc8161276 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -1,7 +1,6 @@
1#![allow(non_snake_case)] 1#![allow(non_snake_case)]
2 2
3use core::cell::Cell; 3use core::cell::Cell;
4use core::convert::TryInto;
5use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering}; 4use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};
6use core::{mem, ptr}; 5use core::{mem, ptr};
7 6
@@ -9,16 +8,16 @@ use critical_section::CriticalSection;
9use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
10use embassy_sync::blocking_mutex::Mutex; 9use embassy_sync::blocking_mutex::Mutex;
11use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ}; 10use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ};
12use stm32_metapac::timer::regs; 11use stm32_metapac::timer::{regs, TimGp16};
13 12
14use crate::interrupt::typelevel::Interrupt; 13use crate::interrupt::typelevel::Interrupt;
15use crate::pac::timer::vals; 14use crate::pac::timer::vals;
16use crate::rcc::sealed::RccPeripheral; 15use crate::rcc::SealedRccPeripheral;
17#[cfg(feature = "low-power")] 16#[cfg(feature = "low-power")]
18use crate::rtc::Rtc; 17use crate::rtc::Rtc;
19#[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] 18#[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))]
20use crate::timer::sealed::AdvancedControlInstance; 19use crate::timer::AdvancedInstance1Channel;
21use crate::timer::sealed::{CoreInstance, GeneralPurpose16bitInstance as Instance}; 20use crate::timer::CoreInstance;
22use crate::{interrupt, peripherals}; 21use crate::{interrupt, peripherals};
23 22
24// NOTE regarding ALARM_COUNT: 23// NOTE regarding ALARM_COUNT:
@@ -208,6 +207,10 @@ foreach_interrupt! {
208 }; 207 };
209} 208}
210 209
210fn regs_gp16() -> TimGp16 {
211 unsafe { TimGp16::from_ptr(T::regs()) }
212}
213
211// Clock timekeeping works with something we call "periods", which are time intervals 214// Clock timekeeping works with something we call "periods", which are time intervals
212// of 2^15 ticks. The Clock counter value is 16 bits, so one "overflow cycle" is 2 periods. 215// of 2^15 ticks. The Clock counter value is 16 bits, so one "overflow cycle" is 2 periods.
213// 216//
@@ -272,9 +275,9 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
272 275
273impl RtcDriver { 276impl RtcDriver {
274 fn init(&'static self, cs: critical_section::CriticalSection) { 277 fn init(&'static self, cs: critical_section::CriticalSection) {
275 let r = T::regs_gp16(); 278 let r = regs_gp16();
276 279
277 <T as RccPeripheral>::enable_and_reset_with_cs(cs); 280 <T as SealedRccPeripheral>::enable_and_reset_with_cs(cs);
278 281
279 let timer_freq = T::frequency(); 282 let timer_freq = T::frequency();
280 283
@@ -287,7 +290,7 @@ impl RtcDriver {
287 Ok(n) => n, 290 Ok(n) => n,
288 }; 291 };
289 292
290 r.psc().write(|w| w.set_psc(psc)); 293 r.psc().write_value(psc);
291 r.arr().write(|w| w.set_arr(u16::MAX)); 294 r.arr().write(|w| w.set_arr(u16::MAX));
292 295
293 // Set URS, generate update and clear URS 296 // Set URS, generate update and clear URS
@@ -309,9 +312,9 @@ impl RtcDriver {
309 312
310 #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] 313 #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))]
311 { 314 {
312 <T as AdvancedControlInstance>::CaptureCompareInterrupt::unpend(); 315 <T as AdvancedInstance1Channel>::CaptureCompareInterrupt::unpend();
313 unsafe { 316 unsafe {
314 <T as AdvancedControlInstance>::CaptureCompareInterrupt::enable(); 317 <T as AdvancedInstance1Channel>::CaptureCompareInterrupt::enable();
315 } 318 }
316 } 319 }
317 320
@@ -319,7 +322,7 @@ impl RtcDriver {
319 } 322 }
320 323
321 fn on_interrupt(&self) { 324 fn on_interrupt(&self) {
322 let r = T::regs_gp16(); 325 let r = regs_gp16();
323 326
324 // XXX: reduce the size of this critical section ? 327 // XXX: reduce the size of this critical section ?
325 critical_section::with(|cs| { 328 critical_section::with(|cs| {
@@ -350,7 +353,7 @@ impl RtcDriver {
350 } 353 }
351 354
352 fn next_period(&self) { 355 fn next_period(&self) {
353 let r = T::regs_gp16(); 356 let r = regs_gp16();
354 357
355 // We only modify the period from the timer interrupt, so we know this can't race. 358 // We only modify the period from the timer interrupt, so we know this can't race.
356 let period = self.period.load(Ordering::Relaxed) + 1; 359 let period = self.period.load(Ordering::Relaxed) + 1;
@@ -414,7 +417,7 @@ impl RtcDriver {
414 /// Add the given offset to the current time 417 /// Add the given offset to the current time
415 fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) { 418 fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) {
416 let offset = offset.as_ticks(); 419 let offset = offset.as_ticks();
417 let cnt = T::regs_gp16().cnt().read().cnt() as u32; 420 let cnt = regs_gp16().cnt().read().cnt() as u32;
418 let period = self.period.load(Ordering::SeqCst); 421 let period = self.period.load(Ordering::SeqCst);
419 422
420 // Correct the race, if it exists 423 // Correct the race, if it exists
@@ -440,7 +443,7 @@ impl RtcDriver {
440 let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period }; 443 let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period };
441 444
442 self.period.store(period, Ordering::SeqCst); 445 self.period.store(period, Ordering::SeqCst);
443 T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); 446 regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16));
444 447
445 // Now, recompute all alarms 448 // Now, recompute all alarms
446 for i in 0..ALARM_COUNT { 449 for i in 0..ALARM_COUNT {
@@ -497,7 +500,7 @@ impl RtcDriver {
497 .unwrap() 500 .unwrap()
498 .start_wakeup_alarm(time_until_next_alarm, cs); 501 .start_wakeup_alarm(time_until_next_alarm, cs);
499 502
500 T::regs_gp16().cr1().modify(|w| w.set_cen(false)); 503 regs_gp16().cr1().modify(|w| w.set_cen(false));
501 504
502 Ok(()) 505 Ok(())
503 } 506 }
@@ -507,7 +510,7 @@ impl RtcDriver {
507 #[cfg(feature = "low-power")] 510 #[cfg(feature = "low-power")]
508 /// Resume the timer with the given offset 511 /// Resume the timer with the given offset
509 pub(crate) fn resume_time(&self) { 512 pub(crate) fn resume_time(&self) {
510 if T::regs_gp16().cr1().read().cen() { 513 if regs_gp16().cr1().read().cen() {
511 // Time isn't currently stopped 514 // Time isn't currently stopped
512 515
513 return; 516 return;
@@ -516,14 +519,14 @@ impl RtcDriver {
516 critical_section::with(|cs| { 519 critical_section::with(|cs| {
517 self.stop_wakeup_alarm(cs); 520 self.stop_wakeup_alarm(cs);
518 521
519 T::regs_gp16().cr1().modify(|w| w.set_cen(true)); 522 regs_gp16().cr1().modify(|w| w.set_cen(true));
520 }) 523 })
521 } 524 }
522} 525}
523 526
524impl Driver for RtcDriver { 527impl Driver for RtcDriver {
525 fn now(&self) -> u64 { 528 fn now(&self) -> u64 {
526 let r = T::regs_gp16(); 529 let r = regs_gp16();
527 530
528 let period = self.period.load(Ordering::Relaxed); 531 let period = self.period.load(Ordering::Relaxed);
529 compiler_fence(Ordering::Acquire); 532 compiler_fence(Ordering::Acquire);
@@ -554,7 +557,7 @@ impl Driver for RtcDriver {
554 557
555 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool { 558 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
556 critical_section::with(|cs| { 559 critical_section::with(|cs| {
557 let r = T::regs_gp16(); 560 let r = regs_gp16();
558 561
559 let n = alarm.id() as usize; 562 let n = alarm.id() as usize;
560 let alarm = self.get_alarm(cs, alarm); 563 let alarm = self.get_alarm(cs, alarm);
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 72f1ec864..a892646cf 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -5,12 +5,15 @@ use core::marker::PhantomData;
5use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use stm32_metapac::timer::vals::Ckd; 6use stm32_metapac::timer::vals::Ckd;
7 7
8use super::simple_pwm::*; 8use super::low_level::{CountingMode, OutputPolarity, Timer};
9use super::*; 9use super::simple_pwm::{Ch1, Ch2, Ch3, Ch4, PwmPin};
10#[allow(unused_imports)] 10use super::{
11use crate::gpio::sealed::{AFType, Pin}; 11 AdvancedInstance4Channel, Channel, Channel1ComplementaryPin, Channel2ComplementaryPin, Channel3ComplementaryPin,
12 Channel4ComplementaryPin,
13};
12use crate::gpio::{AnyPin, OutputType}; 14use crate::gpio::{AnyPin, OutputType};
13use crate::time::Hertz; 15use crate::time::Hertz;
16use crate::timer::low_level::OutputCompareMode;
14use crate::Peripheral; 17use crate::Peripheral;
15 18
16/// Complementary PWM pin wrapper. 19/// Complementary PWM pin wrapper.
@@ -23,7 +26,7 @@ pub struct ComplementaryPwmPin<'d, T, C> {
23 26
24macro_rules! complementary_channel_impl { 27macro_rules! complementary_channel_impl {
25 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 28 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
26 impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> { 29 impl<'d, T: AdvancedInstance4Channel> ComplementaryPwmPin<'d, T, $channel> {
27 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] 30 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
28 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self { 31 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
29 into_ref!(pin); 32 into_ref!(pin);
@@ -48,11 +51,11 @@ complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
48complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); 51complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
49 52
50/// PWM driver with support for standard and complementary outputs. 53/// PWM driver with support for standard and complementary outputs.
51pub struct ComplementaryPwm<'d, T> { 54pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> {
52 inner: PeripheralRef<'d, T>, 55 inner: Timer<'d, T>,
53} 56}
54 57
55impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { 58impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
56 /// Create a new complementary PWM driver. 59 /// Create a new complementary PWM driver.
57 #[allow(clippy::too_many_arguments)] 60 #[allow(clippy::too_many_arguments)]
58 pub fn new( 61 pub fn new(
@@ -72,11 +75,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
72 } 75 }
73 76
74 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { 77 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
75 into_ref!(tim); 78 let mut this = Self { inner: Timer::new(tim) };
76
77 T::enable_and_reset();
78
79 let mut this = Self { inner: tim };
80 79
81 this.inner.set_counting_mode(counting_mode); 80 this.inner.set_counting_mode(counting_mode);
82 this.set_frequency(freq); 81 this.set_frequency(freq);
@@ -123,7 +122,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
123 /// 122 ///
124 /// This value depends on the configured frequency and the timer's clock rate from RCC. 123 /// This value depends on the configured frequency and the timer's clock rate from RCC.
125 pub fn get_max_duty(&self) -> u16 { 124 pub fn get_max_duty(&self) -> u16 {
126 self.inner.get_max_compare_value() + 1 125 self.inner.get_max_compare_value() as u16 + 1
127 } 126 }
128 127
129 /// Set the duty for a given channel. 128 /// Set the duty for a given channel.
@@ -131,7 +130,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
131 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. 130 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
132 pub fn set_duty(&mut self, channel: Channel, duty: u16) { 131 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
133 assert!(duty <= self.get_max_duty()); 132 assert!(duty <= self.get_max_duty());
134 self.inner.set_compare_value(channel, duty) 133 self.inner.set_compare_value(channel, duty as _)
135 } 134 }
136 135
137 /// Set the output polarity for a given channel. 136 /// Set the output polarity for a given channel.
@@ -149,7 +148,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
149 } 148 }
150} 149}
151 150
152impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { 151impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
153 type Channel = Channel; 152 type Channel = Channel;
154 type Time = Hertz; 153 type Time = Hertz;
155 type Duty = u16; 154 type Duty = u16;
@@ -169,16 +168,16 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for C
169 } 168 }
170 169
171 fn get_duty(&self, channel: Self::Channel) -> Self::Duty { 170 fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
172 self.inner.get_compare_value(channel) 171 self.inner.get_compare_value(channel) as u16
173 } 172 }
174 173
175 fn get_max_duty(&self) -> Self::Duty { 174 fn get_max_duty(&self) -> Self::Duty {
176 self.inner.get_max_compare_value() + 1 175 self.inner.get_max_compare_value() as u16 + 1
177 } 176 }
178 177
179 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { 178 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
180 assert!(duty <= self.get_max_duty()); 179 assert!(duty <= self.get_max_duty());
181 self.inner.set_compare_value(channel, duty) 180 self.inner.set_compare_value(channel, duty as u32)
182 } 181 }
183 182
184 fn set_period<P>(&mut self, period: P) 183 fn set_period<P>(&mut self, period: P)
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs
new file mode 100644
index 000000000..a5d942314
--- /dev/null
+++ b/embassy-stm32/src/timer/low_level.rs
@@ -0,0 +1,638 @@
1//! Low-level timer driver.
2//!
3//! This is an unopinionated, very low-level driver for all STM32 timers. It allows direct register
4//! manipulation with the `regs_*()` methods, and has utility functions that are thin wrappers
5//! over the registers.
6//!
7//! The available functionality depends on the timer type.
8
9use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
10
11use super::*;
12use crate::pac::timer::vals;
13use crate::time::Hertz;
14
15/// Input capture mode.
16#[derive(Clone, Copy)]
17pub enum InputCaptureMode {
18 /// Rising edge only.
19 Rising,
20 /// Falling edge only.
21 Falling,
22 /// Both rising or falling edges.
23 BothEdges,
24}
25
26/// Input TI selection.
27#[derive(Clone, Copy)]
28pub enum InputTISelection {
29 /// Normal
30 Normal,
31 /// Alternate
32 Alternate,
33 /// TRC
34 TRC,
35}
36
37impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs {
38 fn from(tisel: InputTISelection) -> Self {
39 match tisel {
40 InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4,
41 InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3,
42 InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC,
43 }
44 }
45}
46
47/// Timer counting mode.
48#[repr(u8)]
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
50pub enum CountingMode {
51 #[default]
52 /// The timer counts up to the reload value and then resets back to 0.
53 EdgeAlignedUp,
54 /// The timer counts down to 0 and then resets back to the reload value.
55 EdgeAlignedDown,
56 /// The timer counts up to the reload value and then counts back to 0.
57 ///
58 /// The output compare interrupt flags of channels configured in output are
59 /// set when the counter is counting down.
60 CenterAlignedDownInterrupts,
61 /// The timer counts up to the reload value and then counts back to 0.
62 ///
63 /// The output compare interrupt flags of channels configured in output are
64 /// set when the counter is counting up.
65 CenterAlignedUpInterrupts,
66 /// The timer counts up to the reload value and then counts back to 0.
67 ///
68 /// The output compare interrupt flags of channels configured in output are
69 /// set when the counter is counting both up or down.
70 CenterAlignedBothInterrupts,
71}
72
73impl CountingMode {
74 /// Return whether this mode is edge-aligned (up or down).
75 pub fn is_edge_aligned(&self) -> bool {
76 matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown)
77 }
78
79 /// Return whether this mode is center-aligned.
80 pub fn is_center_aligned(&self) -> bool {
81 matches!(
82 self,
83 CountingMode::CenterAlignedDownInterrupts
84 | CountingMode::CenterAlignedUpInterrupts
85 | CountingMode::CenterAlignedBothInterrupts
86 )
87 }
88}
89
90impl From<CountingMode> for (vals::Cms, vals::Dir) {
91 fn from(value: CountingMode) -> Self {
92 match value {
93 CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP),
94 CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN),
95 CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP),
96 CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP),
97 CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP),
98 }
99 }
100}
101
102impl From<(vals::Cms, vals::Dir)> for CountingMode {
103 fn from(value: (vals::Cms, vals::Dir)) -> Self {
104 match value {
105 (vals::Cms::EDGEALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp,
106 (vals::Cms::EDGEALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown,
107 (vals::Cms::CENTERALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts,
108 (vals::Cms::CENTERALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts,
109 (vals::Cms::CENTERALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts,
110 }
111 }
112}
113
114/// Output compare mode.
115#[derive(Clone, Copy)]
116pub enum OutputCompareMode {
117 /// The comparison between the output compare register TIMx_CCRx and
118 /// the counter TIMx_CNT has no effect on the outputs.
119 /// (this mode is used to generate a timing base).
120 Frozen,
121 /// Set channel to active level on match. OCxREF signal is forced high when the
122 /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
123 ActiveOnMatch,
124 /// Set channel to inactive level on match. OCxREF signal is forced low when the
125 /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
126 InactiveOnMatch,
127 /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx.
128 Toggle,
129 /// Force inactive level - OCxREF is forced low.
130 ForceInactive,
131 /// Force active level - OCxREF is forced high.
132 ForceActive,
133 /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRx
134 /// else inactive. In downcounting, channel is inactive (OCxREF=0) as long as
135 /// TIMx_CNT>TIMx_CCRx else active (OCxREF=1).
136 PwmMode1,
137 /// PWM mode 2 - In upcounting, channel is inactive as long as
138 /// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as
139 /// TIMx_CNT>TIMx_CCRx else inactive.
140 PwmMode2,
141 // TODO: there's more modes here depending on the chip family.
142}
143
144impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
145 fn from(mode: OutputCompareMode) -> Self {
146 match mode {
147 OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN,
148 OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH,
149 OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH,
150 OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE,
151 OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE,
152 OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE,
153 OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1,
154 OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2,
155 }
156 }
157}
158
159/// Timer output pin polarity.
160#[derive(Clone, Copy)]
161pub enum OutputPolarity {
162 /// Active high (higher duty value makes the pin spend more time high).
163 ActiveHigh,
164 /// Active low (higher duty value makes the pin spend more time low).
165 ActiveLow,
166}
167
168impl From<OutputPolarity> for bool {
169 fn from(mode: OutputPolarity) -> Self {
170 match mode {
171 OutputPolarity::ActiveHigh => false,
172 OutputPolarity::ActiveLow => true,
173 }
174 }
175}
176
177/// Low-level timer driver.
178pub struct Timer<'d, T: CoreInstance> {
179 tim: PeripheralRef<'d, T>,
180}
181
182impl<'d, T: CoreInstance> Drop for Timer<'d, T> {
183 fn drop(&mut self) {
184 T::disable()
185 }
186}
187
188impl<'d, T: CoreInstance> Timer<'d, T> {
189 /// Create a new timer driver.
190 pub fn new(tim: impl Peripheral<P = T> + 'd) -> Self {
191 into_ref!(tim);
192
193 T::enable_and_reset();
194
195 Self { tim }
196 }
197
198 /// Get access to the virutal core 16bit timer registers.
199 ///
200 /// Note: This works even if the timer is more capable, because registers
201 /// for the less capable timers are a subset. This allows writing a driver
202 /// for a given set of capabilities, and having it transparently work with
203 /// more capable timers.
204 pub fn regs_core(&self) -> crate::pac::timer::TimCore {
205 unsafe { crate::pac::timer::TimCore::from_ptr(T::regs()) }
206 }
207
208 #[cfg(not(stm32l0))]
209 fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp32 {
210 unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) }
211 }
212
213 /// Start the timer.
214 pub fn start(&self) {
215 self.regs_core().cr1().modify(|r| r.set_cen(true));
216 }
217
218 /// Stop the timer.
219 pub fn stop(&self) {
220 self.regs_core().cr1().modify(|r| r.set_cen(false));
221 }
222
223 /// Reset the counter value to 0
224 pub fn reset(&self) {
225 self.regs_core().cnt().write(|r| r.set_cnt(0));
226 }
227
228 /// Set the frequency of how many times per second the timer counts up to the max value or down to 0.
229 ///
230 /// This means that in the default edge-aligned mode,
231 /// the timer counter will wrap around at the same frequency as is being set.
232 /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved
233 /// because it needs to count up and down.
234 pub fn set_frequency(&self, frequency: Hertz) {
235 let f = frequency.0;
236 assert!(f > 0);
237 let timer_f = T::frequency().0;
238
239 match T::BITS {
240 TimerBits::Bits16 => {
241 let pclk_ticks_per_timer_period = timer_f / f;
242 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into());
243 let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1);
244
245 // the timer counts `0..=arr`, we want it to count `0..divide_by`
246 let arr = unwrap!(u16::try_from(divide_by - 1));
247
248 let regs = self.regs_core();
249 regs.psc().write_value(psc);
250 regs.arr().write(|r| r.set_arr(arr));
251
252 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
253 regs.egr().write(|r| r.set_ug(true));
254 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
255 }
256 #[cfg(not(stm32l0))]
257 TimerBits::Bits32 => {
258 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
259 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into());
260 let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into());
261
262 let regs = self.regs_gp32_unchecked();
263 regs.psc().write_value(psc);
264 regs.arr().write_value(arr);
265
266 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
267 regs.egr().write(|r| r.set_ug(true));
268 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
269 }
270 }
271 }
272
273 /// Clear update interrupt.
274 ///
275 /// Returns whether the update interrupt flag was set.
276 pub fn clear_update_interrupt(&self) -> bool {
277 let regs = self.regs_core();
278 let sr = regs.sr().read();
279 if sr.uif() {
280 regs.sr().modify(|r| {
281 r.set_uif(false);
282 });
283 true
284 } else {
285 false
286 }
287 }
288
289 /// Enable/disable the update interrupt.
290 pub fn enable_update_interrupt(&self, enable: bool) {
291 self.regs_core().dier().modify(|r| r.set_uie(enable));
292 }
293
294 /// Enable/disable autoreload preload.
295 pub fn set_autoreload_preload(&self, enable: bool) {
296 self.regs_core().cr1().modify(|r| r.set_arpe(enable));
297 }
298
299 /// Get the timer frequency.
300 pub fn get_frequency(&self) -> Hertz {
301 let timer_f = T::frequency();
302
303 match T::BITS {
304 TimerBits::Bits16 => {
305 let regs = self.regs_core();
306 let arr = regs.arr().read().arr();
307 let psc = regs.psc().read();
308
309 timer_f / arr / (psc + 1)
310 }
311 #[cfg(not(stm32l0))]
312 TimerBits::Bits32 => {
313 let regs = self.regs_gp32_unchecked();
314 let arr = regs.arr().read();
315 let psc = regs.psc().read();
316
317 timer_f / arr / (psc + 1)
318 }
319 }
320 }
321}
322
323impl<'d, T: BasicNoCr2Instance> Timer<'d, T> {
324 /// Get access to the Baisc 16bit timer registers.
325 ///
326 /// Note: This works even if the timer is more capable, because registers
327 /// for the less capable timers are a subset. This allows writing a driver
328 /// for a given set of capabilities, and having it transparently work with
329 /// more capable timers.
330 pub fn regs_basic_no_cr2(&self) -> crate::pac::timer::TimBasicNoCr2 {
331 unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(T::regs()) }
332 }
333
334 /// Enable/disable the update dma.
335 pub fn enable_update_dma(&self, enable: bool) {
336 self.regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable));
337 }
338
339 /// Get the update dma enable/disable state.
340 pub fn get_update_dma_state(&self) -> bool {
341 self.regs_basic_no_cr2().dier().read().ude()
342 }
343}
344
345impl<'d, T: BasicInstance> Timer<'d, T> {
346 /// Get access to the Baisc 16bit timer registers.
347 ///
348 /// Note: This works even if the timer is more capable, because registers
349 /// for the less capable timers are a subset. This allows writing a driver
350 /// for a given set of capabilities, and having it transparently work with
351 /// more capable timers.
352 pub fn regs_basic(&self) -> crate::pac::timer::TimBasic {
353 unsafe { crate::pac::timer::TimBasic::from_ptr(T::regs()) }
354 }
355}
356
357impl<'d, T: GeneralInstance1Channel> Timer<'d, T> {
358 /// Get access to the general purpose 1 channel 16bit timer registers.
359 ///
360 /// Note: This works even if the timer is more capable, because registers
361 /// for the less capable timers are a subset. This allows writing a driver
362 /// for a given set of capabilities, and having it transparently work with
363 /// more capable timers.
364 pub fn regs_1ch(&self) -> crate::pac::timer::Tim1ch {
365 unsafe { crate::pac::timer::Tim1ch::from_ptr(T::regs()) }
366 }
367
368 /// Set clock divider.
369 pub fn set_clock_division(&self, ckd: vals::Ckd) {
370 self.regs_1ch().cr1().modify(|r| r.set_ckd(ckd));
371 }
372
373 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
374 pub fn get_max_compare_value(&self) -> u32 {
375 match T::BITS {
376 TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32,
377 #[cfg(not(stm32l0))]
378 TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(),
379 }
380 }
381}
382
383impl<'d, T: GeneralInstance2Channel> Timer<'d, T> {
384 /// Get access to the general purpose 2 channel 16bit timer registers.
385 ///
386 /// Note: This works even if the timer is more capable, because registers
387 /// for the less capable timers are a subset. This allows writing a driver
388 /// for a given set of capabilities, and having it transparently work with
389 /// more capable timers.
390 pub fn regs_2ch(&self) -> crate::pac::timer::Tim2ch {
391 unsafe { crate::pac::timer::Tim2ch::from_ptr(T::regs()) }
392 }
393}
394
395impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
396 /// Get access to the general purpose 16bit timer registers.
397 ///
398 /// Note: This works even if the timer is more capable, because registers
399 /// for the less capable timers are a subset. This allows writing a driver
400 /// for a given set of capabilities, and having it transparently work with
401 /// more capable timers.
402 pub fn regs_gp16(&self) -> crate::pac::timer::TimGp16 {
403 unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }
404 }
405
406 /// Enable timer outputs.
407 pub fn enable_outputs(&self) {
408 self.tim.enable_outputs()
409 }
410
411 /// Set counting mode.
412 pub fn set_counting_mode(&self, mode: CountingMode) {
413 let (cms, dir) = mode.into();
414
415 let timer_enabled = self.regs_core().cr1().read().cen();
416 // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running.
417 // Changing direction is discouraged while the timer is running.
418 assert!(!timer_enabled);
419
420 self.regs_gp16().cr1().modify(|r| r.set_dir(dir));
421 self.regs_gp16().cr1().modify(|r| r.set_cms(cms))
422 }
423
424 /// Get counting mode.
425 pub fn get_counting_mode(&self) -> CountingMode {
426 let cr1 = self.regs_gp16().cr1().read();
427 (cr1.cms(), cr1.dir()).into()
428 }
429
430 /// Set input capture filter.
431 pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) {
432 let raw_channel = channel.index();
433 self.regs_gp16()
434 .ccmr_input(raw_channel / 2)
435 .modify(|r| r.set_icf(raw_channel % 2, icf));
436 }
437
438 /// Clear input interrupt.
439 pub fn clear_input_interrupt(&self, channel: Channel) {
440 self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
441 }
442
443 /// Enable input interrupt.
444 pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) {
445 self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
446 }
447
448 /// Set input capture prescaler.
449 pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) {
450 let raw_channel = channel.index();
451 self.regs_gp16()
452 .ccmr_input(raw_channel / 2)
453 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
454 }
455
456 /// Set input TI selection.
457 pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) {
458 let raw_channel = channel.index();
459 self.regs_gp16()
460 .ccmr_input(raw_channel / 2)
461 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
462 }
463
464 /// Set input capture mode.
465 pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) {
466 self.regs_gp16().ccer().modify(|r| match mode {
467 InputCaptureMode::Rising => {
468 r.set_ccnp(channel.index(), false);
469 r.set_ccp(channel.index(), false);
470 }
471 InputCaptureMode::Falling => {
472 r.set_ccnp(channel.index(), false);
473 r.set_ccp(channel.index(), true);
474 }
475 InputCaptureMode::BothEdges => {
476 r.set_ccnp(channel.index(), true);
477 r.set_ccp(channel.index(), true);
478 }
479 });
480 }
481
482 /// Set output compare mode.
483 pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) {
484 let raw_channel: usize = channel.index();
485 self.regs_gp16()
486 .ccmr_output(raw_channel / 2)
487 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
488 }
489
490 /// Set output polarity.
491 pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
492 self.regs_gp16()
493 .ccer()
494 .modify(|w| w.set_ccp(channel.index(), polarity.into()));
495 }
496
497 /// Enable/disable a channel.
498 pub fn enable_channel(&self, channel: Channel, enable: bool) {
499 self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
500 }
501
502 /// Get enable/disable state of a channel
503 pub fn get_channel_enable_state(&self, channel: Channel) -> bool {
504 self.regs_gp16().ccer().read().cce(channel.index())
505 }
506
507 /// Set compare value for a channel.
508 pub fn set_compare_value(&self, channel: Channel, value: u32) {
509 match T::BITS {
510 TimerBits::Bits16 => {
511 let value = unwrap!(u16::try_from(value));
512 self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
513 }
514 #[cfg(not(stm32l0))]
515 TimerBits::Bits32 => {
516 self.regs_gp32_unchecked().ccr(channel.index()).write_value(value);
517 }
518 }
519 }
520
521 /// Get compare value for a channel.
522 pub fn get_compare_value(&self, channel: Channel) -> u32 {
523 match T::BITS {
524 TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32,
525 #[cfg(not(stm32l0))]
526 TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(),
527 }
528 }
529
530 /// Get capture value for a channel.
531 pub fn get_capture_value(&self, channel: Channel) -> u32 {
532 self.get_compare_value(channel)
533 }
534
535 /// Set output compare preload.
536 pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) {
537 let channel_index = channel.index();
538 self.regs_gp16()
539 .ccmr_output(channel_index / 2)
540 .modify(|w| w.set_ocpe(channel_index % 2, preload));
541 }
542
543 /// Get capture compare DMA selection
544 pub fn get_cc_dma_selection(&self) -> vals::Ccds {
545 self.regs_gp16().cr2().read().ccds()
546 }
547
548 /// Set capture compare DMA selection
549 pub fn set_cc_dma_selection(&self, ccds: vals::Ccds) {
550 self.regs_gp16().cr2().modify(|w| w.set_ccds(ccds))
551 }
552
553 /// Get capture compare DMA enable state
554 pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
555 self.regs_gp16().dier().read().ccde(channel.index())
556 }
557
558 /// Set capture compare DMA enable state
559 pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) {
560 self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
561 }
562}
563
564#[cfg(not(stm32l0))]
565impl<'d, T: GeneralInstance32bit4Channel> Timer<'d, T> {
566 /// Get access to the general purpose 32bit timer registers.
567 ///
568 /// Note: This works even if the timer is more capable, because registers
569 /// for the less capable timers are a subset. This allows writing a driver
570 /// for a given set of capabilities, and having it transparently work with
571 /// more capable timers.
572 pub fn regs_gp32(&self) -> crate::pac::timer::TimGp32 {
573 unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) }
574 }
575}
576
577#[cfg(not(stm32l0))]
578impl<'d, T: AdvancedInstance1Channel> Timer<'d, T> {
579 /// Get access to the general purpose 1 channel with one complementary 16bit timer registers.
580 ///
581 /// Note: This works even if the timer is more capable, because registers
582 /// for the less capable timers are a subset. This allows writing a driver
583 /// for a given set of capabilities, and having it transparently work with
584 /// more capable timers.
585 pub fn regs_1ch_cmp(&self) -> crate::pac::timer::Tim1chCmp {
586 unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) }
587 }
588
589 /// Set clock divider for the dead time.
590 pub fn set_dead_time_clock_division(&self, value: vals::Ckd) {
591 self.regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value));
592 }
593
594 /// Set dead time, as a fraction of the max duty value.
595 pub fn set_dead_time_value(&self, value: u8) {
596 self.regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value));
597 }
598
599 /// Set state of MOE-bit in BDTR register to en-/disable output
600 pub fn set_moe(&self, enable: bool) {
601 self.regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable));
602 }
603}
604
605#[cfg(not(stm32l0))]
606impl<'d, T: AdvancedInstance2Channel> Timer<'d, T> {
607 /// Get access to the general purpose 2 channel with one complementary 16bit timer registers.
608 ///
609 /// Note: This works even if the timer is more capable, because registers
610 /// for the less capable timers are a subset. This allows writing a driver
611 /// for a given set of capabilities, and having it transparently work with
612 /// more capable timers.
613 pub fn regs_2ch_cmp(&self) -> crate::pac::timer::Tim2chCmp {
614 unsafe { crate::pac::timer::Tim2chCmp::from_ptr(T::regs()) }
615 }
616}
617
618#[cfg(not(stm32l0))]
619impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> {
620 /// Get access to the advanced timer registers.
621 pub fn regs_advanced(&self) -> crate::pac::timer::TimAdv {
622 unsafe { crate::pac::timer::TimAdv::from_ptr(T::regs()) }
623 }
624
625 /// Set complementary output polarity.
626 pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
627 self.regs_advanced()
628 .ccer()
629 .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
630 }
631
632 /// Enable/disable a complementary channel.
633 pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) {
634 self.regs_advanced()
635 .ccer()
636 .modify(|w| w.set_ccne(channel.index(), enable));
637 }
638}
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index ef893c7f5..2ba6b3f11 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,490 +1,13 @@
1//! Timers, PWM, quadrature decoder. 1//! Timers, PWM, quadrature decoder.
2//!
3
4//! Timer inheritance
5//!
6
7// sealed:
8//
9// Core -------------------------> 1CH -------------------------> 1CH_CMP
10// | | ^ |
11// +--> Basic_NoCr2 --> Basic +--> 2CH --> GP16 --> GP32 | +--> 2CH_CMP --> ADV
12// | | | ^ | | ^ ^
13// | | +------|--|--------------|-----------+ |
14// | +--------------------+ +--------------|-----------|---------+
15// | | | |
16// | +--------------------------------------|-----------+
17// +----------------------------------------------------+
18
19//! ```text
20//! BasicInstance --> CaptureCompare16bitInstance --+--> ComplementaryCaptureCompare16bitInstance
21//! |
22//! +--> CaptureCompare32bitInstance
23//! ```
24//!
25//! Mapping:
26//!
27//! | trait | timer |
28//! | :----------------------------------------: | ------------------------------------------------------------------------------------------------- |
29//! | [BasicInstance] | Basic Timer |
30//! | [CaptureCompare16bitInstance] | 1-channel Timer, 2-channel Timer, General Purpose 16-bit Timer |
31//! | [CaptureCompare32bitInstance] | General Purpose 32-bit Timer |
32//! | [ComplementaryCaptureCompare16bitInstance] | 1-channel with one complentary Timer, 2-channel with one complentary Timer, Advance Control Timer |
33 2
34#[cfg(not(stm32l0))] 3#[cfg(not(stm32l0))]
35pub mod complementary_pwm; 4pub mod complementary_pwm;
5pub mod low_level;
36pub mod qei; 6pub mod qei;
37pub mod simple_pwm; 7pub mod simple_pwm;
38 8
39use stm32_metapac::timer::vals;
40
41use crate::interrupt; 9use crate::interrupt;
42use crate::rcc::RccPeripheral; 10use crate::rcc::RccPeripheral;
43use crate::time::Hertz;
44
45/// Low-level timer access.
46#[cfg(feature = "unstable-pac")]
47pub mod low_level {
48 pub use super::sealed::*;
49}
50
51pub(crate) mod sealed {
52 use super::*;
53
54 /// Virtual Core 16-bit timer instance.
55 pub trait CoreInstance: RccPeripheral {
56 /// Interrupt for this timer.
57 type Interrupt: interrupt::typelevel::Interrupt;
58
59 /// Get access to the virutal core 16bit timer registers.
60 ///
61 /// Note: This works even if the timer is more capable, because registers
62 /// for the less capable timers are a subset. This allows writing a driver
63 /// for a given set of capabilities, and having it transparently work with
64 /// more capable timers.
65 fn regs_core() -> crate::pac::timer::TimCore;
66
67 /// Start the timer.
68 fn start(&self) {
69 Self::regs_core().cr1().modify(|r| r.set_cen(true));
70 }
71
72 /// Stop the timer.
73 fn stop(&self) {
74 Self::regs_core().cr1().modify(|r| r.set_cen(false));
75 }
76
77 /// Reset the counter value to 0
78 fn reset(&self) {
79 Self::regs_core().cnt().write(|r| r.set_cnt(0));
80 }
81
82 /// Set the frequency of how many times per second the timer counts up to the max value or down to 0.
83 ///
84 /// This means that in the default edge-aligned mode,
85 /// the timer counter will wrap around at the same frequency as is being set.
86 /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved
87 /// because it needs to count up and down.
88 fn set_frequency(&self, frequency: Hertz) {
89 let f = frequency.0;
90 let timer_f = Self::frequency().0;
91 assert!(f > 0);
92 let pclk_ticks_per_timer_period = timer_f / f;
93 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into());
94 let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1);
95
96 // the timer counts `0..=arr`, we want it to count `0..divide_by`
97 let arr = unwrap!(u16::try_from(divide_by - 1));
98
99 let regs = Self::regs_core();
100 regs.psc().write(|r| r.set_psc(psc));
101 regs.arr().write(|r| r.set_arr(arr));
102
103 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
104 regs.egr().write(|r| r.set_ug(true));
105 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
106 }
107
108 /// Clear update interrupt.
109 ///
110 /// Returns whether the update interrupt flag was set.
111 fn clear_update_interrupt(&self) -> bool {
112 let regs = Self::regs_core();
113 let sr = regs.sr().read();
114 if sr.uif() {
115 regs.sr().modify(|r| {
116 r.set_uif(false);
117 });
118 true
119 } else {
120 false
121 }
122 }
123
124 /// Enable/disable the update interrupt.
125 fn enable_update_interrupt(&self, enable: bool) {
126 Self::regs_core().dier().modify(|r| r.set_uie(enable));
127 }
128
129 /// Enable/disable autoreload preload.
130 fn set_autoreload_preload(&self, enable: bool) {
131 Self::regs_core().cr1().modify(|r| r.set_arpe(enable));
132 }
133
134 /// Get the timer frequency.
135 fn get_frequency(&self) -> Hertz {
136 let timer_f = Self::frequency();
137
138 let regs = Self::regs_core();
139 let arr = regs.arr().read().arr();
140 let psc = regs.psc().read().psc();
141
142 timer_f / arr / (psc + 1)
143 }
144 }
145
146 /// Virtual Basic without CR2 16-bit timer instance.
147 pub trait BasicNoCr2Instance: CoreInstance {
148 /// Get access to the Baisc 16bit timer registers.
149 ///
150 /// Note: This works even if the timer is more capable, because registers
151 /// for the less capable timers are a subset. This allows writing a driver
152 /// for a given set of capabilities, and having it transparently work with
153 /// more capable timers.
154 fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2;
155
156 /// Enable/disable the update dma.
157 fn enable_update_dma(&self, enable: bool) {
158 Self::regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable));
159 }
160
161 /// Get the update dma enable/disable state.
162 fn get_update_dma_state(&self) -> bool {
163 Self::regs_basic_no_cr2().dier().read().ude()
164 }
165 }
166
167 /// Basic 16-bit timer instance.
168 pub trait BasicInstance: BasicNoCr2Instance {
169 /// Get access to the Baisc 16bit timer registers.
170 ///
171 /// Note: This works even if the timer is more capable, because registers
172 /// for the less capable timers are a subset. This allows writing a driver
173 /// for a given set of capabilities, and having it transparently work with
174 /// more capable timers.
175 fn regs_basic() -> crate::pac::timer::TimBasic;
176 }
177
178 /// Gneral-purpose 1 channel 16-bit timer instance.
179 pub trait GeneralPurpose1ChannelInstance: CoreInstance {
180 /// Get access to the general purpose 1 channel 16bit timer registers.
181 ///
182 /// Note: This works even if the timer is more capable, because registers
183 /// for the less capable timers are a subset. This allows writing a driver
184 /// for a given set of capabilities, and having it transparently work with
185 /// more capable timers.
186 fn regs_1ch() -> crate::pac::timer::Tim1ch;
187
188 /// Set clock divider.
189 fn set_clock_division(&self, ckd: vals::Ckd) {
190 Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd));
191 }
192
193 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
194 fn get_max_compare_value(&self) -> u16 {
195 Self::regs_1ch().arr().read().arr()
196 }
197 }
198
199 /// Gneral-purpose 1 channel 16-bit timer instance.
200 pub trait GeneralPurpose2ChannelInstance: GeneralPurpose1ChannelInstance {
201 /// Get access to the general purpose 2 channel 16bit timer registers.
202 ///
203 /// Note: This works even if the timer is more capable, because registers
204 /// for the less capable timers are a subset. This allows writing a driver
205 /// for a given set of capabilities, and having it transparently work with
206 /// more capable timers.
207 fn regs_2ch() -> crate::pac::timer::Tim2ch;
208 }
209
210 /// Gneral-purpose 16-bit timer instance.
211 pub trait GeneralPurpose16bitInstance: BasicInstance + GeneralPurpose2ChannelInstance {
212 /// Get access to the general purpose 16bit timer registers.
213 ///
214 /// Note: This works even if the timer is more capable, because registers
215 /// for the less capable timers are a subset. This allows writing a driver
216 /// for a given set of capabilities, and having it transparently work with
217 /// more capable timers.
218 fn regs_gp16() -> crate::pac::timer::TimGp16;
219
220 /// Set counting mode.
221 fn set_counting_mode(&self, mode: CountingMode) {
222 let (cms, dir) = mode.into();
223
224 let timer_enabled = Self::regs_core().cr1().read().cen();
225 // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running.
226 // Changing direction is discouraged while the timer is running.
227 assert!(!timer_enabled);
228
229 Self::regs_gp16().cr1().modify(|r| r.set_dir(dir));
230 Self::regs_gp16().cr1().modify(|r| r.set_cms(cms))
231 }
232
233 /// Get counting mode.
234 fn get_counting_mode(&self) -> CountingMode {
235 let cr1 = Self::regs_gp16().cr1().read();
236 (cr1.cms(), cr1.dir()).into()
237 }
238
239 /// Set input capture filter.
240 fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) {
241 let raw_channel = channel.index();
242 Self::regs_gp16()
243 .ccmr_input(raw_channel / 2)
244 .modify(|r| r.set_icf(raw_channel % 2, icf));
245 }
246
247 /// Clear input interrupt.
248 fn clear_input_interrupt(&self, channel: Channel) {
249 Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
250 }
251
252 /// Enable input interrupt.
253 fn enable_input_interrupt(&self, channel: Channel, enable: bool) {
254 Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
255 }
256
257 /// Set input capture prescaler.
258 fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) {
259 let raw_channel = channel.index();
260 Self::regs_gp16()
261 .ccmr_input(raw_channel / 2)
262 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
263 }
264
265 /// Set input TI selection.
266 fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) {
267 let raw_channel = channel.index();
268 Self::regs_gp16()
269 .ccmr_input(raw_channel / 2)
270 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
271 }
272
273 /// Set input capture mode.
274 fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) {
275 Self::regs_gp16().ccer().modify(|r| match mode {
276 InputCaptureMode::Rising => {
277 r.set_ccnp(channel.index(), false);
278 r.set_ccp(channel.index(), false);
279 }
280 InputCaptureMode::Falling => {
281 r.set_ccnp(channel.index(), false);
282 r.set_ccp(channel.index(), true);
283 }
284 InputCaptureMode::BothEdges => {
285 r.set_ccnp(channel.index(), true);
286 r.set_ccp(channel.index(), true);
287 }
288 });
289 }
290
291 /// Set output compare mode.
292 fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) {
293 let raw_channel: usize = channel.index();
294 Self::regs_gp16()
295 .ccmr_output(raw_channel / 2)
296 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
297 }
298
299 /// Set output polarity.
300 fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
301 Self::regs_gp16()
302 .ccer()
303 .modify(|w| w.set_ccp(channel.index(), polarity.into()));
304 }
305
306 /// Enable/disable a channel.
307 fn enable_channel(&self, channel: Channel, enable: bool) {
308 Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
309 }
310
311 /// Get enable/disable state of a channel
312 fn get_channel_enable_state(&self, channel: Channel) -> bool {
313 Self::regs_gp16().ccer().read().cce(channel.index())
314 }
315
316 /// Set compare value for a channel.
317 fn set_compare_value(&self, channel: Channel, value: u16) {
318 Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
319 }
320
321 /// Get capture value for a channel.
322 fn get_capture_value(&self, channel: Channel) -> u16 {
323 Self::regs_gp16().ccr(channel.index()).read().ccr()
324 }
325
326 /// Get compare value for a channel.
327 fn get_compare_value(&self, channel: Channel) -> u16 {
328 Self::regs_gp16().ccr(channel.index()).read().ccr()
329 }
330
331 /// Set output compare preload.
332 fn set_output_compare_preload(&self, channel: Channel, preload: bool) {
333 let channel_index = channel.index();
334 Self::regs_gp16()
335 .ccmr_output(channel_index / 2)
336 .modify(|w| w.set_ocpe(channel_index % 2, preload));
337 }
338
339 /// Get capture compare DMA selection
340 fn get_cc_dma_selection(&self) -> super::vals::Ccds {
341 Self::regs_gp16().cr2().read().ccds()
342 }
343
344 /// Set capture compare DMA selection
345 fn set_cc_dma_selection(&self, ccds: super::vals::Ccds) {
346 Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds))
347 }
348
349 /// Get capture compare DMA enable state
350 fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
351 Self::regs_gp16().dier().read().ccde(channel.index())
352 }
353
354 /// Set capture compare DMA enable state
355 fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) {
356 Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
357 }
358 }
359
360 #[cfg(not(stm32l0))]
361 /// Gneral-purpose 32-bit timer instance.
362 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
363 /// Get access to the general purpose 32bit timer registers.
364 ///
365 /// Note: This works even if the timer is more capable, because registers
366 /// for the less capable timers are a subset. This allows writing a driver
367 /// for a given set of capabilities, and having it transparently work with
368 /// more capable timers.
369 fn regs_gp32() -> crate::pac::timer::TimGp32;
370
371 /// Set timer frequency.
372 fn set_frequency(&self, frequency: Hertz) {
373 let f = frequency.0;
374 assert!(f > 0);
375 let timer_f = Self::frequency().0;
376 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
377 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into());
378 let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into());
379
380 let regs = Self::regs_gp32();
381 regs.psc().write(|r| r.set_psc(psc));
382 regs.arr().write_value(arr);
383
384 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
385 regs.egr().write(|r| r.set_ug(true));
386 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
387 }
388
389 /// Get timer frequency.
390 fn get_frequency(&self) -> Hertz {
391 let timer_f = Self::frequency();
392
393 let regs = Self::regs_gp32();
394 let arr = regs.arr().read();
395 let psc = regs.psc().read().psc();
396
397 timer_f / arr / (psc + 1)
398 }
399
400 /// Set comapre value for a channel.
401 fn set_compare_value(&self, channel: Channel, value: u32) {
402 Self::regs_gp32().ccr(channel.index()).write_value(value);
403 }
404
405 /// Get capture value for a channel.
406 fn get_capture_value(&self, channel: Channel) -> u32 {
407 Self::regs_gp32().ccr(channel.index()).read()
408 }
409
410 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
411 fn get_max_compare_value(&self) -> u32 {
412 Self::regs_gp32().arr().read()
413 }
414
415 /// Get compare value for a channel.
416 fn get_compare_value(&self, channel: Channel) -> u32 {
417 Self::regs_gp32().ccr(channel.index()).read()
418 }
419 }
420
421 #[cfg(not(stm32l0))]
422 /// Gneral-purpose 1 channel with one complementary 16-bit timer instance.
423 pub trait GeneralPurpose1ChannelComplementaryInstance: BasicNoCr2Instance + GeneralPurpose1ChannelInstance {
424 /// Get access to the general purpose 1 channel with one complementary 16bit timer registers.
425 ///
426 /// Note: This works even if the timer is more capable, because registers
427 /// for the less capable timers are a subset. This allows writing a driver
428 /// for a given set of capabilities, and having it transparently work with
429 /// more capable timers.
430 fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp;
431
432 /// Set clock divider for the dead time.
433 fn set_dead_time_clock_division(&self, value: vals::Ckd) {
434 Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value));
435 }
436
437 /// Set dead time, as a fraction of the max duty value.
438 fn set_dead_time_value(&self, value: u8) {
439 Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value));
440 }
441
442 /// Set state of MOE-bit in BDTR register to en-/disable output
443 fn set_moe(&self, enable: bool) {
444 Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable));
445 }
446 }
447
448 #[cfg(not(stm32l0))]
449 /// Gneral-purpose 2 channel with one complementary 16-bit timer instance.
450 pub trait GeneralPurpose2ChannelComplementaryInstance:
451 BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance
452 {
453 /// Get access to the general purpose 2 channel with one complementary 16bit timer registers.
454 ///
455 /// Note: This works even if the timer is more capable, because registers
456 /// for the less capable timers are a subset. This allows writing a driver
457 /// for a given set of capabilities, and having it transparently work with
458 /// more capable timers.
459 fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp;
460 }
461
462 #[cfg(not(stm32l0))]
463 /// Advanced control timer instance.
464 pub trait AdvancedControlInstance:
465 GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
466 {
467 /// Capture compare interrupt for this timer.
468 type CaptureCompareInterrupt: interrupt::typelevel::Interrupt;
469
470 /// Get access to the advanced timer registers.
471 fn regs_advanced() -> crate::pac::timer::TimAdv;
472
473 /// Set complementary output polarity.
474 fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
475 Self::regs_advanced()
476 .ccer()
477 .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
478 }
479
480 /// Enable/disable a complementary channel.
481 fn enable_complementary_channel(&self, channel: Channel, enable: bool) {
482 Self::regs_advanced()
483 .ccer()
484 .modify(|w| w.set_ccne(channel.index(), enable));
485 }
486 }
487}
488 11
489/// Timer channel. 12/// Timer channel.
490#[derive(Clone, Copy)] 13#[derive(Clone, Copy)]
@@ -511,181 +34,44 @@ impl Channel {
511 } 34 }
512} 35}
513 36
514/// Input capture mode. 37/// Amount of bits of a timer.
515#[derive(Clone, Copy)] 38#[derive(Clone, Copy, PartialEq, Eq, Debug)]
516pub enum InputCaptureMode { 39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
517 /// Rising edge only. 40pub enum TimerBits {
518 Rising, 41 /// 16 bits.
519 /// Falling edge only. 42 Bits16,
520 Falling, 43 /// 32 bits.
521 /// Both rising or falling edges. 44 #[cfg(not(stm32l0))]
522 BothEdges, 45 Bits32,
523} 46}
524 47
525/// Input TI selection. 48/// Core timer instance.
526#[derive(Clone, Copy)] 49pub trait CoreInstance: RccPeripheral + 'static {
527pub enum InputTISelection { 50 /// Interrupt for this timer.
528 /// Normal 51 type Interrupt: interrupt::typelevel::Interrupt;
529 Normal,
530 /// Alternate
531 Alternate,
532 /// TRC
533 TRC,
534}
535 52
536impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs { 53 /// Amount of bits this timer has.
537 fn from(tisel: InputTISelection) -> Self { 54 const BITS: TimerBits;
538 match tisel {
539 InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4,
540 InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3,
541 InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC,
542 }
543 }
544}
545 55
546/// Timer counting mode. 56 /// Registers for this timer.
547#[repr(u8)]
548#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
549pub enum CountingMode {
550 #[default]
551 /// The timer counts up to the reload value and then resets back to 0.
552 EdgeAlignedUp,
553 /// The timer counts down to 0 and then resets back to the reload value.
554 EdgeAlignedDown,
555 /// The timer counts up to the reload value and then counts back to 0.
556 /// 57 ///
557 /// The output compare interrupt flags of channels configured in output are 58 /// This is a raw pointer to the register block. The actual register block layout varies depending on the timer type.
558 /// set when the counter is counting down. 59 fn regs() -> *mut ();
559 CenterAlignedDownInterrupts,
560 /// The timer counts up to the reload value and then counts back to 0.
561 ///
562 /// The output compare interrupt flags of channels configured in output are
563 /// set when the counter is counting up.
564 CenterAlignedUpInterrupts,
565 /// The timer counts up to the reload value and then counts back to 0.
566 ///
567 /// The output compare interrupt flags of channels configured in output are
568 /// set when the counter is counting both up or down.
569 CenterAlignedBothInterrupts,
570}
571
572impl CountingMode {
573 /// Return whether this mode is edge-aligned (up or down).
574 pub fn is_edge_aligned(&self) -> bool {
575 matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown)
576 }
577
578 /// Return whether this mode is center-aligned.
579 pub fn is_center_aligned(&self) -> bool {
580 matches!(
581 self,
582 CountingMode::CenterAlignedDownInterrupts
583 | CountingMode::CenterAlignedUpInterrupts
584 | CountingMode::CenterAlignedBothInterrupts
585 )
586 }
587}
588
589impl From<CountingMode> for (vals::Cms, vals::Dir) {
590 fn from(value: CountingMode) -> Self {
591 match value {
592 CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP),
593 CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN),
594 CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP),
595 CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP),
596 CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP),
597 }
598 }
599}
600
601impl From<(vals::Cms, vals::Dir)> for CountingMode {
602 fn from(value: (vals::Cms, vals::Dir)) -> Self {
603 match value {
604 (vals::Cms::EDGEALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp,
605 (vals::Cms::EDGEALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown,
606 (vals::Cms::CENTERALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts,
607 (vals::Cms::CENTERALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts,
608 (vals::Cms::CENTERALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts,
609 }
610 }
611}
612
613/// Output compare mode.
614#[derive(Clone, Copy)]
615pub enum OutputCompareMode {
616 /// The comparison between the output compare register TIMx_CCRx and
617 /// the counter TIMx_CNT has no effect on the outputs.
618 /// (this mode is used to generate a timing base).
619 Frozen,
620 /// Set channel to active level on match. OCxREF signal is forced high when the
621 /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
622 ActiveOnMatch,
623 /// Set channel to inactive level on match. OCxREF signal is forced low when the
624 /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
625 InactiveOnMatch,
626 /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx.
627 Toggle,
628 /// Force inactive level - OCxREF is forced low.
629 ForceInactive,
630 /// Force active level - OCxREF is forced high.
631 ForceActive,
632 /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRx
633 /// else inactive. In downcounting, channel is inactive (OCxREF=0) as long as
634 /// TIMx_CNT>TIMx_CCRx else active (OCxREF=1).
635 PwmMode1,
636 /// PWM mode 2 - In upcounting, channel is inactive as long as
637 /// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as
638 /// TIMx_CNT>TIMx_CCRx else inactive.
639 PwmMode2,
640 // TODO: there's more modes here depending on the chip family.
641}
642
643impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
644 fn from(mode: OutputCompareMode) -> Self {
645 match mode {
646 OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN,
647 OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH,
648 OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH,
649 OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE,
650 OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE,
651 OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE,
652 OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1,
653 OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2,
654 }
655 }
656} 60}
61/// Cut-down basic timer instance.
62pub trait BasicNoCr2Instance: CoreInstance {}
63/// Basic timer instance.
64pub trait BasicInstance: BasicNoCr2Instance {}
657 65
658/// Timer output pin polarity. 66/// General-purpose 16-bit timer with 1 channel instance.
659#[derive(Clone, Copy)] 67pub trait GeneralInstance1Channel: CoreInstance {}
660pub enum OutputPolarity {
661 /// Active high (higher duty value makes the pin spend more time high).
662 ActiveHigh,
663 /// Active low (higher duty value makes the pin spend more time low).
664 ActiveLow,
665}
666 68
667impl From<OutputPolarity> for bool { 69/// General-purpose 16-bit timer with 2 channels instance.
668 fn from(mode: OutputPolarity) -> Self { 70pub trait GeneralInstance2Channel: GeneralInstance1Channel {}
669 match mode {
670 OutputPolarity::ActiveHigh => false,
671 OutputPolarity::ActiveLow => true,
672 }
673 }
674}
675 71
676/// Basic 16-bit timer instance. 72/// General-purpose 16-bit timer with 4 channels instance.
677pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {} 73pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel {
678 74 // SimplePwm<'d, T> is implemented for T: GeneralInstance4Channel
679// It's just a General-purpose 16-bit timer instance.
680/// Capture Compare timer instance.
681pub trait CaptureCompare16bitInstance:
682 BasicInstance
683 + sealed::GeneralPurpose2ChannelInstance
684 + sealed::GeneralPurpose1ChannelInstance
685 + sealed::GeneralPurpose16bitInstance
686 + 'static
687{
688 // SimplePwm<'d, T> is implemented for T: CaptureCompare16bitInstance
689 // Advanced timers implement this trait, but the output needs to be 75 // Advanced timers implement this trait, but the output needs to be
690 // enabled explicitly. 76 // enabled explicitly.
691 // To support general-purpose and advanced timers, this function is added 77 // To support general-purpose and advanced timers, this function is added
@@ -694,296 +80,149 @@ pub trait CaptureCompare16bitInstance:
694 fn enable_outputs(&self) {} 80 fn enable_outputs(&self) {}
695} 81}
696 82
697#[cfg(not(stm32l0))] 83/// General-purpose 32-bit timer with 4 channels instance.
698// It's just a General-purpose 32-bit timer instance. 84pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {}
699/// Capture Compare 32-bit timer instance.
700pub trait CaptureCompare32bitInstance:
701 CaptureCompare16bitInstance + sealed::GeneralPurpose32bitInstance + 'static
702{
703}
704
705#[cfg(not(stm32l0))]
706// It's just a Advanced Control timer instance.
707/// Complementary Capture Compare 32-bit timer instance.
708pub trait ComplementaryCaptureCompare16bitInstance:
709 CaptureCompare16bitInstance
710 + sealed::GeneralPurpose1ChannelComplementaryInstance
711 + sealed::GeneralPurpose2ChannelComplementaryInstance
712 + sealed::AdvancedControlInstance
713 + 'static
714{
715}
716
717pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
718pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
719pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
720pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
721pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
722
723cfg_if::cfg_if! {
724 if #[cfg(not(stm32l0))] {
725 pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
726 pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
727 pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
728 pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
729
730 pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance);
731 pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance);
732 85
733 pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance); 86/// Advanced 16-bit timer with 1 channel instance.
734 pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance); 87pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel {
735 88 /// Capture compare interrupt for this timer.
736 pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance); 89 type CaptureCompareInterrupt: interrupt::typelevel::Interrupt;
737 pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance);
738 }
739} 90}
91/// Advanced 16-bit timer with 2 channels instance.
740 92
741#[allow(unused)] 93pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {}
742macro_rules! impl_core_timer {
743 ($inst:ident, $irq:ident) => {
744 impl sealed::CoreInstance for crate::peripherals::$inst {
745 type Interrupt = crate::interrupt::typelevel::$irq;
746 94
747 fn regs_core() -> crate::pac::timer::TimCore { 95/// Advanced 16-bit timer with 4 channels instance.
748 unsafe { crate::pac::timer::TimCore::from_ptr(crate::pac::$inst.as_ptr()) } 96pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
749 }
750 }
751 };
752}
753 97
754#[allow(unused)] 98pin_trait!(Channel1Pin, GeneralInstance4Channel);
755macro_rules! impl_basic_no_cr2_timer { 99pin_trait!(Channel2Pin, GeneralInstance4Channel);
756 ($inst:ident) => { 100pin_trait!(Channel3Pin, GeneralInstance4Channel);
757 impl sealed::BasicNoCr2Instance for crate::peripherals::$inst { 101pin_trait!(Channel4Pin, GeneralInstance4Channel);
758 fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2 { 102pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
759 unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(crate::pac::$inst.as_ptr()) }
760 }
761 }
762 };
763}
764 103
765#[allow(unused)] 104pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel);
766macro_rules! impl_basic_timer { 105pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel);
767 ($inst:ident) => { 106pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel);
768 impl sealed::BasicInstance for crate::peripherals::$inst { 107pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel);
769 fn regs_basic() -> crate::pac::timer::TimBasic {
770 unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) }
771 }
772 }
773 };
774}
775 108
776#[allow(unused)] 109pin_trait!(BreakInputPin, AdvancedInstance4Channel);
777macro_rules! impl_1ch_timer { 110pin_trait!(BreakInput2Pin, AdvancedInstance4Channel);
778 ($inst:ident) => {
779 impl sealed::GeneralPurpose1ChannelInstance for crate::peripherals::$inst {
780 fn regs_1ch() -> crate::pac::timer::Tim1ch {
781 unsafe { crate::pac::timer::Tim1ch::from_ptr(crate::pac::$inst.as_ptr()) }
782 }
783 }
784 };
785}
786 111
787#[allow(unused)] 112pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel);
788macro_rules! impl_2ch_timer { 113pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel);
789 ($inst:ident) => {
790 impl sealed::GeneralPurpose2ChannelInstance for crate::peripherals::$inst {
791 fn regs_2ch() -> crate::pac::timer::Tim2ch {
792 unsafe { crate::pac::timer::Tim2ch::from_ptr(crate::pac::$inst.as_ptr()) }
793 }
794 }
795 };
796}
797 114
798#[allow(unused)] 115pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel);
799macro_rules! impl_gp16_timer { 116pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel);
800 ($inst:ident) => {
801 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
802 fn regs_gp16() -> crate::pac::timer::TimGp16 {
803 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
804 }
805 }
806 };
807}
808 117
809#[allow(unused)] 118// Update Event trigger DMA for every timer
810macro_rules! impl_gp32_timer { 119dma_trait!(UpDma, BasicInstance);
811 ($inst:ident) => {
812 impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst {
813 fn regs_gp32() -> crate::pac::timer::TimGp32 {
814 crate::pac::$inst
815 }
816 }
817 };
818}
819 120
820#[allow(unused)] 121dma_trait!(Ch1Dma, GeneralInstance4Channel);
821macro_rules! impl_1ch_cmp_timer { 122dma_trait!(Ch2Dma, GeneralInstance4Channel);
822 ($inst:ident) => { 123dma_trait!(Ch3Dma, GeneralInstance4Channel);
823 impl sealed::GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst { 124dma_trait!(Ch4Dma, GeneralInstance4Channel);
824 fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp {
825 unsafe { crate::pac::timer::Tim1chCmp::from_ptr(crate::pac::$inst.as_ptr()) }
826 }
827 }
828 };
829}
830 125
831#[allow(unused)] 126#[allow(unused)]
832macro_rules! impl_2ch_cmp_timer { 127macro_rules! impl_core_timer {
833 ($inst:ident) => { 128 ($inst:ident, $bits:expr) => {
834 impl sealed::GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst { 129 impl CoreInstance for crate::peripherals::$inst {
835 fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp { 130 type Interrupt = crate::_generated::peripheral_interrupts::$inst::UP;
836 unsafe { crate::pac::timer::Tim2chCmp::from_ptr(crate::pac::$inst.as_ptr()) }
837 }
838 }
839 };
840}
841 131
842#[allow(unused)] 132 const BITS: TimerBits = $bits;
843macro_rules! impl_adv_timer {
844 ($inst:ident, $irq:ident) => {
845 impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
846 type CaptureCompareInterrupt = crate::interrupt::typelevel::$irq;
847 133
848 fn regs_advanced() -> crate::pac::timer::TimAdv { 134 fn regs() -> *mut () {
849 unsafe { crate::pac::timer::TimAdv::from_ptr(crate::pac::$inst.as_ptr()) } 135 crate::pac::$inst.as_ptr()
850 } 136 }
851 } 137 }
852 }; 138 };
853} 139}
854 140
855foreach_interrupt! { 141foreach_interrupt! {
856
857 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { 142 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
858 impl_core_timer!($inst, $irq); 143 impl_core_timer!($inst, TimerBits::Bits16);
859 impl_basic_no_cr2_timer!($inst); 144 impl BasicNoCr2Instance for crate::peripherals::$inst {}
860 impl_basic_timer!($inst);
861 impl BasicInstance for crate::peripherals::$inst {} 145 impl BasicInstance for crate::peripherals::$inst {}
862 }; 146 };
863 147
864 ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { 148 ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
865 impl_core_timer!($inst, $irq); 149 impl_core_timer!($inst, TimerBits::Bits16);
866 impl_basic_no_cr2_timer!($inst); 150 impl BasicNoCr2Instance for crate::peripherals::$inst {}
867 impl_basic_timer!($inst);
868 impl_1ch_timer!($inst);
869 impl_2ch_timer!($inst);
870 impl_gp16_timer!($inst);
871 impl BasicInstance for crate::peripherals::$inst {} 151 impl BasicInstance for crate::peripherals::$inst {}
872 impl CaptureCompare16bitInstance for crate::peripherals::$inst {} 152 impl GeneralInstance1Channel for crate::peripherals::$inst {}
153 impl GeneralInstance2Channel for crate::peripherals::$inst {}
154 impl GeneralInstance4Channel for crate::peripherals::$inst {}
873 }; 155 };
874 156
875
876 ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { 157 ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
877 impl_core_timer!($inst, $irq); 158 impl_core_timer!($inst, TimerBits::Bits16);
878 impl_basic_no_cr2_timer!($inst); 159 impl BasicNoCr2Instance for crate::peripherals::$inst {}
879 impl_basic_timer!($inst);
880 impl_1ch_timer!($inst);
881 impl_2ch_timer!($inst);
882 impl_gp16_timer!($inst);
883 impl BasicInstance for crate::peripherals::$inst {} 160 impl BasicInstance for crate::peripherals::$inst {}
884 impl CaptureCompare16bitInstance for crate::peripherals::$inst {} 161 impl GeneralInstance1Channel for crate::peripherals::$inst {}
162 impl GeneralInstance2Channel for crate::peripherals::$inst {}
163 impl GeneralInstance4Channel for crate::peripherals::$inst {}
885 }; 164 };
886 165
887 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { 166 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
888 impl_core_timer!($inst, $irq); 167 impl_core_timer!($inst, TimerBits::Bits16);
889 impl_basic_no_cr2_timer!($inst); 168 impl BasicNoCr2Instance for crate::peripherals::$inst {}
890 impl_basic_timer!($inst);
891 impl_1ch_timer!($inst);
892 impl_2ch_timer!($inst);
893 impl_gp16_timer!($inst);
894 impl BasicInstance for crate::peripherals::$inst {} 169 impl BasicInstance for crate::peripherals::$inst {}
895 impl CaptureCompare16bitInstance for crate::peripherals::$inst {} 170 impl GeneralInstance1Channel for crate::peripherals::$inst {}
171 impl GeneralInstance2Channel for crate::peripherals::$inst {}
172 impl GeneralInstance4Channel for crate::peripherals::$inst {}
896 }; 173 };
897 174
898 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { 175 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
899 impl_core_timer!($inst, $irq); 176 impl_core_timer!($inst, TimerBits::Bits32);
900 impl_basic_no_cr2_timer!($inst); 177 impl BasicNoCr2Instance for crate::peripherals::$inst {}
901 impl_basic_timer!($inst);
902 impl_1ch_timer!($inst);
903 impl_2ch_timer!($inst);
904 impl_gp16_timer!($inst);
905 impl_gp32_timer!($inst);
906 impl BasicInstance for crate::peripherals::$inst {} 178 impl BasicInstance for crate::peripherals::$inst {}
907 impl CaptureCompare16bitInstance for crate::peripherals::$inst {} 179 impl GeneralInstance1Channel for crate::peripherals::$inst {}
908 impl CaptureCompare32bitInstance for crate::peripherals::$inst {} 180 impl GeneralInstance2Channel for crate::peripherals::$inst {}
181 impl GeneralInstance4Channel for crate::peripherals::$inst {}
182 impl GeneralInstance32bit4Channel for crate::peripherals::$inst {}
909 }; 183 };
910 184
911 ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { 185 ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
912 impl_core_timer!($inst, $irq); 186 impl_core_timer!($inst, TimerBits::Bits16);
913 impl_basic_no_cr2_timer!($inst); 187 impl BasicNoCr2Instance for crate::peripherals::$inst {}
914 impl_basic_timer!($inst);
915 impl_1ch_timer!($inst);
916 impl_2ch_timer!($inst);
917 impl_gp16_timer!($inst);
918 impl_1ch_cmp_timer!($inst);
919 impl_2ch_cmp_timer!($inst);
920 impl BasicInstance for crate::peripherals::$inst {} 188 impl BasicInstance for crate::peripherals::$inst {}
921 impl CaptureCompare16bitInstance for crate::peripherals::$inst { 189 impl GeneralInstance1Channel for crate::peripherals::$inst {}
922 /// Enable timer outputs. 190 impl GeneralInstance2Channel for crate::peripherals::$inst {}
923 fn enable_outputs(&self) { 191 impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }}
924 use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; 192 impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; }
925 self.set_moe(true); 193 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
926 } 194 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
927 }
928 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
929 };
930 ($inst:ident, timer, TIM_1CH_CMP, CC, $irq:ident) => {
931 impl_adv_timer!($inst, $irq);
932 }; 195 };
933 196
934
935 ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { 197 ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => {
936 impl_core_timer!($inst, $irq); 198 impl_core_timer!($inst, TimerBits::Bits16);
937 impl_basic_no_cr2_timer!($inst); 199 impl BasicNoCr2Instance for crate::peripherals::$inst {}
938 impl_basic_timer!($inst);
939 impl_1ch_timer!($inst);
940 impl_2ch_timer!($inst);
941 impl_gp16_timer!($inst);
942 impl_1ch_cmp_timer!($inst);
943 impl_2ch_cmp_timer!($inst);
944 impl BasicInstance for crate::peripherals::$inst {} 200 impl BasicInstance for crate::peripherals::$inst {}
945 impl CaptureCompare16bitInstance for crate::peripherals::$inst { 201 impl GeneralInstance1Channel for crate::peripherals::$inst {}
946 /// Enable timer outputs. 202 impl GeneralInstance2Channel for crate::peripherals::$inst {}
947 fn enable_outputs(&self) { 203 impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }}
948 use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; 204 impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; }
949 self.set_moe(true); 205 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
950 } 206 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
951 }
952 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
953 };
954 ($inst:ident, timer, TIM_2CH_CMP, CC, $irq:ident) => {
955 impl_adv_timer!($inst, $irq);
956 }; 207 };
957 208
958
959 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { 209 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
960 impl_core_timer!($inst, $irq); 210 impl_core_timer!($inst, TimerBits::Bits16);
961 impl_basic_no_cr2_timer!($inst); 211 impl BasicNoCr2Instance for crate::peripherals::$inst {}
962 impl_basic_timer!($inst);
963 impl_1ch_timer!($inst);
964 impl_2ch_timer!($inst);
965 impl_gp16_timer!($inst);
966 impl_1ch_cmp_timer!($inst);
967 impl_2ch_cmp_timer!($inst);
968 impl BasicInstance for crate::peripherals::$inst {} 212 impl BasicInstance for crate::peripherals::$inst {}
969 impl CaptureCompare16bitInstance for crate::peripherals::$inst { 213 impl GeneralInstance1Channel for crate::peripherals::$inst {}
970 /// Enable timer outputs. 214 impl GeneralInstance2Channel for crate::peripherals::$inst {}
971 fn enable_outputs(&self) { 215 impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }}
972 use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; 216 impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; }
973 self.set_moe(true); 217 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
974 } 218 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
975 }
976 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
977 };
978 ($inst:ident, timer, TIM_ADV, CC, $irq:ident) => {
979 impl_adv_timer!($inst, $irq);
980 }; 219 };
981} 220}
982 221
983// Update Event trigger DMA for every timer 222#[cfg(not(stm32l0))]
984dma_trait!(UpDma, BasicInstance); 223#[allow(unused)]
985 224fn set_moe<T: GeneralInstance4Channel>() {
986dma_trait!(Ch1Dma, CaptureCompare16bitInstance); 225 unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) }
987dma_trait!(Ch2Dma, CaptureCompare16bitInstance); 226 .bdtr()
988dma_trait!(Ch3Dma, CaptureCompare16bitInstance); 227 .modify(|w| w.set_moe(true));
989dma_trait!(Ch4Dma, CaptureCompare16bitInstance); 228}
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 59efb72ba..ab9879be6 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -3,10 +3,11 @@
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
5use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use stm32_metapac::timer::vals;
6 7
7use super::*; 8use super::low_level::Timer;
8use crate::gpio::sealed::AFType; 9use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel};
9use crate::gpio::AnyPin; 10use crate::gpio::{AFType, AnyPin};
10use crate::Peripheral; 11use crate::Peripheral;
11 12
12/// Counting direction 13/// Counting direction
@@ -30,7 +31,7 @@ pub struct QeiPin<'d, T, Channel> {
30 31
31macro_rules! channel_impl { 32macro_rules! channel_impl {
32 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 33 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
33 impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> { 34 impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> {
34 #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] 35 #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
35 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self { 36 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self {
36 into_ref!(pin); 37 into_ref!(pin);
@@ -53,29 +54,28 @@ channel_impl!(new_ch1, Ch1, Channel1Pin);
53channel_impl!(new_ch2, Ch2, Channel2Pin); 54channel_impl!(new_ch2, Ch2, Channel2Pin);
54 55
55/// Quadrature decoder driver. 56/// Quadrature decoder driver.
56pub struct Qei<'d, T> { 57pub struct Qei<'d, T: GeneralInstance4Channel> {
57 _inner: PeripheralRef<'d, T>, 58 inner: Timer<'d, T>,
58} 59}
59 60
60impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { 61impl<'d, T: GeneralInstance4Channel> Qei<'d, T> {
61 /// Create a new quadrature decoder driver. 62 /// Create a new quadrature decoder driver.
62 pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { 63 pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
63 Self::new_inner(tim) 64 Self::new_inner(tim)
64 } 65 }
65 66
66 fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self { 67 fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self {
67 into_ref!(tim); 68 let inner = Timer::new(tim);
68 69 let r = inner.regs_gp16();
69 T::enable_and_reset();
70 70
71 // Configure TxC1 and TxC2 as captures 71 // Configure TxC1 and TxC2 as captures
72 T::regs_gp16().ccmr_input(0).modify(|w| { 72 r.ccmr_input(0).modify(|w| {
73 w.set_ccs(0, vals::CcmrInputCcs::TI4); 73 w.set_ccs(0, vals::CcmrInputCcs::TI4);
74 w.set_ccs(1, vals::CcmrInputCcs::TI4); 74 w.set_ccs(1, vals::CcmrInputCcs::TI4);
75 }); 75 });
76 76
77 // enable and configure to capture on rising edge 77 // enable and configure to capture on rising edge
78 T::regs_gp16().ccer().modify(|w| { 78 r.ccer().modify(|w| {
79 w.set_cce(0, true); 79 w.set_cce(0, true);
80 w.set_cce(1, true); 80 w.set_cce(1, true);
81 81
@@ -83,19 +83,19 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
83 w.set_ccp(1, false); 83 w.set_ccp(1, false);
84 }); 84 });
85 85
86 T::regs_gp16().smcr().modify(|w| { 86 r.smcr().modify(|w| {
87 w.set_sms(vals::Sms::ENCODER_MODE_3); 87 w.set_sms(vals::Sms::ENCODER_MODE_3);
88 }); 88 });
89 89
90 T::regs_gp16().arr().modify(|w| w.set_arr(u16::MAX)); 90 r.arr().modify(|w| w.set_arr(u16::MAX));
91 T::regs_gp16().cr1().modify(|w| w.set_cen(true)); 91 r.cr1().modify(|w| w.set_cen(true));
92 92
93 Self { _inner: tim } 93 Self { inner }
94 } 94 }
95 95
96 /// Get direction. 96 /// Get direction.
97 pub fn read_direction(&self) -> Direction { 97 pub fn read_direction(&self) -> Direction {
98 match T::regs_gp16().cr1().read().dir() { 98 match self.inner.regs_gp16().cr1().read().dir() {
99 vals::Dir::DOWN => Direction::Downcounting, 99 vals::Dir::DOWN => Direction::Downcounting,
100 vals::Dir::UP => Direction::Upcounting, 100 vals::Dir::UP => Direction::Upcounting,
101 } 101 }
@@ -103,6 +103,6 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
103 103
104 /// Get count. 104 /// Get count.
105 pub fn count(&self) -> u16 { 105 pub fn count(&self) -> u16 {
106 T::regs_gp16().cnt().read().cnt() 106 self.inner.regs_gp16().cnt().read().cnt()
107 } 107 }
108} 108}
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 6df2f66ec..b54e9a0d6 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -4,9 +4,8 @@ use core::marker::PhantomData;
4 4
5use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6 6
7use super::*; 7use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
8#[allow(unused_imports)] 8use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel};
9use crate::gpio::sealed::{AFType, Pin};
10use crate::gpio::{AnyPin, OutputType}; 9use crate::gpio::{AnyPin, OutputType};
11use crate::time::Hertz; 10use crate::time::Hertz;
12use crate::Peripheral; 11use crate::Peripheral;
@@ -30,7 +29,7 @@ pub struct PwmPin<'d, T, C> {
30 29
31macro_rules! channel_impl { 30macro_rules! channel_impl {
32 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 31 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
33 impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> { 32 impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> {
34 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] 33 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
35 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self { 34 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
36 into_ref!(pin); 35 into_ref!(pin);
@@ -55,11 +54,11 @@ channel_impl!(new_ch3, Ch3, Channel3Pin);
55channel_impl!(new_ch4, Ch4, Channel4Pin); 54channel_impl!(new_ch4, Ch4, Channel4Pin);
56 55
57/// Simple PWM driver. 56/// Simple PWM driver.
58pub struct SimplePwm<'d, T> { 57pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
59 inner: PeripheralRef<'d, T>, 58 inner: Timer<'d, T>,
60} 59}
61 60
62impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { 61impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
63 /// Create a new simple PWM driver. 62 /// Create a new simple PWM driver.
64 pub fn new( 63 pub fn new(
65 tim: impl Peripheral<P = T> + 'd, 64 tim: impl Peripheral<P = T> + 'd,
@@ -74,15 +73,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
74 } 73 }
75 74
76 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { 75 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
77 into_ref!(tim); 76 let mut this = Self { inner: Timer::new(tim) };
78
79 T::enable_and_reset();
80
81 let mut this = Self { inner: tim };
82 77
83 this.inner.set_counting_mode(counting_mode); 78 this.inner.set_counting_mode(counting_mode);
84 this.set_frequency(freq); 79 this.set_frequency(freq);
85 this.inner.enable_outputs(); // Required for advanced timers, see CaptureCompare16bitInstance for details 80 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
86 this.inner.start(); 81 this.inner.start();
87 82
88 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] 83 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
@@ -127,14 +122,14 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
127 /// Get max duty value. 122 /// Get max duty value.
128 /// 123 ///
129 /// This value depends on the configured frequency and the timer's clock rate from RCC. 124 /// This value depends on the configured frequency and the timer's clock rate from RCC.
130 pub fn get_max_duty(&self) -> u16 { 125 pub fn get_max_duty(&self) -> u32 {
131 self.inner.get_max_compare_value() + 1 126 self.inner.get_max_compare_value() + 1
132 } 127 }
133 128
134 /// Set the duty for a given channel. 129 /// Set the duty for a given channel.
135 /// 130 ///
136 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. 131 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
137 pub fn set_duty(&mut self, channel: Channel, duty: u16) { 132 pub fn set_duty(&mut self, channel: Channel, duty: u32) {
138 assert!(duty <= self.get_max_duty()); 133 assert!(duty <= self.get_max_duty());
139 self.inner.set_compare_value(channel, duty) 134 self.inner.set_compare_value(channel, duty)
140 } 135 }
@@ -142,7 +137,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
142 /// Get the duty for a given channel. 137 /// Get the duty for a given channel.
143 /// 138 ///
144 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. 139 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
145 pub fn get_duty(&self, channel: Channel) -> u16 { 140 pub fn get_duty(&self, channel: Channel) -> u32 {
146 self.inner.get_compare_value(channel) 141 self.inner.get_compare_value(channel)
147 } 142 }
148 143
@@ -166,8 +161,6 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
166 channel: Channel, 161 channel: Channel,
167 duty: &[u16], 162 duty: &[u16],
168 ) { 163 ) {
169 assert!(duty.iter().all(|v| *v <= self.get_max_duty()));
170
171 into_ref!(dma); 164 into_ref!(dma);
172 165
173 #[allow(clippy::let_unit_value)] // eg. stm32f334 166 #[allow(clippy::let_unit_value)] // eg. stm32f334
@@ -202,7 +195,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
202 &mut dma, 195 &mut dma,
203 req, 196 req,
204 duty, 197 duty,
205 T::regs_1ch().ccr(channel.index()).as_ptr() as *mut _, 198 self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut _,
206 dma_transfer_option, 199 dma_transfer_option,
207 ) 200 )
208 .await 201 .await
@@ -228,22 +221,20 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
228 221
229macro_rules! impl_waveform_chx { 222macro_rules! impl_waveform_chx {
230 ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { 223 ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => {
231 impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { 224 impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
232 /// Generate a sequence of PWM waveform 225 /// Generate a sequence of PWM waveform
233 /// 226 ///
234 /// Note: 227 /// Note:
235 /// you will need to provide corresponding TIMx_CHy DMA channel to use this method. 228 /// you will need to provide corresponding TIMx_CHy DMA channel to use this method.
236 pub async fn $fn_name(&mut self, dma: impl Peripheral<P = impl super::$dma_ch<T>>, duty: &[u16]) { 229 pub async fn $fn_name(&mut self, dma: impl Peripheral<P = impl super::$dma_ch<T>>, duty: &[u16]) {
237 use super::vals::Ccds; 230 use crate::pac::timer::vals::Ccds;
238
239 assert!(duty.iter().all(|v| *v <= self.get_max_duty()));
240 231
241 into_ref!(dma); 232 into_ref!(dma);
242 233
243 #[allow(clippy::let_unit_value)] // eg. stm32f334 234 #[allow(clippy::let_unit_value)] // eg. stm32f334
244 let req = dma.request(); 235 let req = dma.request();
245 236
246 let cc_channel = super::Channel::$cc_ch; 237 let cc_channel = Channel::$cc_ch;
247 238
248 let original_duty_state = self.get_duty(cc_channel); 239 let original_duty_state = self.get_duty(cc_channel);
249 let original_enable_state = self.is_enabled(cc_channel); 240 let original_enable_state = self.is_enabled(cc_channel);
@@ -280,7 +271,7 @@ macro_rules! impl_waveform_chx {
280 &mut dma, 271 &mut dma,
281 req, 272 req,
282 duty, 273 duty,
283 T::regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, 274 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _,
284 dma_transfer_option, 275 dma_transfer_option,
285 ) 276 )
286 .await 277 .await
@@ -315,10 +306,10 @@ impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2);
315impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3); 306impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3);
316impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4); 307impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4);
317 308
318impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> { 309impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> {
319 type Channel = Channel; 310 type Channel = Channel;
320 type Time = Hertz; 311 type Time = Hertz;
321 type Duty = u16; 312 type Duty = u32;
322 313
323 fn disable(&mut self, channel: Self::Channel) { 314 fn disable(&mut self, channel: Self::Channel) {
324 self.inner.enable_channel(channel, false); 315 self.inner.enable_channel(channel, false);
diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs
index 9c37d2c04..fe614b811 100644
--- a/embassy-stm32/src/ucpd.rs
+++ b/embassy-stm32/src/ucpd.rs
@@ -16,11 +16,12 @@
16 16
17use core::future::poll_fn; 17use core::future::poll_fn;
18use core::marker::PhantomData; 18use core::marker::PhantomData;
19use core::sync::atomic::Ordering; 19use core::sync::atomic::{AtomicBool, Ordering};
20use core::task::Poll; 20use core::task::Poll;
21 21
22use embassy_hal_internal::drop::OnDrop; 22use embassy_hal_internal::drop::OnDrop;
23use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 23use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
24use embassy_sync::waitqueue::AtomicWaker;
24 25
25use crate::dma::{AnyChannel, Request, Transfer, TransferOptions}; 26use crate::dma::{AnyChannel, Request, Transfer, TransferOptions};
26use crate::interrupt; 27use crate::interrupt;
@@ -555,50 +556,47 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
555 } 556 }
556} 557}
557 558
558/// UCPD instance trait. 559struct State {
559pub trait Instance: sealed::Instance + RccPeripheral {} 560 waker: AtomicWaker,
560 561 // Inverted logic for a default state of 0 so that the data goes into the .bss section.
561mod sealed { 562 drop_not_ready: AtomicBool,
562 use core::sync::atomic::AtomicBool; 563}
563
564 use embassy_sync::waitqueue::AtomicWaker;
565
566 pub struct State {
567 pub waker: AtomicWaker,
568 // Inverted logic for a default state of 0 so that the data goes into the .bss section.
569 pub drop_not_ready: AtomicBool,
570 }
571 564
572 impl State { 565impl State {
573 pub const fn new() -> Self { 566 pub const fn new() -> Self {
574 Self { 567 Self {
575 waker: AtomicWaker::new(), 568 waker: AtomicWaker::new(),
576 drop_not_ready: AtomicBool::new(false), 569 drop_not_ready: AtomicBool::new(false),
577 }
578 } 570 }
579 } 571 }
572}
580 573
581 pub trait Instance { 574trait SealedInstance {
582 type Interrupt: crate::interrupt::typelevel::Interrupt; 575 const REGS: crate::pac::ucpd::Ucpd;
583 const REGS: crate::pac::ucpd::Ucpd; 576 fn state() -> &'static State;
584 fn state() -> &'static crate::ucpd::sealed::State; 577}
585 } 578
579/// UCPD instance trait.
580#[allow(private_bounds)]
581pub trait Instance: SealedInstance + RccPeripheral {
582 /// Interrupt for this instance.
583 type Interrupt: crate::interrupt::typelevel::Interrupt;
586} 584}
587 585
588foreach_interrupt!( 586foreach_interrupt!(
589 ($inst:ident, ucpd, UCPD, GLOBAL, $irq:ident) => { 587 ($inst:ident, ucpd, UCPD, GLOBAL, $irq:ident) => {
590 impl sealed::Instance for crate::peripherals::$inst { 588 impl SealedInstance for crate::peripherals::$inst {
591 type Interrupt = crate::interrupt::typelevel::$irq;
592
593 const REGS: crate::pac::ucpd::Ucpd = crate::pac::$inst; 589 const REGS: crate::pac::ucpd::Ucpd = crate::pac::$inst;
594 590
595 fn state() -> &'static crate::ucpd::sealed::State { 591 fn state() -> &'static State {
596 static STATE: crate::ucpd::sealed::State = crate::ucpd::sealed::State::new(); 592 static STATE: State = State::new();
597 &STATE 593 &STATE
598 } 594 }
599 } 595 }
600 596
601 impl Instance for crate::peripherals::$inst {} 597 impl Instance for crate::peripherals::$inst {
598 type Interrupt = crate::interrupt::typelevel::$irq;
599 }
602 }; 600 };
603); 601);
604 602
diff --git a/embassy-stm32/src/uid.rs b/embassy-stm32/src/uid.rs
index aa13586f8..5e38532bd 100644
--- a/embassy-stm32/src/uid.rs
+++ b/embassy-stm32/src/uid.rs
@@ -27,5 +27,5 @@ pub fn uid_hex_bytes() -> &'static [u8; 24] {
27 LOADED = true; 27 LOADED = true;
28 } 28 }
29 }); 29 });
30 unsafe { &UID_HEX } 30 unsafe { &*core::ptr::addr_of!(UID_HEX) }
31} 31}
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index c11e3382f..51862e185 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -1,13 +1,10 @@
1use core::future::poll_fn;
2use core::slice; 1use core::slice;
3use core::sync::atomic::{AtomicBool, Ordering}; 2use core::sync::atomic::AtomicBool;
4use core::task::Poll;
5 3
6use embassy_hal_internal::atomic_ring_buffer::RingBuffer; 4use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
7use embassy_sync::waitqueue::AtomicWaker; 5use embassy_sync::waitqueue::AtomicWaker;
8 6
9use super::*; 7use super::*;
10use crate::interrupt::typelevel::Interrupt;
11 8
12/// Interrupt handler. 9/// Interrupt handler.
13pub struct InterruptHandler<T: BasicInstance> { 10pub struct InterruptHandler<T: BasicInstance> {
@@ -55,7 +52,7 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
55 // FIXME: Should we disable any further RX interrupts when the buffer becomes full. 52 // FIXME: Should we disable any further RX interrupts when the buffer becomes full.
56 } 53 }
57 54
58 if state.rx_buf.is_full() { 55 if !state.rx_buf.is_empty() {
59 state.rx_waker.wake(); 56 state.rx_waker.wake();
60 } 57 }
61 } 58 }
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index ea727b010..7ab33043a 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -10,10 +10,11 @@ use core::task::Poll;
10use embassy_embedded_hal::SetConfig; 10use embassy_embedded_hal::SetConfig;
11use embassy_hal_internal::drop::OnDrop; 11use embassy_hal_internal::drop::OnDrop;
12use embassy_hal_internal::{into_ref, PeripheralRef}; 12use embassy_hal_internal::{into_ref, PeripheralRef};
13use embassy_sync::waitqueue::AtomicWaker;
13use futures::future::{select, Either}; 14use futures::future::{select, Either};
14 15
15use crate::dma::{NoDma, Transfer}; 16use crate::dma::{NoDma, Transfer};
16use crate::gpio::sealed::AFType; 17use crate::gpio::AFType;
17use crate::interrupt::typelevel::Interrupt; 18use crate::interrupt::typelevel::Interrupt;
18#[allow(unused_imports)] 19#[allow(unused_imports)]
19#[cfg(not(any(usart_v1, usart_v2)))] 20#[cfg(not(any(usart_v1, usart_v2)))]
@@ -1326,8 +1327,6 @@ mod ringbuffered;
1326#[cfg(not(gpdma))] 1327#[cfg(not(gpdma))]
1327pub use ringbuffered::RingBufferedUartRx; 1328pub use ringbuffered::RingBufferedUartRx;
1328 1329
1329use self::sealed::Kind;
1330
1331#[cfg(any(usart_v1, usart_v2))] 1330#[cfg(any(usart_v1, usart_v2))]
1332fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { 1331fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
1333 r.dr().as_ptr() as _ 1332 r.dr().as_ptr() as _
@@ -1370,52 +1369,50 @@ fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
1370 r.icr().write(|w| *w = regs::Icr(sr.0)); 1369 r.icr().write(|w| *w = regs::Icr(sr.0));
1371} 1370}
1372 1371
1373pub(crate) mod sealed { 1372#[derive(Clone, Copy, PartialEq, Eq)]
1374 use embassy_sync::waitqueue::AtomicWaker; 1373enum Kind {
1375 1374 Uart,
1376 use super::*; 1375 #[cfg(any(usart_v3, usart_v4))]
1377 1376 #[allow(unused)]
1378 #[derive(Clone, Copy, PartialEq, Eq)] 1377 Lpuart,
1379 pub enum Kind { 1378}
1380 Uart,
1381 #[cfg(any(usart_v3, usart_v4))]
1382 Lpuart,
1383 }
1384 1379
1385 pub struct State { 1380struct State {
1386 pub rx_waker: AtomicWaker, 1381 rx_waker: AtomicWaker,
1387 pub tx_waker: AtomicWaker, 1382}
1388 }
1389 1383
1390 impl State { 1384impl State {
1391 pub const fn new() -> Self { 1385 const fn new() -> Self {
1392 Self { 1386 Self {
1393 rx_waker: AtomicWaker::new(), 1387 rx_waker: AtomicWaker::new(),
1394 tx_waker: AtomicWaker::new(),
1395 }
1396 } 1388 }
1397 } 1389 }
1390}
1398 1391
1399 pub trait BasicInstance: crate::rcc::RccPeripheral { 1392trait SealedBasicInstance: crate::rcc::RccPeripheral {
1400 const KIND: Kind; 1393 const KIND: Kind;
1401 type Interrupt: interrupt::typelevel::Interrupt;
1402 1394
1403 fn regs() -> Regs; 1395 fn regs() -> Regs;
1404 fn state() -> &'static State; 1396 fn state() -> &'static State;
1405 1397
1406 fn buffered_state() -> &'static buffered::State; 1398 fn buffered_state() -> &'static buffered::State;
1407 } 1399}
1408 1400
1409 pub trait FullInstance: BasicInstance { 1401trait SealedFullInstance: SealedBasicInstance {
1410 fn regs_uart() -> crate::pac::usart::Usart; 1402 #[allow(unused)]
1411 } 1403 fn regs_uart() -> crate::pac::usart::Usart;
1412} 1404}
1413 1405
1414/// Basic UART driver instance 1406/// Basic UART driver instance
1415pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {} 1407#[allow(private_bounds)]
1408pub trait BasicInstance: Peripheral<P = Self> + SealedBasicInstance + 'static + Send {
1409 /// Interrupt for this instance.
1410 type Interrupt: interrupt::typelevel::Interrupt;
1411}
1416 1412
1417/// Full UART driver instance 1413/// Full UART driver instance
1418pub trait FullInstance: sealed::FullInstance {} 1414#[allow(private_bounds)]
1415pub trait FullInstance: SealedFullInstance {}
1419 1416
1420pin_trait!(RxPin, BasicInstance); 1417pin_trait!(RxPin, BasicInstance);
1421pin_trait!(TxPin, BasicInstance); 1418pin_trait!(TxPin, BasicInstance);
@@ -1429,16 +1426,15 @@ dma_trait!(RxDma, BasicInstance);
1429 1426
1430macro_rules! impl_usart { 1427macro_rules! impl_usart {
1431 ($inst:ident, $irq:ident, $kind:expr) => { 1428 ($inst:ident, $irq:ident, $kind:expr) => {
1432 impl sealed::BasicInstance for crate::peripherals::$inst { 1429 impl SealedBasicInstance for crate::peripherals::$inst {
1433 const KIND: Kind = $kind; 1430 const KIND: Kind = $kind;
1434 type Interrupt = crate::interrupt::typelevel::$irq;
1435 1431
1436 fn regs() -> Regs { 1432 fn regs() -> Regs {
1437 unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } 1433 unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) }
1438 } 1434 }
1439 1435
1440 fn state() -> &'static crate::usart::sealed::State { 1436 fn state() -> &'static crate::usart::State {
1441 static STATE: crate::usart::sealed::State = crate::usart::sealed::State::new(); 1437 static STATE: crate::usart::State = crate::usart::State::new();
1442 &STATE 1438 &STATE
1443 } 1439 }
1444 1440
@@ -1448,7 +1444,9 @@ macro_rules! impl_usart {
1448 } 1444 }
1449 } 1445 }
1450 1446
1451 impl BasicInstance for peripherals::$inst {} 1447 impl BasicInstance for peripherals::$inst {
1448 type Interrupt = crate::interrupt::typelevel::$irq;
1449 }
1452 }; 1450 };
1453} 1451}
1454 1452
@@ -1460,7 +1458,7 @@ foreach_interrupt!(
1460 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { 1458 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
1461 impl_usart!($inst, $irq, Kind::Uart); 1459 impl_usart!($inst, $irq, Kind::Uart);
1462 1460
1463 impl sealed::FullInstance for peripherals::$inst { 1461 impl SealedFullInstance for peripherals::$inst {
1464 fn regs_uart() -> crate::pac::usart::Usart { 1462 fn regs_uart() -> crate::pac::usart::Usart {
1465 crate::pac::$inst 1463 crate::pac::$inst
1466 } 1464 }
diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs
index 4debd4e54..1e3c44167 100644
--- a/embassy-stm32/src/usb/mod.rs
+++ b/embassy-stm32/src/usb/mod.rs
@@ -1,37 +1,69 @@
1//! Universal Serial Bus (USB) 1//! Universal Serial Bus (USB)
2 2
3use crate::interrupt; 3#[cfg_attr(usb, path = "usb.rs")]
4use crate::rcc::RccPeripheral; 4#[cfg_attr(otg, path = "otg.rs")]
5mod _version;
6pub use _version::*;
5 7
6mod usb; 8use crate::interrupt::typelevel::Interrupt;
7pub use usb::*; 9use crate::rcc::SealedRccPeripheral;
8 10
9pub(crate) mod sealed { 11/// clock, power initialization stuff that's common for USB and OTG.
10 pub trait Instance { 12fn common_init<T: Instance>() {
11 fn regs() -> crate::pac::usb::Usb; 13 // Check the USB clock is enabled and running at exactly 48 MHz.
14 // frequency() will panic if not enabled
15 let freq = T::frequency();
16 // Check frequency is within the 0.25% tolerance allowed by the spec.
17 // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user
18 // has tight clock restrictions due to something else (like audio).
19 if freq.0.abs_diff(48_000_000) > 120_000 {
20 panic!(
21 "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.",
22 freq.0
23 )
12 } 24 }
13}
14 25
15/// USB instance trait. 26 #[cfg(any(stm32l4, stm32l5, stm32wb))]
16pub trait Instance: sealed::Instance + RccPeripheral + 'static { 27 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
17 /// Interrupt for this USB instance. 28
18 type Interrupt: interrupt::typelevel::Interrupt; 29 #[cfg(pwr_h5)]
19} 30 critical_section::with(|_| crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)));
31
32 #[cfg(stm32h7)]
33 {
34 // If true, VDD33USB is generated by internal regulator from VDD50USB
35 // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
36 // TODO: unhardcode
37 let internal_regulator = false;
38
39 // Enable USB power
40 critical_section::with(|_| {
41 crate::pac::PWR.cr3().modify(|w| {
42 w.set_usb33den(true);
43 w.set_usbregen(internal_regulator);
44 })
45 });
46
47 // Wait for USB power to stabilize
48 while !crate::pac::PWR.cr3().read().usb33rdy() {}
49 }
50
51 #[cfg(stm32u5)]
52 {
53 // Enable USB power
54 critical_section::with(|_| {
55 crate::pac::PWR.svmcr().modify(|w| {
56 w.set_usv(true);
57 w.set_uvmen(true);
58 })
59 });
60
61 // Wait for USB power to stabilize
62 while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
63 }
64
65 T::Interrupt::unpend();
66 unsafe { T::Interrupt::enable() };
20 67
21// Internal PHY pins 68 <T as SealedRccPeripheral>::enable_and_reset();
22pin_trait!(DpPin, Instance); 69}
23pin_trait!(DmPin, Instance);
24
25foreach_interrupt!(
26 ($inst:ident, usb, $block:ident, LP, $irq:ident) => {
27 impl sealed::Instance for crate::peripherals::$inst {
28 fn regs() -> crate::pac::usb::Usb {
29 crate::pac::$inst
30 }
31 }
32
33 impl Instance for crate::peripherals::$inst {
34 type Interrupt = crate::interrupt::typelevel::$irq;
35 }
36 };
37);
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb/otg.rs
index 373697ec8..b0e7067bd 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -6,17 +6,16 @@ use core::task::Poll;
6use embassy_hal_internal::{into_ref, Peripheral}; 6use embassy_hal_internal::{into_ref, Peripheral};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use embassy_usb_driver::{ 8use embassy_usb_driver::{
9 self, Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, 9 Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut,
10 EndpointOut, EndpointType, Event, Unsupported, 10 EndpointType, Event, Unsupported,
11}; 11};
12use futures::future::poll_fn; 12use futures::future::poll_fn;
13 13
14use super::*; 14use crate::gpio::AFType;
15use crate::gpio::sealed::AFType;
16use crate::interrupt; 15use crate::interrupt;
17use crate::interrupt::typelevel::Interrupt; 16use crate::interrupt::typelevel::Interrupt;
18use crate::pac::otg::{regs, vals}; 17use crate::pac::otg::{regs, vals};
19use crate::rcc::sealed::RccPeripheral; 18use crate::rcc::{RccPeripheral, SealedRccPeripheral};
20use crate::time::Hertz; 19use crate::time::Hertz;
21 20
22/// Interrupt handler. 21/// Interrupt handler.
@@ -561,8 +560,7 @@ impl<'d, T: Instance> Bus<'d, T> {
561 560
562impl<'d, T: Instance> Bus<'d, T> { 561impl<'d, T: Instance> Bus<'d, T> {
563 fn init(&mut self) { 562 fn init(&mut self) {
564 #[cfg(stm32l4)] 563 super::common_init::<T>();
565 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
566 564
567 #[cfg(stm32f7)] 565 #[cfg(stm32f7)]
568 { 566 {
@@ -590,22 +588,6 @@ impl<'d, T: Instance> Bus<'d, T> {
590 588
591 #[cfg(stm32h7)] 589 #[cfg(stm32h7)]
592 { 590 {
593 // If true, VDD33USB is generated by internal regulator from VDD50USB
594 // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
595 // TODO: unhardcode
596 let internal_regulator = false;
597
598 // Enable USB power
599 critical_section::with(|_| {
600 crate::pac::PWR.cr3().modify(|w| {
601 w.set_usb33den(true);
602 w.set_usbregen(internal_regulator);
603 })
604 });
605
606 // Wait for USB power to stabilize
607 while !crate::pac::PWR.cr3().read().usb33rdy() {}
608
609 // Enable ULPI clock if external PHY is used 591 // Enable ULPI clock if external PHY is used
610 let ulpien = !self.phy_type.internal(); 592 let ulpien = !self.phy_type.internal();
611 critical_section::with(|_| { 593 critical_section::with(|_| {
@@ -626,25 +608,6 @@ impl<'d, T: Instance> Bus<'d, T> {
626 }); 608 });
627 } 609 }
628 610
629 #[cfg(stm32u5)]
630 {
631 // Enable USB power
632 critical_section::with(|_| {
633 crate::pac::PWR.svmcr().modify(|w| {
634 w.set_usv(true);
635 w.set_uvmen(true);
636 })
637 });
638
639 // Wait for USB power to stabilize
640 while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
641 }
642
643 <T as RccPeripheral>::enable_and_reset();
644
645 T::Interrupt::unpend();
646 unsafe { T::Interrupt::enable() };
647
648 let r = T::regs(); 611 let r = T::regs();
649 let core_id = r.cid().read().0; 612 let core_id = r.cid().read().0;
650 trace!("Core id {:08x}", core_id); 613 trace!("Core id {:08x}", core_id);
@@ -846,7 +809,7 @@ impl<'d, T: Instance> Bus<'d, T> {
846 fn disable(&mut self) { 809 fn disable(&mut self) {
847 T::Interrupt::disable(); 810 T::Interrupt::disable();
848 811
849 <T as RccPeripheral>::disable(); 812 <T as SealedRccPeripheral>::disable();
850 813
851 #[cfg(stm32l4)] 814 #[cfg(stm32l4)]
852 crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); 815 crate::pac::PWR.cr2().modify(|w| w.set_usv(false));
@@ -1469,3 +1432,158 @@ fn calculate_trdt(speed: vals::Dspd, ahb_freq: Hertz) -> u8 {
1469fn quirk_setup_late_cnak(r: crate::pac::otg::Otg) -> bool { 1432fn quirk_setup_late_cnak(r: crate::pac::otg::Otg) -> bool {
1470 r.cid().read().0 & 0xf000 == 0x1000 1433 r.cid().read().0 & 0xf000 == 0x1000
1471} 1434}
1435
1436// Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps
1437const MAX_EP_COUNT: usize = 9;
1438
1439trait SealedInstance {
1440 const HIGH_SPEED: bool;
1441 const FIFO_DEPTH_WORDS: u16;
1442 const ENDPOINT_COUNT: usize;
1443
1444 fn regs() -> crate::pac::otg::Otg;
1445 fn state() -> &'static super::State<{ MAX_EP_COUNT }>;
1446}
1447
1448/// USB instance trait.
1449#[allow(private_bounds)]
1450pub trait Instance: SealedInstance + RccPeripheral + 'static {
1451 /// Interrupt for this USB instance.
1452 type Interrupt: interrupt::typelevel::Interrupt;
1453}
1454
1455// Internal PHY pins
1456pin_trait!(DpPin, Instance);
1457pin_trait!(DmPin, Instance);
1458
1459// External PHY pins
1460pin_trait!(UlpiClkPin, Instance);
1461pin_trait!(UlpiDirPin, Instance);
1462pin_trait!(UlpiNxtPin, Instance);
1463pin_trait!(UlpiStpPin, Instance);
1464pin_trait!(UlpiD0Pin, Instance);
1465pin_trait!(UlpiD1Pin, Instance);
1466pin_trait!(UlpiD2Pin, Instance);
1467pin_trait!(UlpiD3Pin, Instance);
1468pin_trait!(UlpiD4Pin, Instance);
1469pin_trait!(UlpiD5Pin, Instance);
1470pin_trait!(UlpiD6Pin, Instance);
1471pin_trait!(UlpiD7Pin, Instance);
1472
1473foreach_interrupt!(
1474 (USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => {
1475 impl SealedInstance for crate::peripherals::USB_OTG_FS {
1476 const HIGH_SPEED: bool = false;
1477
1478 cfg_if::cfg_if! {
1479 if #[cfg(stm32f1)] {
1480 const FIFO_DEPTH_WORDS: u16 = 128;
1481 const ENDPOINT_COUNT: usize = 8;
1482 } else if #[cfg(any(
1483 stm32f2,
1484 stm32f401,
1485 stm32f405,
1486 stm32f407,
1487 stm32f411,
1488 stm32f415,
1489 stm32f417,
1490 stm32f427,
1491 stm32f429,
1492 stm32f437,
1493 stm32f439,
1494 ))] {
1495 const FIFO_DEPTH_WORDS: u16 = 320;
1496 const ENDPOINT_COUNT: usize = 4;
1497 } else if #[cfg(any(
1498 stm32f412,
1499 stm32f413,
1500 stm32f423,
1501 stm32f446,
1502 stm32f469,
1503 stm32f479,
1504 stm32f7,
1505 stm32l4,
1506 stm32u5,
1507 ))] {
1508 const FIFO_DEPTH_WORDS: u16 = 320;
1509 const ENDPOINT_COUNT: usize = 6;
1510 } else if #[cfg(stm32g0x1)] {
1511 const FIFO_DEPTH_WORDS: u16 = 512;
1512 const ENDPOINT_COUNT: usize = 8;
1513 } else if #[cfg(stm32h7)] {
1514 const FIFO_DEPTH_WORDS: u16 = 1024;
1515 const ENDPOINT_COUNT: usize = 9;
1516 } else if #[cfg(stm32u5)] {
1517 const FIFO_DEPTH_WORDS: u16 = 320;
1518 const ENDPOINT_COUNT: usize = 6;
1519 } else {
1520 compile_error!("USB_OTG_FS peripheral is not supported by this chip.");
1521 }
1522 }
1523
1524 fn regs() -> crate::pac::otg::Otg {
1525 crate::pac::USB_OTG_FS
1526 }
1527
1528 fn state() -> &'static State<MAX_EP_COUNT> {
1529 static STATE: State<MAX_EP_COUNT> = State::new();
1530 &STATE
1531 }
1532 }
1533
1534 impl Instance for crate::peripherals::USB_OTG_FS {
1535 type Interrupt = crate::interrupt::typelevel::$irq;
1536 }
1537 };
1538
1539 (USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => {
1540 impl SealedInstance for crate::peripherals::USB_OTG_HS {
1541 const HIGH_SPEED: bool = true;
1542
1543 cfg_if::cfg_if! {
1544 if #[cfg(any(
1545 stm32f2,
1546 stm32f405,
1547 stm32f407,
1548 stm32f415,
1549 stm32f417,
1550 stm32f427,
1551 stm32f429,
1552 stm32f437,
1553 stm32f439,
1554 ))] {
1555 const FIFO_DEPTH_WORDS: u16 = 1024;
1556 const ENDPOINT_COUNT: usize = 6;
1557 } else if #[cfg(any(
1558 stm32f446,
1559 stm32f469,
1560 stm32f479,
1561 stm32f7,
1562 stm32h7,
1563 ))] {
1564 const FIFO_DEPTH_WORDS: u16 = 1024;
1565 const ENDPOINT_COUNT: usize = 9;
1566 } else if #[cfg(stm32u5)] {
1567 const FIFO_DEPTH_WORDS: u16 = 1024;
1568 const ENDPOINT_COUNT: usize = 9;
1569 } else {
1570 compile_error!("USB_OTG_HS peripheral is not supported by this chip.");
1571 }
1572 }
1573
1574 fn regs() -> crate::pac::otg::Otg {
1575 // OTG HS registers are a superset of FS registers
1576 unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) }
1577 }
1578
1579 fn state() -> &'static State<MAX_EP_COUNT> {
1580 static STATE: State<MAX_EP_COUNT> = State::new();
1581 &STATE
1582 }
1583 }
1584
1585 impl Instance for crate::peripherals::USB_OTG_HS {
1586 type Interrupt = crate::interrupt::typelevel::$irq;
1587 }
1588 };
1589);
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index be321a19b..f48808cb3 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -12,12 +12,10 @@ use embassy_usb_driver::{
12 Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, 12 Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported,
13}; 13};
14 14
15use super::{DmPin, DpPin, Instance};
16use crate::interrupt::typelevel::Interrupt;
17use crate::pac::usb::regs; 15use crate::pac::usb::regs;
18use crate::pac::usb::vals::{EpType, Stat}; 16use crate::pac::usb::vals::{EpType, Stat};
19use crate::pac::USBRAM; 17use crate::pac::USBRAM;
20use crate::rcc::sealed::RccPeripheral; 18use crate::rcc::RccPeripheral;
21use crate::{interrupt, Peripheral}; 19use crate::{interrupt, Peripheral};
22 20
23/// Interrupt handler. 21/// Interrupt handler.
@@ -259,18 +257,10 @@ impl<'d, T: Instance> Driver<'d, T> {
259 dm: impl Peripheral<P = impl DmPin<T>> + 'd, 257 dm: impl Peripheral<P = impl DmPin<T>> + 'd,
260 ) -> Self { 258 ) -> Self {
261 into_ref!(dp, dm); 259 into_ref!(dp, dm);
262 T::Interrupt::unpend();
263 unsafe { T::Interrupt::enable() };
264 260
265 let regs = T::regs(); 261 super::common_init::<T>();
266
267 #[cfg(any(stm32l4, stm32l5, stm32wb))]
268 crate::pac::PWR.cr2().modify(|w| w.set_usv(true));
269
270 #[cfg(pwr_h5)]
271 crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true));
272 262
273 <T as RccPeripheral>::enable_and_reset(); 263 let regs = T::regs();
274 264
275 regs.cntr().write(|w| { 265 regs.cntr().write(|w| {
276 w.set_pdwn(false); 266 w.set_pdwn(false);
@@ -287,8 +277,8 @@ impl<'d, T: Instance> Driver<'d, T> {
287 277
288 #[cfg(not(stm32l1))] 278 #[cfg(not(stm32l1))]
289 { 279 {
290 dp.set_as_af(dp.af_num(), crate::gpio::sealed::AFType::OutputPushPull); 280 dp.set_as_af(dp.af_num(), crate::gpio::AFType::OutputPushPull);
291 dm.set_as_af(dm.af_num(), crate::gpio::sealed::AFType::OutputPushPull); 281 dm.set_as_af(dm.af_num(), crate::gpio::AFType::OutputPushPull);
292 } 282 }
293 #[cfg(stm32l1)] 283 #[cfg(stm32l1)]
294 let _ = (dp, dm); // suppress "unused" warnings. 284 let _ = (dp, dm); // suppress "unused" warnings.
@@ -647,7 +637,6 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
647 637
648trait Dir { 638trait Dir {
649 fn dir() -> Direction; 639 fn dir() -> Direction;
650 fn waker(i: usize) -> &'static AtomicWaker;
651} 640}
652 641
653/// Marker type for the "IN" direction. 642/// Marker type for the "IN" direction.
@@ -656,11 +645,6 @@ impl Dir for In {
656 fn dir() -> Direction { 645 fn dir() -> Direction {
657 Direction::In 646 Direction::In
658 } 647 }
659
660 #[inline]
661 fn waker(i: usize) -> &'static AtomicWaker {
662 &EP_IN_WAKERS[i]
663 }
664} 648}
665 649
666/// Marker type for the "OUT" direction. 650/// Marker type for the "OUT" direction.
@@ -669,11 +653,6 @@ impl Dir for Out {
669 fn dir() -> Direction { 653 fn dir() -> Direction {
670 Direction::Out 654 Direction::Out
671 } 655 }
672
673 #[inline]
674 fn waker(i: usize) -> &'static AtomicWaker {
675 &EP_OUT_WAKERS[i]
676 }
677} 656}
678 657
679/// USB endpoint. 658/// USB endpoint.
@@ -1057,3 +1036,32 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
1057 }); 1036 });
1058 } 1037 }
1059} 1038}
1039
1040trait SealedInstance {
1041 fn regs() -> crate::pac::usb::Usb;
1042}
1043
1044/// USB instance trait.
1045#[allow(private_bounds)]
1046pub trait Instance: SealedInstance + RccPeripheral + 'static {
1047 /// Interrupt for this USB instance.
1048 type Interrupt: interrupt::typelevel::Interrupt;
1049}
1050
1051// Internal PHY pins
1052pin_trait!(DpPin, Instance);
1053pin_trait!(DmPin, Instance);
1054
1055foreach_interrupt!(
1056 ($inst:ident, usb, $block:ident, LP, $irq:ident) => {
1057 impl SealedInstance for crate::peripherals::$inst {
1058 fn regs() -> crate::pac::usb::Usb {
1059 crate::pac::$inst
1060 }
1061 }
1062
1063 impl Instance for crate::peripherals::$inst {
1064 type Interrupt = crate::interrupt::typelevel::$irq;
1065 }
1066 };
1067);
diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs
deleted file mode 100644
index 0649e684b..000000000
--- a/embassy-stm32/src/usb_otg/mod.rs
+++ /dev/null
@@ -1,163 +0,0 @@
1//! USB On The Go (OTG)
2
3use crate::rcc::RccPeripheral;
4use crate::{interrupt, peripherals};
5
6mod usb;
7pub use usb::*;
8
9// Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps
10const MAX_EP_COUNT: usize = 9;
11
12pub(crate) mod sealed {
13 pub trait Instance {
14 const HIGH_SPEED: bool;
15 const FIFO_DEPTH_WORDS: u16;
16 const ENDPOINT_COUNT: usize;
17
18 fn regs() -> crate::pac::otg::Otg;
19 fn state() -> &'static super::State<{ super::MAX_EP_COUNT }>;
20 }
21}
22
23/// USB OTG instance.
24pub trait Instance: sealed::Instance + RccPeripheral {
25 /// Interrupt for this USB OTG instance.
26 type Interrupt: interrupt::typelevel::Interrupt;
27}
28
29// Internal PHY pins
30pin_trait!(DpPin, Instance);
31pin_trait!(DmPin, Instance);
32
33// External PHY pins
34pin_trait!(UlpiClkPin, Instance);
35pin_trait!(UlpiDirPin, Instance);
36pin_trait!(UlpiNxtPin, Instance);
37pin_trait!(UlpiStpPin, Instance);
38pin_trait!(UlpiD0Pin, Instance);
39pin_trait!(UlpiD1Pin, Instance);
40pin_trait!(UlpiD2Pin, Instance);
41pin_trait!(UlpiD3Pin, Instance);
42pin_trait!(UlpiD4Pin, Instance);
43pin_trait!(UlpiD5Pin, Instance);
44pin_trait!(UlpiD6Pin, Instance);
45pin_trait!(UlpiD7Pin, Instance);
46
47foreach_interrupt!(
48 (USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => {
49 impl sealed::Instance for peripherals::USB_OTG_FS {
50 const HIGH_SPEED: bool = false;
51
52 cfg_if::cfg_if! {
53 if #[cfg(stm32f1)] {
54 const FIFO_DEPTH_WORDS: u16 = 128;
55 const ENDPOINT_COUNT: usize = 8;
56 } else if #[cfg(any(
57 stm32f2,
58 stm32f401,
59 stm32f405,
60 stm32f407,
61 stm32f411,
62 stm32f415,
63 stm32f417,
64 stm32f427,
65 stm32f429,
66 stm32f437,
67 stm32f439,
68 ))] {
69 const FIFO_DEPTH_WORDS: u16 = 320;
70 const ENDPOINT_COUNT: usize = 4;
71 } else if #[cfg(any(
72 stm32f412,
73 stm32f413,
74 stm32f423,
75 stm32f446,
76 stm32f469,
77 stm32f479,
78 stm32f7,
79 stm32l4,
80 stm32u5,
81 ))] {
82 const FIFO_DEPTH_WORDS: u16 = 320;
83 const ENDPOINT_COUNT: usize = 6;
84 } else if #[cfg(stm32g0x1)] {
85 const FIFO_DEPTH_WORDS: u16 = 512;
86 const ENDPOINT_COUNT: usize = 8;
87 } else if #[cfg(stm32h7)] {
88 const FIFO_DEPTH_WORDS: u16 = 1024;
89 const ENDPOINT_COUNT: usize = 9;
90 } else if #[cfg(stm32u5)] {
91 const FIFO_DEPTH_WORDS: u16 = 320;
92 const ENDPOINT_COUNT: usize = 6;
93 } else {
94 compile_error!("USB_OTG_FS peripheral is not supported by this chip.");
95 }
96 }
97
98 fn regs() -> crate::pac::otg::Otg {
99 crate::pac::USB_OTG_FS
100 }
101
102 fn state() -> &'static State<MAX_EP_COUNT> {
103 static STATE: State<MAX_EP_COUNT> = State::new();
104 &STATE
105 }
106 }
107
108 impl Instance for peripherals::USB_OTG_FS {
109 type Interrupt = crate::interrupt::typelevel::$irq;
110 }
111 };
112
113 (USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => {
114 impl sealed::Instance for peripherals::USB_OTG_HS {
115 const HIGH_SPEED: bool = true;
116
117 cfg_if::cfg_if! {
118 if #[cfg(any(
119 stm32f2,
120 stm32f405,
121 stm32f407,
122 stm32f415,
123 stm32f417,
124 stm32f427,
125 stm32f429,
126 stm32f437,
127 stm32f439,
128 ))] {
129 const FIFO_DEPTH_WORDS: u16 = 1024;
130 const ENDPOINT_COUNT: usize = 6;
131 } else if #[cfg(any(
132 stm32f446,
133 stm32f469,
134 stm32f479,
135 stm32f7,
136 stm32h7,
137 ))] {
138 const FIFO_DEPTH_WORDS: u16 = 1024;
139 const ENDPOINT_COUNT: usize = 9;
140 } else if #[cfg(stm32u5)] {
141 const FIFO_DEPTH_WORDS: u16 = 1024;
142 const ENDPOINT_COUNT: usize = 9;
143 } else {
144 compile_error!("USB_OTG_HS peripheral is not supported by this chip.");
145 }
146 }
147
148 fn regs() -> crate::pac::otg::Otg {
149 // OTG HS registers are a superset of FS registers
150 unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) }
151 }
152
153 fn state() -> &'static State<MAX_EP_COUNT> {
154 static STATE: State<MAX_EP_COUNT> = State::new();
155 &STATE
156 }
157 }
158
159 impl Instance for peripherals::USB_OTG_HS {
160 type Interrupt = crate::interrupt::typelevel::$irq;
161 }
162 };
163);
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index 2ff0db09e..ab21c4b6b 100644
--- a/embassy-stm32/src/wdg/mod.rs
+++ b/embassy-stm32/src/wdg/mod.rs
@@ -80,18 +80,17 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
80 } 80 }
81} 81}
82 82
83mod sealed { 83trait SealedInstance {
84 pub trait Instance { 84 fn regs() -> crate::pac::iwdg::Iwdg;
85 fn regs() -> crate::pac::iwdg::Iwdg;
86 }
87} 85}
88 86
89/// IWDG instance trait. 87/// IWDG instance trait.
90pub trait Instance: sealed::Instance {} 88#[allow(private_bounds)]
89pub trait Instance: SealedInstance {}
91 90
92foreach_peripheral!( 91foreach_peripheral!(
93 (iwdg, $inst:ident) => { 92 (iwdg, $inst:ident) => {
94 impl sealed::Instance for crate::peripherals::$inst { 93 impl SealedInstance for crate::peripherals::$inst {
95 fn regs() -> crate::pac::iwdg::Iwdg { 94 fn regs() -> crate::pac::iwdg::Iwdg {
96 crate::pac::$inst 95 crate::pac::$inst
97 } 96 }
diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml
index 85673026c..aaf6fab1d 100644
--- a/embassy-sync/Cargo.toml
+++ b/embassy-sync/Cargo.toml
@@ -20,7 +20,7 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-sync/
20target = "thumbv7em-none-eabi" 20target = "thumbv7em-none-eabi"
21 21
22[features] 22[features]
23std = [] 23std = ["critical-section/std"]
24turbowakers = [] 24turbowakers = []
25 25
26[dependencies] 26[dependencies]
diff --git a/embassy-sync/src/fmt.rs b/embassy-sync/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-sync/src/fmt.rs
+++ b/embassy-sync/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-sync/src/lib.rs b/embassy-sync/src/lib.rs
index d88c76db5..61b173e80 100644
--- a/embassy-sync/src/lib.rs
+++ b/embassy-sync/src/lib.rs
@@ -13,6 +13,7 @@ mod ring_buffer;
13pub mod blocking_mutex; 13pub mod blocking_mutex;
14pub mod channel; 14pub mod channel;
15pub mod mutex; 15pub mod mutex;
16pub mod once_lock;
16pub mod pipe; 17pub mod pipe;
17pub mod priority_channel; 18pub mod priority_channel;
18pub mod pubsub; 19pub mod pubsub;
diff --git a/embassy-sync/src/once_lock.rs b/embassy-sync/src/once_lock.rs
new file mode 100644
index 000000000..31cc99711
--- /dev/null
+++ b/embassy-sync/src/once_lock.rs
@@ -0,0 +1,236 @@
1//! Syncronization primitive for initializing a value once, allowing others to await a reference to the value.
2
3use core::cell::Cell;
4use core::future::poll_fn;
5use core::mem::MaybeUninit;
6use core::sync::atomic::{AtomicBool, Ordering};
7use core::task::Poll;
8
9/// The `OnceLock` is a synchronization primitive that allows for
10/// initializing a value once, and allowing others to `.await` a
11/// reference to the value. This is useful for lazy initialization of
12/// a static value.
13///
14/// **Note**: this implementation uses a busy loop to poll the value,
15/// which is not as efficient as registering a dedicated `Waker`.
16/// However, the if the usecase for is to initialize a static variable
17/// relatively early in the program life cycle, it should be fine.
18///
19/// # Example
20/// ```
21/// use futures_executor::block_on;
22/// use embassy_sync::once_lock::OnceLock;
23///
24/// // Define a static value that will be lazily initialized
25/// static VALUE: OnceLock<u32> = OnceLock::new();
26///
27/// let f = async {
28///
29/// // Initialize the value
30/// let reference = VALUE.get_or_init(|| 20);
31/// assert_eq!(reference, &20);
32///
33/// // Wait for the value to be initialized
34/// // and get a static reference it
35/// assert_eq!(VALUE.get().await, &20);
36///
37/// };
38/// block_on(f)
39/// ```
40pub struct OnceLock<T> {
41 init: AtomicBool,
42 data: Cell<MaybeUninit<T>>,
43}
44
45unsafe impl<T> Sync for OnceLock<T> {}
46
47impl<T> OnceLock<T> {
48 /// Create a new uninitialized `OnceLock`.
49 pub const fn new() -> Self {
50 Self {
51 init: AtomicBool::new(false),
52 data: Cell::new(MaybeUninit::zeroed()),
53 }
54 }
55
56 /// Get a reference to the underlying value, waiting for it to be set.
57 /// If the value is already set, this will return immediately.
58 pub async fn get(&self) -> &T {
59 poll_fn(|cx| match self.try_get() {
60 Some(data) => Poll::Ready(data),
61 None => {
62 cx.waker().wake_by_ref();
63 Poll::Pending
64 }
65 })
66 .await
67 }
68
69 /// Try to get a reference to the underlying value if it exists.
70 pub fn try_get(&self) -> Option<&T> {
71 if self.init.load(Ordering::Relaxed) {
72 Some(unsafe { self.get_ref_unchecked() })
73 } else {
74 None
75 }
76 }
77
78 /// Set the underlying value. If the value is already set, this will return an error with the given value.
79 pub fn init(&self, value: T) -> Result<(), T> {
80 // Critical section is required to ensure that the value is
81 // not simultaniously initialized elsewhere at the same time.
82 critical_section::with(|_| {
83 // If the value is not set, set it and return Ok.
84 if !self.init.load(Ordering::Relaxed) {
85 self.data.set(MaybeUninit::new(value));
86 self.init.store(true, Ordering::Relaxed);
87 Ok(())
88
89 // Otherwise return an error with the given value.
90 } else {
91 Err(value)
92 }
93 })
94 }
95
96 /// Get a reference to the underlying value, initializing it if it does not exist.
97 pub fn get_or_init<F>(&self, f: F) -> &T
98 where
99 F: FnOnce() -> T,
100 {
101 // Critical section is required to ensure that the value is
102 // not simultaniously initialized elsewhere at the same time.
103 critical_section::with(|_| {
104 // If the value is not set, set it.
105 if !self.init.load(Ordering::Relaxed) {
106 self.data.set(MaybeUninit::new(f()));
107 self.init.store(true, Ordering::Relaxed);
108 }
109 });
110
111 // Return a reference to the value.
112 unsafe { self.get_ref_unchecked() }
113 }
114
115 /// Consume the `OnceLock`, returning the underlying value if it was initialized.
116 pub fn into_inner(self) -> Option<T> {
117 if self.init.load(Ordering::Relaxed) {
118 Some(unsafe { self.data.into_inner().assume_init() })
119 } else {
120 None
121 }
122 }
123
124 /// Take the underlying value if it was initialized, uninitializing the `OnceLock` in the process.
125 pub fn take(&mut self) -> Option<T> {
126 // If the value is set, uninitialize the lock and return the value.
127 critical_section::with(|_| {
128 if self.init.load(Ordering::Relaxed) {
129 let val = unsafe { self.data.replace(MaybeUninit::zeroed()).assume_init() };
130 self.init.store(false, Ordering::Relaxed);
131 Some(val)
132
133 // Otherwise return None.
134 } else {
135 None
136 }
137 })
138 }
139
140 /// Check if the value has been set.
141 pub fn is_set(&self) -> bool {
142 self.init.load(Ordering::Relaxed)
143 }
144
145 /// Get a reference to the underlying value.
146 /// # Safety
147 /// Must only be used if a value has been set.
148 unsafe fn get_ref_unchecked(&self) -> &T {
149 (*self.data.as_ptr()).assume_init_ref()
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156
157 #[test]
158 fn once_lock() {
159 let lock = OnceLock::new();
160 assert_eq!(lock.try_get(), None);
161 assert_eq!(lock.is_set(), false);
162
163 let v = 42;
164 assert_eq!(lock.init(v), Ok(()));
165 assert_eq!(lock.is_set(), true);
166 assert_eq!(lock.try_get(), Some(&v));
167 assert_eq!(lock.try_get(), Some(&v));
168
169 let v = 43;
170 assert_eq!(lock.init(v), Err(v));
171 assert_eq!(lock.is_set(), true);
172 assert_eq!(lock.try_get(), Some(&42));
173 }
174
175 #[test]
176 fn once_lock_get_or_init() {
177 let lock = OnceLock::new();
178 assert_eq!(lock.try_get(), None);
179 assert_eq!(lock.is_set(), false);
180
181 let v = lock.get_or_init(|| 42);
182 assert_eq!(v, &42);
183 assert_eq!(lock.is_set(), true);
184 assert_eq!(lock.try_get(), Some(&42));
185
186 let v = lock.get_or_init(|| 43);
187 assert_eq!(v, &42);
188 assert_eq!(lock.is_set(), true);
189 assert_eq!(lock.try_get(), Some(&42));
190 }
191
192 #[test]
193 fn once_lock_static() {
194 static LOCK: OnceLock<i32> = OnceLock::new();
195
196 let v: &'static i32 = LOCK.get_or_init(|| 42);
197 assert_eq!(v, &42);
198
199 let v: &'static i32 = LOCK.get_or_init(|| 43);
200 assert_eq!(v, &42);
201 }
202
203 #[futures_test::test]
204 async fn once_lock_async() {
205 static LOCK: OnceLock<i32> = OnceLock::new();
206
207 assert!(LOCK.init(42).is_ok());
208
209 let v: &'static i32 = LOCK.get().await;
210 assert_eq!(v, &42);
211 }
212
213 #[test]
214 fn once_lock_into_inner() {
215 let lock: OnceLock<i32> = OnceLock::new();
216
217 let v = lock.get_or_init(|| 42);
218 assert_eq!(v, &42);
219
220 assert_eq!(lock.into_inner(), Some(42));
221 }
222
223 #[test]
224 fn once_lock_take_init() {
225 let mut lock: OnceLock<i32> = OnceLock::new();
226
227 assert_eq!(lock.get_or_init(|| 42), &42);
228 assert_eq!(lock.is_set(), true);
229
230 assert_eq!(lock.take(), Some(42));
231 assert_eq!(lock.is_set(), false);
232
233 assert_eq!(lock.get_or_init(|| 43), &43);
234 assert_eq!(lock.is_set(), true);
235 }
236}
diff --git a/embassy-sync/src/signal.rs b/embassy-sync/src/signal.rs
index d75750ce7..520f1a896 100644
--- a/embassy-sync/src/signal.rs
+++ b/embassy-sync/src/signal.rs
@@ -125,7 +125,7 @@ where
125 }) 125 })
126 } 126 }
127 127
128 /// non-blocking method to check whether this signal has been signaled. 128 /// non-blocking method to check whether this signal has been signaled. This does not clear the signal.
129 pub fn signaled(&self) -> bool { 129 pub fn signaled(&self) -> bool {
130 self.state.lock(|cell| { 130 self.state.lock(|cell| {
131 let state = cell.replace(State::None); 131 let state = cell.replace(State::None);
diff --git a/embassy-time/src/fmt.rs b/embassy-time/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-time/src/fmt.rs
+++ b/embassy-time/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-usb-dfu/src/fmt.rs b/embassy-usb-dfu/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-usb-dfu/src/fmt.rs
+++ b/embassy-usb-dfu/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-usb-logger/src/lib.rs b/embassy-usb-logger/src/lib.rs
index da5ff0f36..34d1ca663 100644
--- a/embassy-usb-logger/src/lib.rs
+++ b/embassy-usb-logger/src/lib.rs
@@ -16,7 +16,6 @@ type CS = embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
16/// The logger state containing buffers that must live as long as the USB peripheral. 16/// The logger state containing buffers that must live as long as the USB peripheral.
17pub struct LoggerState<'d> { 17pub struct LoggerState<'d> {
18 state: State<'d>, 18 state: State<'d>,
19 device_descriptor: [u8; 32],
20 config_descriptor: [u8; 128], 19 config_descriptor: [u8; 128],
21 bos_descriptor: [u8; 16], 20 bos_descriptor: [u8; 16],
22 msos_descriptor: [u8; 256], 21 msos_descriptor: [u8; 256],
@@ -28,7 +27,6 @@ impl<'d> LoggerState<'d> {
28 pub fn new() -> Self { 27 pub fn new() -> Self {
29 Self { 28 Self {
30 state: State::new(), 29 state: State::new(),
31 device_descriptor: [0; 32],
32 config_descriptor: [0; 128], 30 config_descriptor: [0; 128],
33 bos_descriptor: [0; 16], 31 bos_descriptor: [0; 16],
34 msos_descriptor: [0; 256], 32 msos_descriptor: [0; 256],
@@ -74,7 +72,6 @@ impl<const N: usize> UsbLogger<N> {
74 let mut builder = Builder::new( 72 let mut builder = Builder::new(
75 driver, 73 driver,
76 config, 74 config,
77 &mut state.device_descriptor,
78 &mut state.config_descriptor, 75 &mut state.config_descriptor,
79 &mut state.bos_descriptor, 76 &mut state.bos_descriptor,
80 &mut state.msos_descriptor, 77 &mut state.msos_descriptor,
@@ -151,7 +148,17 @@ struct Writer<'d, const N: usize>(&'d Pipe<CS, N>);
151 148
152impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> { 149impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> {
153 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { 150 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
154 let _ = self.0.try_write(s.as_bytes()); 151 // The Pipe is implemented in such way that we cannot
152 // write across the wraparound discontinuity.
153 let b = s.as_bytes();
154 if let Ok(n) = self.0.try_write(b) {
155 if n < b.len() {
156 // We wrote some data but not all, attempt again
157 // as the reason might be a wraparound in the
158 // ring buffer, which resolves on second attempt.
159 let _ = self.0.try_write(&b[n..]);
160 }
161 }
155 Ok(()) 162 Ok(())
156 } 163 }
157} 164}
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index c4705d041..c06107396 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -128,7 +128,6 @@ pub struct Builder<'d, D: Driver<'d>> {
128 driver: D, 128 driver: D,
129 next_string_index: u8, 129 next_string_index: u8,
130 130
131 device_descriptor: DescriptorWriter<'d>,
132 config_descriptor: DescriptorWriter<'d>, 131 config_descriptor: DescriptorWriter<'d>,
133 bos_descriptor: BosWriter<'d>, 132 bos_descriptor: BosWriter<'d>,
134 133
@@ -144,7 +143,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
144 pub fn new( 143 pub fn new(
145 driver: D, 144 driver: D,
146 config: Config<'d>, 145 config: Config<'d>,
147 device_descriptor_buf: &'d mut [u8],
148 config_descriptor_buf: &'d mut [u8], 146 config_descriptor_buf: &'d mut [u8],
149 bos_descriptor_buf: &'d mut [u8], 147 bos_descriptor_buf: &'d mut [u8],
150 msos_descriptor_buf: &'d mut [u8], 148 msos_descriptor_buf: &'d mut [u8],
@@ -167,11 +165,9 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
167 _ => panic!("invalid max_packet_size_0, the allowed values are 8, 16, 32 or 64"), 165 _ => panic!("invalid max_packet_size_0, the allowed values are 8, 16, 32 or 64"),
168 } 166 }
169 167
170 let mut device_descriptor = DescriptorWriter::new(device_descriptor_buf);
171 let mut config_descriptor = DescriptorWriter::new(config_descriptor_buf); 168 let mut config_descriptor = DescriptorWriter::new(config_descriptor_buf);
172 let mut bos_descriptor = BosWriter::new(DescriptorWriter::new(bos_descriptor_buf)); 169 let mut bos_descriptor = BosWriter::new(DescriptorWriter::new(bos_descriptor_buf));
173 170
174 device_descriptor.device(&config);
175 config_descriptor.configuration(&config); 171 config_descriptor.configuration(&config);
176 bos_descriptor.bos(); 172 bos_descriptor.bos();
177 173
@@ -183,7 +179,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
183 control_buf, 179 control_buf,
184 next_string_index: STRING_INDEX_CUSTOM_START, 180 next_string_index: STRING_INDEX_CUSTOM_START,
185 181
186 device_descriptor,
187 config_descriptor, 182 config_descriptor,
188 bos_descriptor, 183 bos_descriptor,
189 184
@@ -199,7 +194,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
199 self.bos_descriptor.end_bos(); 194 self.bos_descriptor.end_bos();
200 195
201 // Log the number of allocator bytes actually used in descriptor buffers 196 // Log the number of allocator bytes actually used in descriptor buffers
202 info!("USB: device_descriptor used: {}", self.device_descriptor.position());
203 info!("USB: config_descriptor used: {}", self.config_descriptor.position()); 197 info!("USB: config_descriptor used: {}", self.config_descriptor.position());
204 info!("USB: bos_descriptor used: {}", self.bos_descriptor.writer.position()); 198 info!("USB: bos_descriptor used: {}", self.bos_descriptor.writer.position());
205 info!("USB: msos_descriptor used: {}", msos_descriptor.len()); 199 info!("USB: msos_descriptor used: {}", msos_descriptor.len());
@@ -209,7 +203,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
209 self.driver, 203 self.driver,
210 self.config, 204 self.config,
211 self.handlers, 205 self.handlers,
212 self.device_descriptor.into_buf(),
213 self.config_descriptor.into_buf(), 206 self.config_descriptor.into_buf(),
214 self.bos_descriptor.writer.into_buf(), 207 self.bos_descriptor.writer.into_buf(),
215 msos_descriptor, 208 msos_descriptor,
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs
index fa83ef583..eb3d1f53a 100644
--- a/embassy-usb/src/descriptor.rs
+++ b/embassy-usb/src/descriptor.rs
@@ -82,30 +82,6 @@ impl<'a> DescriptorWriter<'a> {
82 self.position = start + length; 82 self.position = start + length;
83 } 83 }
84 84
85 pub(crate) fn device(&mut self, config: &Config) {
86 self.write(
87 descriptor_type::DEVICE,
88 &[
89 0x10,
90 0x02, // bcdUSB 2.1
91 config.device_class, // bDeviceClass
92 config.device_sub_class, // bDeviceSubClass
93 config.device_protocol, // bDeviceProtocol
94 config.max_packet_size_0, // bMaxPacketSize0
95 config.vendor_id as u8,
96 (config.vendor_id >> 8) as u8, // idVendor
97 config.product_id as u8,
98 (config.product_id >> 8) as u8, // idProduct
99 config.device_release as u8,
100 (config.device_release >> 8) as u8, // bcdDevice
101 config.manufacturer.map_or(0, |_| 1), // iManufacturer
102 config.product.map_or(0, |_| 2), // iProduct
103 config.serial_number.map_or(0, |_| 3), // iSerialNumber
104 1, // bNumConfigurations
105 ],
106 );
107 }
108
109 pub(crate) fn configuration(&mut self, config: &Config) { 85 pub(crate) fn configuration(&mut self, config: &Config) {
110 self.num_interfaces_mark = Some(self.position + 4); 86 self.num_interfaces_mark = Some(self.position + 4);
111 87
@@ -269,6 +245,33 @@ impl<'a> DescriptorWriter<'a> {
269 } 245 }
270} 246}
271 247
248/// Create a new Device Descriptor array.
249///
250/// All device descriptors are always 18 bytes, so there's no need for
251/// a variable-length buffer or DescriptorWriter.
252pub(crate) fn device_descriptor(config: &Config) -> [u8; 18] {
253 [
254 18, // bLength
255 0x01, // bDescriptorType
256 0x10,
257 0x02, // bcdUSB 2.1
258 config.device_class, // bDeviceClass
259 config.device_sub_class, // bDeviceSubClass
260 config.device_protocol, // bDeviceProtocol
261 config.max_packet_size_0, // bMaxPacketSize0
262 config.vendor_id as u8,
263 (config.vendor_id >> 8) as u8, // idVendor
264 config.product_id as u8,
265 (config.product_id >> 8) as u8, // idProduct
266 config.device_release as u8,
267 (config.device_release >> 8) as u8, // bcdDevice
268 config.manufacturer.map_or(0, |_| 1), // iManufacturer
269 config.product.map_or(0, |_| 2), // iProduct
270 config.serial_number.map_or(0, |_| 3), // iSerialNumber
271 1, // bNumConfigurations
272 ]
273}
274
272/// A writer for Binary Object Store descriptor. 275/// A writer for Binary Object Store descriptor.
273pub struct BosWriter<'a> { 276pub struct BosWriter<'a> {
274 pub(crate) writer: DescriptorWriter<'a>, 277 pub(crate) writer: DescriptorWriter<'a>,
diff --git a/embassy-usb/src/fmt.rs b/embassy-usb/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-usb/src/fmt.rs
+++ b/embassy-usb/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 241e33a78..d58950838 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -168,8 +168,6 @@ struct Interface {
168#[derive(PartialEq, Eq, Copy, Clone, Debug)] 168#[derive(PartialEq, Eq, Copy, Clone, Debug)]
169#[cfg_attr(feature = "defmt", derive(defmt::Format))] 169#[cfg_attr(feature = "defmt", derive(defmt::Format))]
170pub struct UsbBufferReport { 170pub struct UsbBufferReport {
171 /// Number of device descriptor bytes used
172 pub device_descriptor_used: usize,
173 /// Number of config descriptor bytes used 171 /// Number of config descriptor bytes used
174 pub config_descriptor_used: usize, 172 pub config_descriptor_used: usize,
175 /// Number of bos descriptor bytes used 173 /// Number of bos descriptor bytes used
@@ -191,7 +189,7 @@ struct Inner<'d, D: Driver<'d>> {
191 bus: D::Bus, 189 bus: D::Bus,
192 190
193 config: Config<'d>, 191 config: Config<'d>,
194 device_descriptor: &'d [u8], 192 device_descriptor: [u8; 18],
195 config_descriptor: &'d [u8], 193 config_descriptor: &'d [u8],
196 bos_descriptor: &'d [u8], 194 bos_descriptor: &'d [u8],
197 msos_descriptor: crate::msos::MsOsDescriptorSet<'d>, 195 msos_descriptor: crate::msos::MsOsDescriptorSet<'d>,
@@ -217,7 +215,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
217 driver: D, 215 driver: D,
218 config: Config<'d>, 216 config: Config<'d>,
219 handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>, 217 handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>,
220 device_descriptor: &'d [u8],
221 config_descriptor: &'d [u8], 218 config_descriptor: &'d [u8],
222 bos_descriptor: &'d [u8], 219 bos_descriptor: &'d [u8],
223 msos_descriptor: crate::msos::MsOsDescriptorSet<'d>, 220 msos_descriptor: crate::msos::MsOsDescriptorSet<'d>,
@@ -227,6 +224,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
227 // Start the USB bus. 224 // Start the USB bus.
228 // This prevent further allocation by consuming the driver. 225 // This prevent further allocation by consuming the driver.
229 let (bus, control) = driver.start(config.max_packet_size_0 as u16); 226 let (bus, control) = driver.start(config.max_packet_size_0 as u16);
227 let device_descriptor = descriptor::device_descriptor(&config);
230 228
231 Self { 229 Self {
232 control_buf, 230 control_buf,
@@ -256,7 +254,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
256 /// Useful for tuning buffer sizes for actual usage 254 /// Useful for tuning buffer sizes for actual usage
257 pub fn buffer_usage(&self) -> UsbBufferReport { 255 pub fn buffer_usage(&self) -> UsbBufferReport {
258 UsbBufferReport { 256 UsbBufferReport {
259 device_descriptor_used: self.inner.device_descriptor.len(),
260 config_descriptor_used: self.inner.config_descriptor.len(), 257 config_descriptor_used: self.inner.config_descriptor.len(),
261 bos_descriptor_used: self.inner.bos_descriptor.len(), 258 bos_descriptor_used: self.inner.bos_descriptor.len(),
262 msos_descriptor_used: self.inner.msos_descriptor.len(), 259 msos_descriptor_used: self.inner.msos_descriptor.len(),
@@ -720,7 +717,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
720 717
721 match dtype { 718 match dtype {
722 descriptor_type::BOS => InResponse::Accepted(self.bos_descriptor), 719 descriptor_type::BOS => InResponse::Accepted(self.bos_descriptor),
723 descriptor_type::DEVICE => InResponse::Accepted(self.device_descriptor), 720 descriptor_type::DEVICE => InResponse::Accepted(&self.device_descriptor),
724 descriptor_type::CONFIGURATION => InResponse::Accepted(self.config_descriptor), 721 descriptor_type::CONFIGURATION => InResponse::Accepted(self.config_descriptor),
725 descriptor_type::STRING => { 722 descriptor_type::STRING => {
726 if index == 0 { 723 if index == 0 {
diff --git a/embassy-usb/src/msos.rs b/embassy-usb/src/msos.rs
index 3858c0f51..25936d084 100644
--- a/embassy-usb/src/msos.rs
+++ b/embassy-usb/src/msos.rs
@@ -226,27 +226,21 @@ pub mod windows_version {
226 pub const WIN10: u32 = 0x0A000000; 226 pub const WIN10: u32 = 0x0A000000;
227} 227}
228 228
229mod sealed { 229/// A trait for descriptors
230 use core::mem::size_of; 230trait Descriptor: Sized {
231 const TYPE: DescriptorType;
231 232
232 /// A trait for descriptors 233 /// The size of the descriptor's header.
233 pub trait Descriptor: Sized { 234 fn size(&self) -> usize {
234 const TYPE: super::DescriptorType; 235 size_of::<Self>()
235
236 /// The size of the descriptor's header.
237 fn size(&self) -> usize {
238 size_of::<Self>()
239 }
240
241 fn write_to(&self, buf: &mut [u8]);
242 } 236 }
243 237
244 pub trait DescriptorSet: Descriptor { 238 fn write_to(&self, buf: &mut [u8]);
245 const LENGTH_OFFSET: usize;
246 }
247} 239}
248 240
249use sealed::*; 241trait DescriptorSet: Descriptor {
242 const LENGTH_OFFSET: usize;
243}
250 244
251/// Copies the data of `t` into `buf`. 245/// Copies the data of `t` into `buf`.
252/// 246///
@@ -255,7 +249,7 @@ use sealed::*;
255unsafe fn transmute_write_to<T: Sized>(t: &T, buf: &mut [u8]) { 249unsafe fn transmute_write_to<T: Sized>(t: &T, buf: &mut [u8]) {
256 let bytes = core::slice::from_raw_parts((t as *const T) as *const u8, size_of::<T>()); 250 let bytes = core::slice::from_raw_parts((t as *const T) as *const u8, size_of::<T>());
257 assert!(buf.len() >= bytes.len(), "MS OS descriptor buffer full"); 251 assert!(buf.len() >= bytes.len(), "MS OS descriptor buffer full");
258 (&mut buf[..bytes.len()]).copy_from_slice(bytes); 252 buf[..bytes.len()].copy_from_slice(bytes);
259} 253}
260 254
261/// Table 9. Microsoft OS 2.0 descriptor wDescriptorType values. 255/// Table 9. Microsoft OS 2.0 descriptor wDescriptorType values.
@@ -412,9 +406,11 @@ impl DescriptorSet for FunctionSubsetHeader {
412// Feature Descriptors 406// Feature Descriptors
413 407
414/// A marker trait for feature descriptors that are valid at the device level. 408/// A marker trait for feature descriptors that are valid at the device level.
409#[allow(private_bounds)]
415pub trait DeviceLevelDescriptor: Descriptor {} 410pub trait DeviceLevelDescriptor: Descriptor {}
416 411
417/// A marker trait for feature descriptors that are valid at the function level. 412/// A marker trait for feature descriptors that are valid at the function level.
413#[allow(private_bounds)]
418pub trait FunctionLevelDescriptor: Descriptor {} 414pub trait FunctionLevelDescriptor: Descriptor {}
419 415
420/// Table 13. Microsoft OS 2.0 compatible ID descriptor. 416/// Table 13. Microsoft OS 2.0 compatible ID descriptor.
@@ -444,9 +440,9 @@ impl CompatibleIdFeatureDescriptor {
444 pub fn new(compatible_id: &str, sub_compatible_id: &str) -> Self { 440 pub fn new(compatible_id: &str, sub_compatible_id: &str) -> Self {
445 assert!(compatible_id.len() <= 8 && sub_compatible_id.len() <= 8); 441 assert!(compatible_id.len() <= 8 && sub_compatible_id.len() <= 8);
446 let mut cid = [0u8; 8]; 442 let mut cid = [0u8; 8];
447 (&mut cid[..compatible_id.len()]).copy_from_slice(compatible_id.as_bytes()); 443 cid[..compatible_id.len()].copy_from_slice(compatible_id.as_bytes());
448 let mut scid = [0u8; 8]; 444 let mut scid = [0u8; 8];
449 (&mut scid[..sub_compatible_id.len()]).copy_from_slice(sub_compatible_id.as_bytes()); 445 scid[..sub_compatible_id.len()].copy_from_slice(sub_compatible_id.as_bytes());
450 Self::new_raw(cid, scid) 446 Self::new_raw(cid, scid)
451 } 447 }
452 448
diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs
index 37c3d7d90..929d6802c 100644
--- a/examples/boot/application/stm32wb-dfu/src/main.rs
+++ b/examples/boot/application/stm32wb-dfu/src/main.rs
@@ -41,7 +41,6 @@ async fn main(_spawner: Spawner) {
41 config.product = Some("USB-DFU Runtime example"); 41 config.product = Some("USB-DFU Runtime example");
42 config.serial_number = Some("1235678"); 42 config.serial_number = Some("1235678");
43 43
44 let mut device_descriptor = [0; 256];
45 let mut config_descriptor = [0; 256]; 44 let mut config_descriptor = [0; 256];
46 let mut bos_descriptor = [0; 256]; 45 let mut bos_descriptor = [0; 256];
47 let mut control_buf = [0; 64]; 46 let mut control_buf = [0; 64];
@@ -49,7 +48,6 @@ async fn main(_spawner: Spawner) {
49 let mut builder = Builder::new( 48 let mut builder = Builder::new(
50 driver, 49 driver,
51 config, 50 config,
52 &mut device_descriptor,
53 &mut config_descriptor, 51 &mut config_descriptor,
54 &mut bos_descriptor, 52 &mut bos_descriptor,
55 &mut [], 53 &mut [],
diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs
index d989fbfdf..093b39f9d 100644
--- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs
+++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs
@@ -49,7 +49,6 @@ fn main() -> ! {
49 let mut buffer = AlignedBuffer([0; WRITE_SIZE]); 49 let mut buffer = AlignedBuffer([0; WRITE_SIZE]);
50 let updater = BlockingFirmwareUpdater::new(fw_config, &mut buffer.0[..]); 50 let updater = BlockingFirmwareUpdater::new(fw_config, &mut buffer.0[..]);
51 51
52 let mut device_descriptor = [0; 256];
53 let mut config_descriptor = [0; 256]; 52 let mut config_descriptor = [0; 256];
54 let mut bos_descriptor = [0; 256]; 53 let mut bos_descriptor = [0; 256];
55 let mut control_buf = [0; 4096]; 54 let mut control_buf = [0; 4096];
@@ -57,7 +56,6 @@ fn main() -> ! {
57 let mut builder = Builder::new( 56 let mut builder = Builder::new(
58 driver, 57 driver,
59 config, 58 config,
60 &mut device_descriptor,
61 &mut config_descriptor, 59 &mut config_descriptor,
62 &mut bos_descriptor, 60 &mut bos_descriptor,
63 &mut [], 61 &mut [],
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs
index 3469c6e5f..a7e5c2668 100644
--- a/examples/nrf52840/src/bin/usb_ethernet.rs
+++ b/examples/nrf52840/src/bin/usb_ethernet.rs
@@ -70,7 +70,6 @@ async fn main(spawner: Spawner) {
70 config.device_protocol = 0x01; 70 config.device_protocol = 0x01;
71 71
72 // Create embassy-usb DeviceBuilder using the driver and config. 72 // Create embassy-usb DeviceBuilder using the driver and config.
73 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
74 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 73 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
75 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 74 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
76 static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new(); 75 static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new();
@@ -78,7 +77,6 @@ async fn main(spawner: Spawner) {
78 let mut builder = Builder::new( 77 let mut builder = Builder::new(
79 driver, 78 driver,
80 config, 79 config,
81 &mut DEVICE_DESC.init([0; 256])[..],
82 &mut CONFIG_DESC.init([0; 256])[..], 80 &mut CONFIG_DESC.init([0; 256])[..],
83 &mut BOS_DESC.init([0; 256])[..], 81 &mut BOS_DESC.init([0; 256])[..],
84 &mut MSOS_DESC.init([0; 128])[..], 82 &mut MSOS_DESC.init([0; 128])[..],
diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
index 3e86590c4..52f081487 100644
--- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
@@ -50,7 +50,6 @@ async fn main(_spawner: Spawner) {
50 50
51 // Create embassy-usb DeviceBuilder using the driver and config. 51 // Create embassy-usb DeviceBuilder using the driver and config.
52 // It needs some buffers for building the descriptors. 52 // It needs some buffers for building the descriptors.
53 let mut device_descriptor = [0; 256];
54 let mut config_descriptor = [0; 256]; 53 let mut config_descriptor = [0; 256];
55 let mut bos_descriptor = [0; 256]; 54 let mut bos_descriptor = [0; 256];
56 let mut msos_descriptor = [0; 256]; 55 let mut msos_descriptor = [0; 256];
@@ -63,7 +62,6 @@ async fn main(_spawner: Spawner) {
63 let mut builder = Builder::new( 62 let mut builder = Builder::new(
64 driver, 63 driver,
65 config, 64 config,
66 &mut device_descriptor,
67 &mut config_descriptor, 65 &mut config_descriptor,
68 &mut bos_descriptor, 66 &mut bos_descriptor,
69 &mut msos_descriptor, 67 &mut msos_descriptor,
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs
index 04ad841b7..5d2837793 100644
--- a/examples/nrf52840/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs
@@ -43,7 +43,6 @@ async fn main(_spawner: Spawner) {
43 43
44 // Create embassy-usb DeviceBuilder using the driver and config. 44 // Create embassy-usb DeviceBuilder using the driver and config.
45 // It needs some buffers for building the descriptors. 45 // It needs some buffers for building the descriptors.
46 let mut device_descriptor = [0; 256];
47 let mut config_descriptor = [0; 256]; 46 let mut config_descriptor = [0; 256];
48 let mut bos_descriptor = [0; 256]; 47 let mut bos_descriptor = [0; 256];
49 let mut msos_descriptor = [0; 256]; 48 let mut msos_descriptor = [0; 256];
@@ -55,7 +54,6 @@ async fn main(_spawner: Spawner) {
55 let mut builder = Builder::new( 54 let mut builder = Builder::new(
56 driver, 55 driver,
57 config, 56 config,
58 &mut device_descriptor,
59 &mut config_descriptor, 57 &mut config_descriptor,
60 &mut bos_descriptor, 58 &mut bos_descriptor,
61 &mut msos_descriptor, 59 &mut msos_descriptor,
diff --git a/examples/nrf52840/src/bin/usb_serial.rs b/examples/nrf52840/src/bin/usb_serial.rs
index aff539b1b..02048e692 100644
--- a/examples/nrf52840/src/bin/usb_serial.rs
+++ b/examples/nrf52840/src/bin/usb_serial.rs
@@ -48,7 +48,6 @@ async fn main(_spawner: Spawner) {
48 48
49 // Create embassy-usb DeviceBuilder using the driver and config. 49 // Create embassy-usb DeviceBuilder using the driver and config.
50 // It needs some buffers for building the descriptors. 50 // It needs some buffers for building the descriptors.
51 let mut device_descriptor = [0; 256];
52 let mut config_descriptor = [0; 256]; 51 let mut config_descriptor = [0; 256];
53 let mut bos_descriptor = [0; 256]; 52 let mut bos_descriptor = [0; 256];
54 let mut msos_descriptor = [0; 256]; 53 let mut msos_descriptor = [0; 256];
@@ -59,7 +58,6 @@ async fn main(_spawner: Spawner) {
59 let mut builder = Builder::new( 58 let mut builder = Builder::new(
60 driver, 59 driver,
61 config, 60 config,
62 &mut device_descriptor,
63 &mut config_descriptor, 61 &mut config_descriptor,
64 &mut bos_descriptor, 62 &mut bos_descriptor,
65 &mut msos_descriptor, 63 &mut msos_descriptor,
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs
index 4e8118fb8..895cca8b9 100644
--- a/examples/nrf52840/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs
@@ -67,7 +67,6 @@ async fn main(spawner: Spawner) {
67 let state = STATE.init(State::new()); 67 let state = STATE.init(State::new());
68 68
69 // Create embassy-usb DeviceBuilder using the driver and config. 69 // Create embassy-usb DeviceBuilder using the driver and config.
70 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
71 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 70 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
72 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 71 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
73 static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new(); 72 static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new();
@@ -75,7 +74,6 @@ async fn main(spawner: Spawner) {
75 let mut builder = Builder::new( 74 let mut builder = Builder::new(
76 driver, 75 driver,
77 config, 76 config,
78 &mut DEVICE_DESC.init([0; 256])[..],
79 &mut CONFIG_DESC.init([0; 256])[..], 77 &mut CONFIG_DESC.init([0; 256])[..],
80 &mut BOS_DESC.init([0; 256])[..], 78 &mut BOS_DESC.init([0; 256])[..],
81 &mut MSOS_DESC.init([0; 128])[..], 79 &mut MSOS_DESC.init([0; 128])[..],
diff --git a/examples/nrf52840/src/bin/usb_serial_winusb.rs b/examples/nrf52840/src/bin/usb_serial_winusb.rs
index 060f9ba94..c6675a3d3 100644
--- a/examples/nrf52840/src/bin/usb_serial_winusb.rs
+++ b/examples/nrf52840/src/bin/usb_serial_winusb.rs
@@ -53,7 +53,6 @@ async fn main(_spawner: Spawner) {
53 53
54 // Create embassy-usb DeviceBuilder using the driver and config. 54 // Create embassy-usb DeviceBuilder using the driver and config.
55 // It needs some buffers for building the descriptors. 55 // It needs some buffers for building the descriptors.
56 let mut device_descriptor = [0; 256];
57 let mut config_descriptor = [0; 256]; 56 let mut config_descriptor = [0; 256];
58 let mut bos_descriptor = [0; 256]; 57 let mut bos_descriptor = [0; 256];
59 let mut msos_descriptor = [0; 256]; 58 let mut msos_descriptor = [0; 256];
@@ -64,7 +63,6 @@ async fn main(_spawner: Spawner) {
64 let mut builder = Builder::new( 63 let mut builder = Builder::new(
65 driver, 64 driver,
66 config, 65 config,
67 &mut device_descriptor,
68 &mut config_descriptor, 66 &mut config_descriptor,
69 &mut bos_descriptor, 67 &mut bos_descriptor,
70 &mut msos_descriptor, 68 &mut msos_descriptor,
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs
index c7b087476..7cb546c91 100644
--- a/examples/rp/src/bin/multicore.rs
+++ b/examples/rp/src/bin/multicore.rs
@@ -30,10 +30,14 @@ fn main() -> ! {
30 let p = embassy_rp::init(Default::default()); 30 let p = embassy_rp::init(Default::default());
31 let led = Output::new(p.PIN_25, Level::Low); 31 let led = Output::new(p.PIN_25, Level::Low);
32 32
33 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { 33 spawn_core1(
34 let executor1 = EXECUTOR1.init(Executor::new()); 34 p.CORE1,
35 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); 35 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
36 }); 36 move || {
37 let executor1 = EXECUTOR1.init(Executor::new());
38 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led))));
39 },
40 );
37 41
38 let executor0 = EXECUTOR0.init(Executor::new()); 42 let executor0 = EXECUTOR0.init(Executor::new());
39 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); 43 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task())));
diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs
index a07f1c180..53b696309 100644
--- a/examples/rp/src/bin/pio_uart.rs
+++ b/examples/rp/src/bin/pio_uart.rs
@@ -60,7 +60,6 @@ async fn main(_spawner: Spawner) {
60 60
61 // Create embassy-usb DeviceBuilder using the driver and config. 61 // Create embassy-usb DeviceBuilder using the driver and config.
62 // It needs some buffers for building the descriptors. 62 // It needs some buffers for building the descriptors.
63 let mut device_descriptor = [0; 256];
64 let mut config_descriptor = [0; 256]; 63 let mut config_descriptor = [0; 256];
65 let mut bos_descriptor = [0; 256]; 64 let mut bos_descriptor = [0; 256];
66 let mut control_buf = [0; 64]; 65 let mut control_buf = [0; 64];
@@ -70,7 +69,6 @@ async fn main(_spawner: Spawner) {
70 let mut builder = Builder::new( 69 let mut builder = Builder::new(
71 driver, 70 driver,
72 config, 71 config,
73 &mut device_descriptor,
74 &mut config_descriptor, 72 &mut config_descriptor,
75 &mut bos_descriptor, 73 &mut bos_descriptor,
76 &mut [], // no msos descriptors 74 &mut [], // no msos descriptors
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index 01f0d5967..f1b124efa 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -64,14 +64,12 @@ async fn main(spawner: Spawner) {
64 config.device_protocol = 0x01; 64 config.device_protocol = 0x01;
65 65
66 // Create embassy-usb DeviceBuilder using the driver and config. 66 // Create embassy-usb DeviceBuilder using the driver and config.
67 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
68 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 67 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
69 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 68 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
70 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new(); 69 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
71 let mut builder = Builder::new( 70 let mut builder = Builder::new(
72 driver, 71 driver,
73 config, 72 config,
74 &mut DEVICE_DESC.init([0; 256])[..],
75 &mut CONFIG_DESC.init([0; 256])[..], 73 &mut CONFIG_DESC.init([0; 256])[..],
76 &mut BOS_DESC.init([0; 256])[..], 74 &mut BOS_DESC.init([0; 256])[..],
77 &mut [], // no msos descriptors 75 &mut [], // no msos descriptors
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs
index b5ac16245..710be8d13 100644
--- a/examples/rp/src/bin/usb_hid_keyboard.rs
+++ b/examples/rp/src/bin/usb_hid_keyboard.rs
@@ -36,7 +36,6 @@ async fn main(_spawner: Spawner) {
36 36
37 // Create embassy-usb DeviceBuilder using the driver and config. 37 // Create embassy-usb DeviceBuilder using the driver and config.
38 // It needs some buffers for building the descriptors. 38 // It needs some buffers for building the descriptors.
39 let mut device_descriptor = [0; 256];
40 let mut config_descriptor = [0; 256]; 39 let mut config_descriptor = [0; 256];
41 let mut bos_descriptor = [0; 256]; 40 let mut bos_descriptor = [0; 256];
42 // You can also add a Microsoft OS descriptor. 41 // You can also add a Microsoft OS descriptor.
@@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) {
50 let mut builder = Builder::new( 49 let mut builder = Builder::new(
51 driver, 50 driver,
52 config, 51 config,
53 &mut device_descriptor,
54 &mut config_descriptor, 52 &mut config_descriptor,
55 &mut bos_descriptor, 53 &mut bos_descriptor,
56 &mut msos_descriptor, 54 &mut msos_descriptor,
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs
index afebd8813..e8b399cb1 100644
--- a/examples/rp/src/bin/usb_hid_mouse.rs
+++ b/examples/rp/src/bin/usb_hid_mouse.rs
@@ -39,7 +39,6 @@ async fn main(_spawner: Spawner) {
39 39
40 // Create embassy-usb DeviceBuilder using the driver and config. 40 // Create embassy-usb DeviceBuilder using the driver and config.
41 // It needs some buffers for building the descriptors. 41 // It needs some buffers for building the descriptors.
42 let mut device_descriptor = [0; 256];
43 let mut config_descriptor = [0; 256]; 42 let mut config_descriptor = [0; 256];
44 let mut bos_descriptor = [0; 256]; 43 let mut bos_descriptor = [0; 256];
45 // You can also add a Microsoft OS descriptor. 44 // You can also add a Microsoft OS descriptor.
@@ -53,7 +52,6 @@ async fn main(_spawner: Spawner) {
53 let mut builder = Builder::new( 52 let mut builder = Builder::new(
54 driver, 53 driver,
55 config, 54 config,
56 &mut device_descriptor,
57 &mut config_descriptor, 55 &mut config_descriptor,
58 &mut bos_descriptor, 56 &mut bos_descriptor,
59 &mut msos_descriptor, 57 &mut msos_descriptor,
diff --git a/examples/rp/src/bin/usb_midi.rs b/examples/rp/src/bin/usb_midi.rs
index 95306a35c..11db1b2e1 100644
--- a/examples/rp/src/bin/usb_midi.rs
+++ b/examples/rp/src/bin/usb_midi.rs
@@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) {
46 46
47 // Create embassy-usb DeviceBuilder using the driver and config. 47 // Create embassy-usb DeviceBuilder using the driver and config.
48 // It needs some buffers for building the descriptors. 48 // It needs some buffers for building the descriptors.
49 let mut device_descriptor = [0; 256];
50 let mut config_descriptor = [0; 256]; 49 let mut config_descriptor = [0; 256];
51 let mut bos_descriptor = [0; 256]; 50 let mut bos_descriptor = [0; 256];
52 let mut control_buf = [0; 64]; 51 let mut control_buf = [0; 64];
@@ -54,7 +53,6 @@ async fn main(_spawner: Spawner) {
54 let mut builder = Builder::new( 53 let mut builder = Builder::new(
55 driver, 54 driver,
56 config, 55 config,
57 &mut device_descriptor,
58 &mut config_descriptor, 56 &mut config_descriptor,
59 &mut bos_descriptor, 57 &mut bos_descriptor,
60 &mut [], // no msos descriptors 58 &mut [], // no msos descriptors
diff --git a/examples/rp/src/bin/usb_raw.rs b/examples/rp/src/bin/usb_raw.rs
index a6c8a5b2e..97e7e0244 100644
--- a/examples/rp/src/bin/usb_raw.rs
+++ b/examples/rp/src/bin/usb_raw.rs
@@ -93,7 +93,6 @@ async fn main(_spawner: Spawner) {
93 93
94 // Create embassy-usb DeviceBuilder using the driver and config. 94 // Create embassy-usb DeviceBuilder using the driver and config.
95 // It needs some buffers for building the descriptors. 95 // It needs some buffers for building the descriptors.
96 let mut device_descriptor = [0; 256];
97 let mut config_descriptor = [0; 256]; 96 let mut config_descriptor = [0; 256];
98 let mut bos_descriptor = [0; 256]; 97 let mut bos_descriptor = [0; 256];
99 let mut msos_descriptor = [0; 256]; 98 let mut msos_descriptor = [0; 256];
@@ -106,7 +105,6 @@ async fn main(_spawner: Spawner) {
106 let mut builder = Builder::new( 105 let mut builder = Builder::new(
107 driver, 106 driver,
108 config, 107 config,
109 &mut device_descriptor,
110 &mut config_descriptor, 108 &mut config_descriptor,
111 &mut bos_descriptor, 109 &mut bos_descriptor,
112 &mut msos_descriptor, 110 &mut msos_descriptor,
diff --git a/examples/rp/src/bin/usb_raw_bulk.rs b/examples/rp/src/bin/usb_raw_bulk.rs
index 0dc8e9f72..331c3da4c 100644
--- a/examples/rp/src/bin/usb_raw_bulk.rs
+++ b/examples/rp/src/bin/usb_raw_bulk.rs
@@ -71,7 +71,6 @@ async fn main(_spawner: Spawner) {
71 71
72 // Create embassy-usb DeviceBuilder using the driver and config. 72 // Create embassy-usb DeviceBuilder using the driver and config.
73 // It needs some buffers for building the descriptors. 73 // It needs some buffers for building the descriptors.
74 let mut device_descriptor = [0; 256];
75 let mut config_descriptor = [0; 256]; 74 let mut config_descriptor = [0; 256];
76 let mut bos_descriptor = [0; 256]; 75 let mut bos_descriptor = [0; 256];
77 let mut msos_descriptor = [0; 256]; 76 let mut msos_descriptor = [0; 256];
@@ -80,7 +79,6 @@ async fn main(_spawner: Spawner) {
80 let mut builder = Builder::new( 79 let mut builder = Builder::new(
81 driver, 80 driver,
82 config, 81 config,
83 &mut device_descriptor,
84 &mut config_descriptor, 82 &mut config_descriptor,
85 &mut bos_descriptor, 83 &mut bos_descriptor,
86 &mut msos_descriptor, 84 &mut msos_descriptor,
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index ab24a994c..3c9bc96dd 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) {
46 46
47 // Create embassy-usb DeviceBuilder using the driver and config. 47 // Create embassy-usb DeviceBuilder using the driver and config.
48 // It needs some buffers for building the descriptors. 48 // It needs some buffers for building the descriptors.
49 let mut device_descriptor = [0; 256];
50 let mut config_descriptor = [0; 256]; 49 let mut config_descriptor = [0; 256];
51 let mut bos_descriptor = [0; 256]; 50 let mut bos_descriptor = [0; 256];
52 let mut control_buf = [0; 64]; 51 let mut control_buf = [0; 64];
@@ -56,7 +55,6 @@ async fn main(_spawner: Spawner) {
56 let mut builder = Builder::new( 55 let mut builder = Builder::new(
57 driver, 56 driver,
58 config, 57 config,
59 &mut device_descriptor,
60 &mut config_descriptor, 58 &mut config_descriptor,
61 &mut bos_descriptor, 59 &mut bos_descriptor,
62 &mut [], // no msos descriptors 60 &mut [], // no msos descriptors
diff --git a/examples/rp/src/bin/usb_serial_with_logger.rs b/examples/rp/src/bin/usb_serial_with_logger.rs
index 4ba4fc25c..f9cfdef94 100644
--- a/examples/rp/src/bin/usb_serial_with_logger.rs
+++ b/examples/rp/src/bin/usb_serial_with_logger.rs
@@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) {
46 46
47 // Create embassy-usb DeviceBuilder using the driver and config. 47 // Create embassy-usb DeviceBuilder using the driver and config.
48 // It needs some buffers for building the descriptors. 48 // It needs some buffers for building the descriptors.
49 let mut device_descriptor = [0; 256];
50 let mut config_descriptor = [0; 256]; 49 let mut config_descriptor = [0; 256];
51 let mut bos_descriptor = [0; 256]; 50 let mut bos_descriptor = [0; 256];
52 let mut control_buf = [0; 64]; 51 let mut control_buf = [0; 64];
@@ -57,7 +56,6 @@ async fn main(_spawner: Spawner) {
57 let mut builder = Builder::new( 56 let mut builder = Builder::new(
58 driver, 57 driver,
59 config, 58 config,
60 &mut device_descriptor,
61 &mut config_descriptor, 59 &mut config_descriptor,
62 &mut bos_descriptor, 60 &mut bos_descriptor,
63 &mut [], // no msos descriptors 61 &mut [], // no msos descriptors
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs
index dad93d0a1..59813d8cb 100644
--- a/examples/std/src/bin/net.rs
+++ b/examples/std/src/bin/net.rs
@@ -1,5 +1,3 @@
1use std::default::Default;
2
3use clap::Parser; 1use clap::Parser;
4use embassy_executor::{Executor, Spawner}; 2use embassy_executor::{Executor, Spawner};
5use embassy_net::tcp::TcpSocket; 3use embassy_net::tcp::TcpSocket;
diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs
index fca1e076e..3b6a3de37 100644
--- a/examples/std/src/bin/net_dns.rs
+++ b/examples/std/src/bin/net_dns.rs
@@ -1,5 +1,3 @@
1use std::default::Default;
2
3use clap::Parser; 1use clap::Parser;
4use embassy_executor::{Executor, Spawner}; 2use embassy_executor::{Executor, Spawner};
5use embassy_net::dns::DnsQueryType; 3use embassy_net::dns::DnsQueryType;
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs
index 00ccd83a7..e8b6eaa6c 100644
--- a/examples/std/src/bin/tcp_accept.rs
+++ b/examples/std/src/bin/tcp_accept.rs
@@ -1,5 +1,4 @@
1use core::fmt::Write as _; 1use core::fmt::Write as _;
2use std::default::Default;
3 2
4use clap::Parser; 3use clap::Parser;
5use embassy_executor::{Executor, Spawner}; 4use embassy_executor::{Executor, Spawner};
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs
index 1ae6c1dee..ee99acf41 100644
--- a/examples/stm32f1/src/bin/usb_serial.rs
+++ b/examples/stm32f1/src/bin/usb_serial.rs
@@ -60,7 +60,6 @@ async fn main(_spawner: Spawner) {
60 60
61 // Create embassy-usb DeviceBuilder using the driver and config. 61 // Create embassy-usb DeviceBuilder using the driver and config.
62 // It needs some buffers for building the descriptors. 62 // It needs some buffers for building the descriptors.
63 let mut device_descriptor = [0; 256];
64 let mut config_descriptor = [0; 256]; 63 let mut config_descriptor = [0; 256];
65 let mut bos_descriptor = [0; 256]; 64 let mut bos_descriptor = [0; 256];
66 let mut control_buf = [0; 7]; 65 let mut control_buf = [0; 7];
@@ -70,7 +69,6 @@ async fn main(_spawner: Spawner) {
70 let mut builder = Builder::new( 69 let mut builder = Builder::new(
71 driver, 70 driver,
72 config, 71 config,
73 &mut device_descriptor,
74 &mut config_descriptor, 72 &mut config_descriptor,
75 &mut bos_descriptor, 73 &mut bos_descriptor,
76 &mut [], // no msos descriptors 74 &mut [], // no msos descriptors
diff --git a/examples/stm32f2/src/bin/pll.rs b/examples/stm32f2/src/bin/pll.rs
index e32f283d1..e39e2daec 100644
--- a/examples/stm32f2/src/bin/pll.rs
+++ b/examples/stm32f2/src/bin/pll.rs
@@ -1,8 +1,6 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::convert::TryFrom;
5
6use defmt::*; 4use defmt::*;
7use embassy_executor::Spawner; 5use embassy_executor::Spawner;
8use embassy_stm32::time::Hertz; 6use embassy_stm32::time::Hertz;
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs
index ee1c43afd..5760f2c1c 100644
--- a/examples/stm32f3/src/bin/usb_serial.rs
+++ b/examples/stm32f3/src/bin/usb_serial.rs
@@ -54,7 +54,6 @@ async fn main(_spawner: Spawner) {
54 54
55 // Create embassy-usb DeviceBuilder using the driver and config. 55 // Create embassy-usb DeviceBuilder using the driver and config.
56 // It needs some buffers for building the descriptors. 56 // It needs some buffers for building the descriptors.
57 let mut device_descriptor = [0; 256];
58 let mut config_descriptor = [0; 256]; 57 let mut config_descriptor = [0; 256];
59 let mut bos_descriptor = [0; 256]; 58 let mut bos_descriptor = [0; 256];
60 let mut control_buf = [0; 7]; 59 let mut control_buf = [0; 7];
@@ -64,7 +63,6 @@ async fn main(_spawner: Spawner) {
64 let mut builder = Builder::new( 63 let mut builder = Builder::new(
65 driver, 64 driver,
66 config, 65 config,
67 &mut device_descriptor,
68 &mut config_descriptor, 66 &mut config_descriptor,
69 &mut bos_descriptor, 67 &mut bos_descriptor,
70 &mut [], // no msos descriptors 68 &mut [], // no msos descriptors
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs
index a196259a8..d2cbeea1b 100644
--- a/examples/stm32f4/src/bin/usb_ethernet.rs
+++ b/examples/stm32f4/src/bin/usb_ethernet.rs
@@ -7,8 +7,8 @@ use embassy_net::tcp::TcpSocket;
7use embassy_net::{Stack, StackResources}; 7use embassy_net::{Stack, StackResources};
8use embassy_stm32::rng::{self, Rng}; 8use embassy_stm32::rng::{self, Rng};
9use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
10use embassy_stm32::usb_otg::Driver; 10use embassy_stm32::usb::Driver;
11use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 11use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
12use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 12use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
13use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 13use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
14use embassy_usb::{Builder, UsbDevice}; 14use embassy_usb::{Builder, UsbDevice};
@@ -36,7 +36,7 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
36} 36}
37 37
38bind_interrupts!(struct Irqs { 38bind_interrupts!(struct Irqs {
39 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 39 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
40 HASH_RNG => rng::InterruptHandler<peripherals::RNG>; 40 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
41}); 41});
42 42
@@ -63,13 +63,14 @@ async fn main(spawner: Spawner) {
63 config.rcc.apb1_pre = APBPrescaler::DIV4; 63 config.rcc.apb1_pre = APBPrescaler::DIV4;
64 config.rcc.apb2_pre = APBPrescaler::DIV2; 64 config.rcc.apb2_pre = APBPrescaler::DIV2;
65 config.rcc.sys = Sysclk::PLL1_P; 65 config.rcc.sys = Sysclk::PLL1_P;
66 config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
66 } 67 }
67 let p = embassy_stm32::init(config); 68 let p = embassy_stm32::init(config);
68 69
69 // Create the driver, from the HAL. 70 // Create the driver, from the HAL.
70 static OUTPUT_BUFFER: StaticCell<[u8; 256]> = StaticCell::new(); 71 static OUTPUT_BUFFER: StaticCell<[u8; 256]> = StaticCell::new();
71 let ep_out_buffer = &mut OUTPUT_BUFFER.init([0; 256])[..]; 72 let ep_out_buffer = &mut OUTPUT_BUFFER.init([0; 256])[..];
72 let mut config = embassy_stm32::usb_otg::Config::default(); 73 let mut config = embassy_stm32::usb::Config::default();
73 config.vbus_detection = true; 74 config.vbus_detection = true;
74 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config); 75 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config);
75 76
@@ -88,14 +89,12 @@ async fn main(spawner: Spawner) {
88 config.device_protocol = 0x01; 89 config.device_protocol = 0x01;
89 90
90 // Create embassy-usb DeviceBuilder using the driver and config. 91 // Create embassy-usb DeviceBuilder using the driver and config.
91 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
92 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 92 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
93 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 93 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
94 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new(); 94 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
95 let mut builder = Builder::new( 95 let mut builder = Builder::new(
96 driver, 96 driver,
97 config, 97 config,
98 &mut DEVICE_DESC.init([0; 256])[..],
99 &mut CONFIG_DESC.init([0; 256])[..], 98 &mut CONFIG_DESC.init([0; 256])[..],
100 &mut BOS_DESC.init([0; 256])[..], 99 &mut BOS_DESC.init([0; 256])[..],
101 &mut [], // no msos descriptors 100 &mut [], // no msos descriptors
diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs
index 19b5971fb..a799b4e72 100644
--- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs
+++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs
@@ -8,8 +8,8 @@ use embassy_executor::Spawner;
8use embassy_stm32::exti::ExtiInput; 8use embassy_stm32::exti::ExtiInput;
9use embassy_stm32::gpio::Pull; 9use embassy_stm32::gpio::Pull;
10use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
11use embassy_stm32::usb_otg::Driver; 11use embassy_stm32::usb::Driver;
12use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 12use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
13use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 13use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
14use embassy_usb::control::OutResponse; 14use embassy_usb::control::OutResponse;
15use embassy_usb::{Builder, Handler}; 15use embassy_usb::{Builder, Handler};
@@ -18,7 +18,7 @@ use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
20bind_interrupts!(struct Irqs { 20bind_interrupts!(struct Irqs {
21 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 21 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
22}); 22});
23 23
24#[embassy_executor::main] 24#[embassy_executor::main]
@@ -42,12 +42,13 @@ async fn main(_spawner: Spawner) {
42 config.rcc.apb1_pre = APBPrescaler::DIV4; 42 config.rcc.apb1_pre = APBPrescaler::DIV4;
43 config.rcc.apb2_pre = APBPrescaler::DIV2; 43 config.rcc.apb2_pre = APBPrescaler::DIV2;
44 config.rcc.sys = Sysclk::PLL1_P; 44 config.rcc.sys = Sysclk::PLL1_P;
45 config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
45 } 46 }
46 let p = embassy_stm32::init(config); 47 let p = embassy_stm32::init(config);
47 48
48 // Create the driver, from the HAL. 49 // Create the driver, from the HAL.
49 let mut ep_out_buffer = [0u8; 256]; 50 let mut ep_out_buffer = [0u8; 256];
50 let mut config = embassy_stm32::usb_otg::Config::default(); 51 let mut config = embassy_stm32::usb::Config::default();
51 config.vbus_detection = true; 52 config.vbus_detection = true;
52 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 53 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
53 54
@@ -68,7 +69,6 @@ async fn main(_spawner: Spawner) {
68 69
69 // Create embassy-usb DeviceBuilder using the driver and config. 70 // Create embassy-usb DeviceBuilder using the driver and config.
70 // It needs some buffers for building the descriptors. 71 // It needs some buffers for building the descriptors.
71 let mut device_descriptor = [0; 256];
72 let mut config_descriptor = [0; 256]; 72 let mut config_descriptor = [0; 256];
73 let mut bos_descriptor = [0; 256]; 73 let mut bos_descriptor = [0; 256];
74 // You can also add a Microsoft OS descriptor. 74 // You can also add a Microsoft OS descriptor.
@@ -83,7 +83,6 @@ async fn main(_spawner: Spawner) {
83 let mut builder = Builder::new( 83 let mut builder = Builder::new(
84 driver, 84 driver,
85 config, 85 config,
86 &mut device_descriptor,
87 &mut config_descriptor, 86 &mut config_descriptor,
88 &mut bos_descriptor, 87 &mut bos_descriptor,
89 &mut msos_descriptor, 88 &mut msos_descriptor,
diff --git a/examples/stm32f4/src/bin/usb_hid_mouse.rs b/examples/stm32f4/src/bin/usb_hid_mouse.rs
index c98792880..0bc236119 100644
--- a/examples/stm32f4/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32f4/src/bin/usb_hid_mouse.rs
@@ -4,8 +4,8 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::time::Hertz; 6use embassy_stm32::time::Hertz;
7use embassy_stm32::usb_otg::Driver; 7use embassy_stm32::usb::Driver;
8use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 8use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
9use embassy_time::Timer; 9use embassy_time::Timer;
10use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 10use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
11use embassy_usb::control::OutResponse; 11use embassy_usb::control::OutResponse;
@@ -15,7 +15,7 @@ use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17bind_interrupts!(struct Irqs { 17bind_interrupts!(struct Irqs {
18 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 18 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
19}); 19});
20 20
21#[embassy_executor::main] 21#[embassy_executor::main]
@@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) {
39 config.rcc.apb1_pre = APBPrescaler::DIV4; 39 config.rcc.apb1_pre = APBPrescaler::DIV4;
40 config.rcc.apb2_pre = APBPrescaler::DIV2; 40 config.rcc.apb2_pre = APBPrescaler::DIV2;
41 config.rcc.sys = Sysclk::PLL1_P; 41 config.rcc.sys = Sysclk::PLL1_P;
42 config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
42 } 43 }
43 let p = embassy_stm32::init(config); 44 let p = embassy_stm32::init(config);
44 45
45 // Create the driver, from the HAL. 46 // Create the driver, from the HAL.
46 let mut ep_out_buffer = [0u8; 256]; 47 let mut ep_out_buffer = [0u8; 256];
47 let mut config = embassy_stm32::usb_otg::Config::default(); 48 let mut config = embassy_stm32::usb::Config::default();
48 config.vbus_detection = true; 49 config.vbus_detection = true;
49 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 50 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
50 51
@@ -63,7 +64,6 @@ async fn main(_spawner: Spawner) {
63 64
64 // Create embassy-usb DeviceBuilder using the driver and config. 65 // Create embassy-usb DeviceBuilder using the driver and config.
65 // It needs some buffers for building the descriptors. 66 // It needs some buffers for building the descriptors.
66 let mut device_descriptor = [0; 256];
67 let mut config_descriptor = [0; 256]; 67 let mut config_descriptor = [0; 256];
68 let mut bos_descriptor = [0; 256]; 68 let mut bos_descriptor = [0; 256];
69 let mut control_buf = [0; 64]; 69 let mut control_buf = [0; 64];
@@ -75,7 +75,6 @@ async fn main(_spawner: Spawner) {
75 let mut builder = Builder::new( 75 let mut builder = Builder::new(
76 driver, 76 driver,
77 config, 77 config,
78 &mut device_descriptor,
79 &mut config_descriptor, 78 &mut config_descriptor,
80 &mut bos_descriptor, 79 &mut bos_descriptor,
81 &mut [], // no msos descriptors 80 &mut [], // no msos descriptors
diff --git a/examples/stm32f4/src/bin/usb_raw.rs b/examples/stm32f4/src/bin/usb_raw.rs
index afff55187..4e583aeb8 100644
--- a/examples/stm32f4/src/bin/usb_raw.rs
+++ b/examples/stm32f4/src/bin/usb_raw.rs
@@ -52,8 +52,8 @@
52use defmt::*; 52use defmt::*;
53use embassy_executor::Spawner; 53use embassy_executor::Spawner;
54use embassy_stm32::time::Hertz; 54use embassy_stm32::time::Hertz;
55use embassy_stm32::usb_otg::Driver; 55use embassy_stm32::usb::Driver;
56use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 56use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
57use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType}; 57use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType};
58use embassy_usb::msos::{self, windows_version}; 58use embassy_usb::msos::{self, windows_version};
59use embassy_usb::types::InterfaceNumber; 59use embassy_usb::types::InterfaceNumber;
@@ -66,7 +66,7 @@ use {defmt_rtt as _, panic_probe as _};
66const DEVICE_INTERFACE_GUIDS: &[&str] = &["{DAC2087C-63FA-458D-A55D-827C0762DEC7}"]; 66const DEVICE_INTERFACE_GUIDS: &[&str] = &["{DAC2087C-63FA-458D-A55D-827C0762DEC7}"];
67 67
68bind_interrupts!(struct Irqs { 68bind_interrupts!(struct Irqs {
69 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 69 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
70}); 70});
71 71
72#[embassy_executor::main] 72#[embassy_executor::main]
@@ -92,12 +92,13 @@ async fn main(_spawner: Spawner) {
92 config.rcc.apb1_pre = APBPrescaler::DIV4; 92 config.rcc.apb1_pre = APBPrescaler::DIV4;
93 config.rcc.apb2_pre = APBPrescaler::DIV2; 93 config.rcc.apb2_pre = APBPrescaler::DIV2;
94 config.rcc.sys = Sysclk::PLL1_P; 94 config.rcc.sys = Sysclk::PLL1_P;
95 config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
95 } 96 }
96 let p = embassy_stm32::init(config); 97 let p = embassy_stm32::init(config);
97 98
98 // Create the driver, from the HAL. 99 // Create the driver, from the HAL.
99 let mut ep_out_buffer = [0u8; 256]; 100 let mut ep_out_buffer = [0u8; 256];
100 let mut config = embassy_stm32::usb_otg::Config::default(); 101 let mut config = embassy_stm32::usb::Config::default();
101 config.vbus_detection = true; 102 config.vbus_detection = true;
102 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 103 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
103 104
@@ -116,7 +117,6 @@ async fn main(_spawner: Spawner) {
116 117
117 // Create embassy-usb DeviceBuilder using the driver and config. 118 // Create embassy-usb DeviceBuilder using the driver and config.
118 // It needs some buffers for building the descriptors. 119 // It needs some buffers for building the descriptors.
119 let mut device_descriptor = [0; 256];
120 let mut config_descriptor = [0; 256]; 120 let mut config_descriptor = [0; 256];
121 let mut bos_descriptor = [0; 256]; 121 let mut bos_descriptor = [0; 256];
122 let mut msos_descriptor = [0; 256]; 122 let mut msos_descriptor = [0; 256];
@@ -129,7 +129,6 @@ async fn main(_spawner: Spawner) {
129 let mut builder = Builder::new( 129 let mut builder = Builder::new(
130 driver, 130 driver,
131 config, 131 config,
132 &mut device_descriptor,
133 &mut config_descriptor, 132 &mut config_descriptor,
134 &mut bos_descriptor, 133 &mut bos_descriptor,
135 &mut msos_descriptor, 134 &mut msos_descriptor,
diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs
index 58d994a61..f3a375d31 100644
--- a/examples/stm32f4/src/bin/usb_serial.rs
+++ b/examples/stm32f4/src/bin/usb_serial.rs
@@ -4,8 +4,8 @@
4use defmt::{panic, *}; 4use defmt::{panic, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::time::Hertz; 6use embassy_stm32::time::Hertz;
7use embassy_stm32::usb_otg::{Driver, Instance}; 7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 8use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 10use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder; 11use embassy_usb::Builder;
@@ -13,7 +13,7 @@ use futures::future::join;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
16 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 16 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
17}); 17});
18 18
19#[embassy_executor::main] 19#[embassy_executor::main]
@@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) {
39 config.rcc.apb1_pre = APBPrescaler::DIV4; 39 config.rcc.apb1_pre = APBPrescaler::DIV4;
40 config.rcc.apb2_pre = APBPrescaler::DIV2; 40 config.rcc.apb2_pre = APBPrescaler::DIV2;
41 config.rcc.sys = Sysclk::PLL1_P; 41 config.rcc.sys = Sysclk::PLL1_P;
42 config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
42 } 43 }
43 let p = embassy_stm32::init(config); 44 let p = embassy_stm32::init(config);
44 45
45 // Create the driver, from the HAL. 46 // Create the driver, from the HAL.
46 let mut ep_out_buffer = [0u8; 256]; 47 let mut ep_out_buffer = [0u8; 256];
47 let mut config = embassy_stm32::usb_otg::Config::default(); 48 let mut config = embassy_stm32::usb::Config::default();
48 config.vbus_detection = true; 49 config.vbus_detection = true;
49 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 50 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
50 51
@@ -63,7 +64,6 @@ async fn main(_spawner: Spawner) {
63 64
64 // Create embassy-usb DeviceBuilder using the driver and config. 65 // Create embassy-usb DeviceBuilder using the driver and config.
65 // It needs some buffers for building the descriptors. 66 // It needs some buffers for building the descriptors.
66 let mut device_descriptor = [0; 256];
67 let mut config_descriptor = [0; 256]; 67 let mut config_descriptor = [0; 256];
68 let mut bos_descriptor = [0; 256]; 68 let mut bos_descriptor = [0; 256];
69 let mut control_buf = [0; 64]; 69 let mut control_buf = [0; 64];
@@ -73,7 +73,6 @@ async fn main(_spawner: Spawner) {
73 let mut builder = Builder::new( 73 let mut builder = Builder::new(
74 driver, 74 driver,
75 config, 75 config,
76 &mut device_descriptor,
77 &mut config_descriptor, 76 &mut config_descriptor,
78 &mut bos_descriptor, 77 &mut bos_descriptor,
79 &mut [], // no msos descriptors 78 &mut [], // no msos descriptors
diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs
index 6122cea2d..cbaff75fc 100644
--- a/examples/stm32f4/src/bin/ws2812_pwm.rs
+++ b/examples/stm32f4/src/bin/ws2812_pwm.rs
@@ -15,8 +15,9 @@
15use embassy_executor::Spawner; 15use embassy_executor::Spawner;
16use embassy_stm32::gpio::OutputType; 16use embassy_stm32::gpio::OutputType;
17use embassy_stm32::time::khz; 17use embassy_stm32::time::khz;
18use embassy_stm32::timer::low_level::CountingMode;
18use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 19use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
19use embassy_stm32::timer::{Channel, CountingMode}; 20use embassy_stm32::timer::Channel;
20use embassy_time::{Duration, Ticker, Timer}; 21use embassy_time::{Duration, Ticker, Timer};
21use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
22 23
@@ -60,7 +61,7 @@ async fn main(_spawner: Spawner) {
60 // construct ws2812 non-return-to-zero (NRZ) code bit by bit 61 // construct ws2812 non-return-to-zero (NRZ) code bit by bit
61 // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low 62 // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low
62 63
63 let max_duty = ws2812_pwm.get_max_duty(); 64 let max_duty = ws2812_pwm.get_max_duty() as u16;
64 let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing 65 let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing
65 let n1 = 2 * n0; // ws2812 Bit 1 high level timing 66 let n1 = 2 * n0; // ws2812 Bit 1 high level timing
66 67
diff --git a/examples/stm32f7/src/bin/usb_serial.rs b/examples/stm32f7/src/bin/usb_serial.rs
index 97daf6bd1..39a5512f4 100644
--- a/examples/stm32f7/src/bin/usb_serial.rs
+++ b/examples/stm32f7/src/bin/usb_serial.rs
@@ -4,8 +4,8 @@
4use defmt::{panic, *}; 4use defmt::{panic, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::time::Hertz; 6use embassy_stm32::time::Hertz;
7use embassy_stm32::usb_otg::{Driver, Instance}; 7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 8use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 10use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder; 11use embassy_usb::Builder;
@@ -13,7 +13,7 @@ use futures::future::join;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
16 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 16 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
17}); 17});
18 18
19#[embassy_executor::main] 19#[embassy_executor::main]
@@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) {
39 config.rcc.apb1_pre = APBPrescaler::DIV4; 39 config.rcc.apb1_pre = APBPrescaler::DIV4;
40 config.rcc.apb2_pre = APBPrescaler::DIV2; 40 config.rcc.apb2_pre = APBPrescaler::DIV2;
41 config.rcc.sys = Sysclk::PLL1_P; 41 config.rcc.sys = Sysclk::PLL1_P;
42 config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
42 } 43 }
43 let p = embassy_stm32::init(config); 44 let p = embassy_stm32::init(config);
44 45
45 // Create the driver, from the HAL. 46 // Create the driver, from the HAL.
46 let mut ep_out_buffer = [0u8; 256]; 47 let mut ep_out_buffer = [0u8; 256];
47 let mut config = embassy_stm32::usb_otg::Config::default(); 48 let mut config = embassy_stm32::usb::Config::default();
48 config.vbus_detection = true; 49 config.vbus_detection = true;
49 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 50 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
50 51
@@ -63,7 +64,6 @@ async fn main(_spawner: Spawner) {
63 64
64 // Create embassy-usb DeviceBuilder using the driver and config. 65 // Create embassy-usb DeviceBuilder using the driver and config.
65 // It needs some buffers for building the descriptors. 66 // It needs some buffers for building the descriptors.
66 let mut device_descriptor = [0; 256];
67 let mut config_descriptor = [0; 256]; 67 let mut config_descriptor = [0; 256];
68 let mut bos_descriptor = [0; 256]; 68 let mut bos_descriptor = [0; 256];
69 let mut control_buf = [0; 64]; 69 let mut control_buf = [0; 64];
@@ -73,7 +73,6 @@ async fn main(_spawner: Spawner) {
73 let mut builder = Builder::new( 73 let mut builder = Builder::new(
74 driver, 74 driver,
75 config, 75 config,
76 &mut device_descriptor,
77 &mut config_descriptor, 76 &mut config_descriptor,
78 &mut bos_descriptor, 77 &mut bos_descriptor,
79 &mut [], // no msos descriptors 78 &mut [], // no msos descriptors
diff --git a/examples/stm32g0/src/bin/usb_serial.rs b/examples/stm32g0/src/bin/usb_serial.rs
index 8b9915626..162dfd86b 100644
--- a/examples/stm32g0/src/bin/usb_serial.rs
+++ b/examples/stm32g0/src/bin/usb_serial.rs
@@ -36,7 +36,6 @@ async fn main(_spawner: Spawner) {
36 36
37 // Create embassy-usb DeviceBuilder using the driver and config. 37 // Create embassy-usb DeviceBuilder using the driver and config.
38 // It needs some buffers for building the descriptors. 38 // It needs some buffers for building the descriptors.
39 let mut device_descriptor = [0; 256];
40 let mut config_descriptor = [0; 256]; 39 let mut config_descriptor = [0; 256];
41 let mut bos_descriptor = [0; 256]; 40 let mut bos_descriptor = [0; 256];
42 let mut control_buf = [0; 7]; 41 let mut control_buf = [0; 7];
@@ -46,7 +45,6 @@ async fn main(_spawner: Spawner) {
46 let mut builder = Builder::new( 45 let mut builder = Builder::new(
47 driver, 46 driver,
48 config, 47 config,
49 &mut device_descriptor,
50 &mut config_descriptor, 48 &mut config_descriptor,
51 &mut bos_descriptor, 49 &mut bos_descriptor,
52 &mut [], // no msos descriptors 50 &mut [], // no msos descriptors
diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs
index dc95aa6e5..dbe8f27c1 100644
--- a/examples/stm32g4/src/bin/usb_serial.rs
+++ b/examples/stm32g4/src/bin/usb_serial.rs
@@ -56,7 +56,6 @@ async fn main(_spawner: Spawner) {
56 config.device_protocol = 0x01; 56 config.device_protocol = 0x01;
57 config.composite_with_iads = true; 57 config.composite_with_iads = true;
58 58
59 let mut device_descriptor = [0; 256];
60 let mut config_descriptor = [0; 256]; 59 let mut config_descriptor = [0; 256];
61 let mut bos_descriptor = [0; 256]; 60 let mut bos_descriptor = [0; 256];
62 let mut control_buf = [0; 64]; 61 let mut control_buf = [0; 64];
@@ -66,7 +65,6 @@ async fn main(_spawner: Spawner) {
66 let mut builder = Builder::new( 65 let mut builder = Builder::new(
67 driver, 66 driver,
68 config, 67 config,
69 &mut device_descriptor,
70 &mut config_descriptor, 68 &mut config_descriptor,
71 &mut bos_descriptor, 69 &mut bos_descriptor,
72 &mut [], // no msos descriptors 70 &mut [], // no msos descriptors
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs
index 83477c8fa..4f86bb342 100644
--- a/examples/stm32h5/src/bin/usb_serial.rs
+++ b/examples/stm32h5/src/bin/usb_serial.rs
@@ -65,7 +65,6 @@ async fn main(_spawner: Spawner) {
65 65
66 // Create embassy-usb DeviceBuilder using the driver and config. 66 // Create embassy-usb DeviceBuilder using the driver and config.
67 // It needs some buffers for building the descriptors. 67 // It needs some buffers for building the descriptors.
68 let mut device_descriptor = [0; 256];
69 let mut config_descriptor = [0; 256]; 68 let mut config_descriptor = [0; 256];
70 let mut bos_descriptor = [0; 256]; 69 let mut bos_descriptor = [0; 256];
71 let mut control_buf = [0; 64]; 70 let mut control_buf = [0; 64];
@@ -75,7 +74,6 @@ async fn main(_spawner: Spawner) {
75 let mut builder = Builder::new( 74 let mut builder = Builder::new(
76 driver, 75 driver,
77 config, 76 config,
78 &mut device_descriptor,
79 &mut config_descriptor, 77 &mut config_descriptor,
80 &mut bos_descriptor, 78 &mut bos_descriptor,
81 &mut [], // no msos descriptors 79 &mut [], // no msos descriptors
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs
index e5a104baf..170a5aa28 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -78,9 +78,9 @@ async fn main(_spawner: Spawner) {
78 ); 78 );
79 79
80 defmt::info!("attempting capture"); 80 defmt::info!("attempting capture");
81 defmt::unwrap!(dcmi.capture(unsafe { &mut FRAME }).await); 81 defmt::unwrap!(dcmi.capture(unsafe { &mut *core::ptr::addr_of_mut!(FRAME) }).await);
82 82
83 defmt::info!("captured frame: {:x}", unsafe { &FRAME }); 83 defmt::info!("captured frame: {:x}", unsafe { &*core::ptr::addr_of!(FRAME) });
84 84
85 defmt::info!("main loop running"); 85 defmt::info!("main loop running");
86 loop { 86 loop {
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
index feec28993..3a9887e3c 100644
--- a/examples/stm32h7/src/bin/dac_dma.rs
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -6,9 +6,9 @@ use embassy_executor::Spawner;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::pac::timer::vals::Mms; 7use embassy_stm32::pac::timer::vals::Mms;
8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; 8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7};
9use embassy_stm32::rcc::low_level::RccPeripheral; 9use embassy_stm32::rcc::frequency;
10use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
11use embassy_stm32::timer::low_level::BasicInstance; 11use embassy_stm32::timer::low_level::Timer;
12use micromath::F32Ext; 12use micromath::F32Ext;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
@@ -51,19 +51,19 @@ async fn main(spawner: Spawner) {
51 // Obtain two independent channels (p.DAC1 can only be consumed once, though!) 51 // Obtain two independent channels (p.DAC1 can only be consumed once, though!)
52 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); 52 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split();
53 53
54 spawner.spawn(dac_task1(dac_ch1)).ok(); 54 spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok();
55 spawner.spawn(dac_task2(dac_ch2)).ok(); 55 spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok();
56} 56}
57 57
58#[embassy_executor::task] 58#[embassy_executor::task]
59async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { 59async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) {
60 let data: &[u8; 256] = &calculate_array::<256>(); 60 let data: &[u8; 256] = &calculate_array::<256>();
61 61
62 info!("TIM6 frequency is {}", TIM6::frequency()); 62 info!("TIM6 frequency is {}", frequency::<TIM6>());
63 const FREQUENCY: Hertz = Hertz::hz(200); 63 const FREQUENCY: Hertz = Hertz::hz(200);
64 64
65 // Compute the reload value such that we obtain the FREQUENCY for the sine 65 // Compute the reload value such that we obtain the FREQUENCY for the sine
66 let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; 66 let reload: u32 = (frequency::<TIM6>().0 / FREQUENCY.0) / data.len() as u32;
67 67
68 // Depends on your clock and on the specific chip used, you may need higher or lower values here 68 // Depends on your clock and on the specific chip used, you may need higher or lower values here
69 if reload < 10 { 69 if reload < 10 {
@@ -74,17 +74,17 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) {
74 dac.set_triggering(true); 74 dac.set_triggering(true);
75 dac.enable(); 75 dac.enable();
76 76
77 TIM6::enable_and_reset(); 77 let tim = Timer::new(tim);
78 TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); 78 tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1));
79 TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); 79 tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE));
80 TIM6::regs_basic().cr1().modify(|w| { 80 tim.regs_basic().cr1().modify(|w| {
81 w.set_opm(false); 81 w.set_opm(false);
82 w.set_cen(true); 82 w.set_cen(true);
83 }); 83 });
84 84
85 debug!( 85 debug!(
86 "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", 86 "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
87 TIM6::frequency(), 87 frequency::<TIM6>(),
88 FREQUENCY, 88 FREQUENCY,
89 reload, 89 reload,
90 reload as u16, 90 reload as u16,
@@ -99,22 +99,22 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) {
99} 99}
100 100
101#[embassy_executor::task] 101#[embassy_executor::task]
102async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { 102async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) {
103 let data: &[u8; 256] = &calculate_array::<256>(); 103 let data: &[u8; 256] = &calculate_array::<256>();
104 104
105 info!("TIM7 frequency is {}", TIM7::frequency()); 105 info!("TIM7 frequency is {}", frequency::<TIM6>());
106 106
107 const FREQUENCY: Hertz = Hertz::hz(600); 107 const FREQUENCY: Hertz = Hertz::hz(600);
108 let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; 108 let reload: u32 = (frequency::<TIM7>().0 / FREQUENCY.0) / data.len() as u32;
109 109
110 if reload < 10 { 110 if reload < 10 {
111 error!("Reload value {} below threshold!", reload); 111 error!("Reload value {} below threshold!", reload);
112 } 112 }
113 113
114 TIM7::enable_and_reset(); 114 let tim = Timer::new(tim);
115 TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); 115 tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1));
116 TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); 116 tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE));
117 TIM7::regs_basic().cr1().modify(|w| { 117 tim.regs_basic().cr1().modify(|w| {
118 w.set_opm(false); 118 w.set_opm(false);
119 w.set_cen(true); 119 w.set_cen(true);
120 }); 120 });
@@ -125,7 +125,7 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) {
125 125
126 debug!( 126 debug!(
127 "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", 127 "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
128 TIM7::frequency(), 128 frequency::<TIM7>(),
129 FREQUENCY, 129 FREQUENCY,
130 reload, 130 reload,
131 reload as u16, 131 reload as u16,
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index cd9a27fcd..7c7964ecd 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -64,19 +64,21 @@ async fn main(spawner: Spawner) -> ! {
64 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 64 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
65 65
66 static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new(); 66 static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new();
67 // warning: Not all STM32H7 devices have the exact same pins here
68 // for STM32H747XIH, replace p.PB13 for PG12
67 let device = Ethernet::new( 69 let device = Ethernet::new(
68 PACKETS.init(PacketQueue::<4, 4>::new()), 70 PACKETS.init(PacketQueue::<4, 4>::new()),
69 p.ETH, 71 p.ETH,
70 Irqs, 72 Irqs,
71 p.PA1, 73 p.PA1, // ref_clk
72 p.PA2, 74 p.PA2, // mdio
73 p.PC1, 75 p.PC1, // eth_mdc
74 p.PA7, 76 p.PA7, // CRS_DV: Carrier Sense
75 p.PC4, 77 p.PC4, // RX_D0: Received Bit 0
76 p.PC5, 78 p.PC5, // RX_D1: Received Bit 1
77 p.PG13, 79 p.PG13, // TX_D0: Transmit Bit 0
78 p.PB13, 80 p.PB13, // TX_D1: Transmit Bit 1
79 p.PG11, 81 p.PG11, // TX_EN: Transmit Enable
80 GenericSMI::new(0), 82 GenericSMI::new(0),
81 mac_addr, 83 mac_addr,
82 ); 84 );
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index 049d9967d..a95b44b74 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -3,11 +3,11 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::low_level::AFType; 6use embassy_stm32::gpio::{AFType, Flex, Pull, Speed};
7use embassy_stm32::gpio::Speed;
8use embassy_stm32::time::{khz, Hertz}; 7use embassy_stm32::time::{khz, Hertz};
9use embassy_stm32::timer::*; 8use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer};
10use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef}; 9use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel};
10use embassy_stm32::{into_ref, Config, Peripheral};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
@@ -56,11 +56,15 @@ async fn main(_spawner: Spawner) {
56 Timer::after_millis(300).await; 56 Timer::after_millis(300).await;
57 } 57 }
58} 58}
59pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> { 59pub struct SimplePwm32<'d, T: GeneralInstance32bit4Channel> {
60 inner: PeripheralRef<'d, T>, 60 tim: LLTimer<'d, T>,
61 _ch1: Flex<'d>,
62 _ch2: Flex<'d>,
63 _ch3: Flex<'d>,
64 _ch4: Flex<'d>,
61} 65}
62 66
63impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { 67impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> {
64 pub fn new( 68 pub fn new(
65 tim: impl Peripheral<P = T> + 'd, 69 tim: impl Peripheral<P = T> + 'd,
66 ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, 70 ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd,
@@ -69,25 +73,33 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
69 ch4: impl Peripheral<P = impl Channel4Pin<T>> + 'd, 73 ch4: impl Peripheral<P = impl Channel4Pin<T>> + 'd,
70 freq: Hertz, 74 freq: Hertz,
71 ) -> Self { 75 ) -> Self {
72 into_ref!(tim, ch1, ch2, ch3, ch4); 76 into_ref!(ch1, ch2, ch3, ch4);
73 77
74 T::enable_and_reset(); 78 let af1 = ch1.af_num();
75 79 let af2 = ch2.af_num();
76 ch1.set_speed(Speed::VeryHigh); 80 let af3 = ch3.af_num();
77 ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); 81 let af4 = ch4.af_num();
78 ch2.set_speed(Speed::VeryHigh); 82 let mut ch1 = Flex::new(ch1);
79 ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); 83 let mut ch2 = Flex::new(ch2);
80 ch3.set_speed(Speed::VeryHigh); 84 let mut ch3 = Flex::new(ch3);
81 ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); 85 let mut ch4 = Flex::new(ch4);
82 ch4.set_speed(Speed::VeryHigh); 86 ch1.set_as_af_unchecked(af1, AFType::OutputPushPull, Pull::None, Speed::VeryHigh);
83 ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); 87 ch2.set_as_af_unchecked(af2, AFType::OutputPushPull, Pull::None, Speed::VeryHigh);
84 88 ch3.set_as_af_unchecked(af3, AFType::OutputPushPull, Pull::None, Speed::VeryHigh);
85 let mut this = Self { inner: tim }; 89 ch4.set_as_af_unchecked(af4, AFType::OutputPushPull, Pull::None, Speed::VeryHigh);
90
91 let mut this = Self {
92 tim: LLTimer::new(tim),
93 _ch1: ch1,
94 _ch2: ch2,
95 _ch3: ch3,
96 _ch4: ch4,
97 };
86 98
87 this.set_frequency(freq); 99 this.set_frequency(freq);
88 this.inner.start(); 100 this.tim.start();
89 101
90 let r = T::regs_gp32(); 102 let r = this.tim.regs_gp32();
91 r.ccmr_output(0) 103 r.ccmr_output(0)
92 .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); 104 .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into()));
93 r.ccmr_output(0) 105 r.ccmr_output(0)
@@ -101,23 +113,26 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
101 } 113 }
102 114
103 pub fn enable(&mut self, channel: Channel) { 115 pub fn enable(&mut self, channel: Channel) {
104 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true)); 116 self.tim.regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true));
105 } 117 }
106 118
107 pub fn disable(&mut self, channel: Channel) { 119 pub fn disable(&mut self, channel: Channel) {
108 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), false)); 120 self.tim
121 .regs_gp32()
122 .ccer()
123 .modify(|w| w.set_cce(channel.index(), false));
109 } 124 }
110 125
111 pub fn set_frequency(&mut self, freq: Hertz) { 126 pub fn set_frequency(&mut self, freq: Hertz) {
112 <T as embassy_stm32::timer::low_level::GeneralPurpose32bitInstance>::set_frequency(&mut self.inner, freq); 127 self.tim.set_frequency(freq);
113 } 128 }
114 129
115 pub fn get_max_duty(&self) -> u32 { 130 pub fn get_max_duty(&self) -> u32 {
116 T::regs_gp32().arr().read() 131 self.tim.regs_gp32().arr().read()
117 } 132 }
118 133
119 pub fn set_duty(&mut self, channel: Channel, duty: u32) { 134 pub fn set_duty(&mut self, channel: Channel, duty: u32) {
120 defmt::assert!(duty < self.get_max_duty()); 135 defmt::assert!(duty < self.get_max_duty());
121 T::regs_gp32().ccr(channel.index()).write_value(duty) 136 self.tim.regs_gp32().ccr(channel.index()).write_value(duty)
122 } 137 }
123} 138}
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs
index d81efb541..576506ad3 100644
--- a/examples/stm32h7/src/bin/usb_serial.rs
+++ b/examples/stm32h7/src/bin/usb_serial.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::{panic, *}; 4use defmt::{panic, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::usb_otg::{Driver, Instance}; 6use embassy_stm32::usb::{Driver, Instance};
7use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 7use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
8use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 8use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
9use embassy_usb::driver::EndpointError; 9use embassy_usb::driver::EndpointError;
10use embassy_usb::Builder; 10use embassy_usb::Builder;
@@ -12,7 +12,7 @@ use futures::future::join;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
15 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 15 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
16}); 16});
17 17
18#[embassy_executor::main] 18#[embassy_executor::main]
@@ -40,12 +40,13 @@ async fn main(_spawner: Spawner) {
40 config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz 40 config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
41 config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz 41 config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
42 config.rcc.voltage_scale = VoltageScale::Scale1; 42 config.rcc.voltage_scale = VoltageScale::Scale1;
43 config.rcc.mux.usbsel = mux::Usbsel::HSI48;
43 } 44 }
44 let p = embassy_stm32::init(config); 45 let p = embassy_stm32::init(config);
45 46
46 // Create the driver, from the HAL. 47 // Create the driver, from the HAL.
47 let mut ep_out_buffer = [0u8; 256]; 48 let mut ep_out_buffer = [0u8; 256];
48 let mut config = embassy_stm32::usb_otg::Config::default(); 49 let mut config = embassy_stm32::usb::Config::default();
49 config.vbus_detection = true; 50 config.vbus_detection = true;
50 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 51 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
51 52
@@ -64,7 +65,6 @@ async fn main(_spawner: Spawner) {
64 65
65 // Create embassy-usb DeviceBuilder using the driver and config. 66 // Create embassy-usb DeviceBuilder using the driver and config.
66 // It needs some buffers for building the descriptors. 67 // It needs some buffers for building the descriptors.
67 let mut device_descriptor = [0; 256];
68 let mut config_descriptor = [0; 256]; 68 let mut config_descriptor = [0; 256];
69 let mut bos_descriptor = [0; 256]; 69 let mut bos_descriptor = [0; 256];
70 let mut control_buf = [0; 64]; 70 let mut control_buf = [0; 64];
@@ -74,7 +74,6 @@ async fn main(_spawner: Spawner) {
74 let mut builder = Builder::new( 74 let mut builder = Builder::new(
75 driver, 75 driver,
76 config, 76 config,
77 &mut device_descriptor,
78 &mut config_descriptor, 77 &mut config_descriptor,
79 &mut bos_descriptor, 78 &mut bos_descriptor,
80 &mut [], // no msos descriptors 79 &mut [], // no msos descriptors
diff --git a/examples/stm32l1/src/bin/usb_serial.rs b/examples/stm32l1/src/bin/usb_serial.rs
index f738ea358..653bbd6d2 100644
--- a/examples/stm32l1/src/bin/usb_serial.rs
+++ b/examples/stm32l1/src/bin/usb_serial.rs
@@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) {
46 config.device_protocol = 0x01; 46 config.device_protocol = 0x01;
47 config.composite_with_iads = true; 47 config.composite_with_iads = true;
48 48
49 let mut device_descriptor = [0; 256];
50 let mut config_descriptor = [0; 256]; 49 let mut config_descriptor = [0; 256];
51 let mut bos_descriptor = [0; 256]; 50 let mut bos_descriptor = [0; 256];
52 let mut control_buf = [0; 64]; 51 let mut control_buf = [0; 64];
@@ -56,7 +55,6 @@ async fn main(_spawner: Spawner) {
56 let mut builder = Builder::new( 55 let mut builder = Builder::new(
57 driver, 56 driver,
58 config, 57 config,
59 &mut device_descriptor,
60 &mut config_descriptor, 58 &mut config_descriptor,
61 &mut bos_descriptor, 59 &mut bos_descriptor,
62 &mut [], // no msos descriptors 60 &mut [], // no msos descriptors
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs
index f227812cd..d01b016c0 100644
--- a/examples/stm32l4/src/bin/dac_dma.rs
+++ b/examples/stm32l4/src/bin/dac_dma.rs
@@ -6,9 +6,9 @@ use embassy_executor::Spawner;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::pac::timer::vals::Mms; 7use embassy_stm32::pac::timer::vals::Mms;
8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; 8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7};
9use embassy_stm32::rcc::low_level::RccPeripheral; 9use embassy_stm32::rcc::frequency;
10use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
11use embassy_stm32::timer::low_level::BasicInstance; 11use embassy_stm32::timer::low_level::Timer;
12use micromath::F32Ext; 12use micromath::F32Ext;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
@@ -22,19 +22,19 @@ async fn main(spawner: Spawner) {
22 // Obtain two independent channels (p.DAC1 can only be consumed once, though!) 22 // Obtain two independent channels (p.DAC1 can only be consumed once, though!)
23 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); 23 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split();
24 24
25 spawner.spawn(dac_task1(dac_ch1)).ok(); 25 spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok();
26 spawner.spawn(dac_task2(dac_ch2)).ok(); 26 spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok();
27} 27}
28 28
29#[embassy_executor::task] 29#[embassy_executor::task]
30async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { 30async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) {
31 let data: &[u8; 256] = &calculate_array::<256>(); 31 let data: &[u8; 256] = &calculate_array::<256>();
32 32
33 info!("TIM6 frequency is {}", TIM6::frequency()); 33 info!("TIM6 frequency is {}", frequency::<TIM6>());
34 const FREQUENCY: Hertz = Hertz::hz(200); 34 const FREQUENCY: Hertz = Hertz::hz(200);
35 35
36 // Compute the reload value such that we obtain the FREQUENCY for the sine 36 // Compute the reload value such that we obtain the FREQUENCY for the sine
37 let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; 37 let reload: u32 = (frequency::<TIM6>().0 / FREQUENCY.0) / data.len() as u32;
38 38
39 // Depends on your clock and on the specific chip used, you may need higher or lower values here 39 // Depends on your clock and on the specific chip used, you may need higher or lower values here
40 if reload < 10 { 40 if reload < 10 {
@@ -45,17 +45,17 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) {
45 dac.set_triggering(true); 45 dac.set_triggering(true);
46 dac.enable(); 46 dac.enable();
47 47
48 TIM6::enable_and_reset(); 48 let tim = Timer::new(tim);
49 TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); 49 tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1));
50 TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); 50 tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE));
51 TIM6::regs_basic().cr1().modify(|w| { 51 tim.regs_basic().cr1().modify(|w| {
52 w.set_opm(false); 52 w.set_opm(false);
53 w.set_cen(true); 53 w.set_cen(true);
54 }); 54 });
55 55
56 debug!( 56 debug!(
57 "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", 57 "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
58 TIM6::frequency(), 58 frequency::<TIM6>(),
59 FREQUENCY, 59 FREQUENCY,
60 reload, 60 reload,
61 reload as u16, 61 reload as u16,
@@ -70,22 +70,22 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) {
70} 70}
71 71
72#[embassy_executor::task] 72#[embassy_executor::task]
73async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { 73async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) {
74 let data: &[u8; 256] = &calculate_array::<256>(); 74 let data: &[u8; 256] = &calculate_array::<256>();
75 75
76 info!("TIM7 frequency is {}", TIM7::frequency()); 76 info!("TIM7 frequency is {}", frequency::<TIM7>());
77 77
78 const FREQUENCY: Hertz = Hertz::hz(600); 78 const FREQUENCY: Hertz = Hertz::hz(600);
79 let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; 79 let reload: u32 = (frequency::<TIM7>().0 / FREQUENCY.0) / data.len() as u32;
80 80
81 if reload < 10 { 81 if reload < 10 {
82 error!("Reload value {} below threshold!", reload); 82 error!("Reload value {} below threshold!", reload);
83 } 83 }
84 84
85 TIM7::enable_and_reset(); 85 let tim = Timer::new(tim);
86 TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); 86 tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1));
87 TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); 87 tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE));
88 TIM7::regs_basic().cr1().modify(|w| { 88 tim.regs_basic().cr1().modify(|w| {
89 w.set_opm(false); 89 w.set_opm(false);
90 w.set_cen(true); 90 w.set_cen(true);
91 }); 91 });
@@ -96,7 +96,7 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) {
96 96
97 debug!( 97 debug!(
98 "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", 98 "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
99 TIM7::frequency(), 99 frequency::<TIM7>(),
100 FREQUENCY, 100 FREQUENCY,
101 reload, 101 reload,
102 reload as u16, 102 reload as u16,
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 32bfab6eb..343e09e68 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -42,7 +42,7 @@ bind_interrupts!(struct Irqs {
42 RNG => rng::InterruptHandler<peripherals::RNG>; 42 RNG => rng::InterruptHandler<peripherals::RNG>;
43}); 43});
44 44
45use embassy_net_adin1110::{self, Device, Runner, ADIN1110}; 45use embassy_net_adin1110::{Device, Runner, ADIN1110};
46use embedded_hal_bus::spi::ExclusiveDevice; 46use embedded_hal_bus::spi::ExclusiveDevice;
47use hal::gpio::Pull; 47use hal::gpio::Pull;
48use hal::i2c::Config as I2C_Config; 48use hal::i2c::Config as I2C_Config;
diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs
index 9247e56a1..198504b59 100644
--- a/examples/stm32l4/src/bin/usb_serial.rs
+++ b/examples/stm32l4/src/bin/usb_serial.rs
@@ -4,9 +4,8 @@
4use defmt::{panic, *}; 4use defmt::{panic, *};
5use defmt_rtt as _; // global logger 5use defmt_rtt as _; // global logger
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::*; 7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::usb_otg::{Driver, Instance}; 8use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
9use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 10use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder; 11use embassy_usb::Builder;
@@ -14,7 +13,7 @@ use futures::future::join;
14use panic_probe as _; 13use panic_probe as _;
15 14
16bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
17 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 16 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
18}); 17});
19 18
20#[embassy_executor::main] 19#[embassy_executor::main]
@@ -22,23 +21,26 @@ async fn main(_spawner: Spawner) {
22 info!("Hello World!"); 21 info!("Hello World!");
23 22
24 let mut config = Config::default(); 23 let mut config = Config::default();
25 config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB 24 {
26 config.rcc.sys = Sysclk::PLL1_R; 25 use embassy_stm32::rcc::*;
27 config.rcc.hsi = true; 26 config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
28 config.rcc.pll = Some(Pll { 27 config.rcc.sys = Sysclk::PLL1_R;
29 source: PllSource::HSI, 28 config.rcc.hsi = true;
30 prediv: PllPreDiv::DIV1, 29 config.rcc.pll = Some(Pll {
31 mul: PllMul::MUL10, 30 source: PllSource::HSI,
32 divp: None, 31 prediv: PllPreDiv::DIV1,
33 divq: None, 32 mul: PllMul::MUL10,
34 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2) 33 divp: None,
35 }); 34 divq: None,
36 35 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2)
36 });
37 config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
38 }
37 let p = embassy_stm32::init(config); 39 let p = embassy_stm32::init(config);
38 40
39 // Create the driver, from the HAL. 41 // Create the driver, from the HAL.
40 let mut ep_out_buffer = [0u8; 256]; 42 let mut ep_out_buffer = [0u8; 256];
41 let mut config = embassy_stm32::usb_otg::Config::default(); 43 let mut config = embassy_stm32::usb::Config::default();
42 config.vbus_detection = true; 44 config.vbus_detection = true;
43 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 45 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
44 46
@@ -58,7 +60,6 @@ async fn main(_spawner: Spawner) {
58 60
59 // Create embassy-usb DeviceBuilder using the driver and config. 61 // Create embassy-usb DeviceBuilder using the driver and config.
60 // It needs some buffers for building the descriptors. 62 // It needs some buffers for building the descriptors.
61 let mut device_descriptor = [0; 256];
62 let mut config_descriptor = [0; 256]; 63 let mut config_descriptor = [0; 256];
63 let mut bos_descriptor = [0; 256]; 64 let mut bos_descriptor = [0; 256];
64 let mut control_buf = [0; 64]; 65 let mut control_buf = [0; 64];
@@ -68,7 +69,6 @@ async fn main(_spawner: Spawner) {
68 let mut builder = Builder::new( 69 let mut builder = Builder::new(
69 driver, 70 driver,
70 config, 71 config,
71 &mut device_descriptor,
72 &mut config_descriptor, 72 &mut config_descriptor,
73 &mut bos_descriptor, 73 &mut bos_descriptor,
74 &mut [], // no msos descriptors 74 &mut [], // no msos descriptors
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index f6d8b16d0..7f73fd677 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -5,7 +5,6 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket; 6use embassy_net::tcp::TcpSocket;
7use embassy_net::{Stack, StackResources}; 7use embassy_net::{Stack, StackResources};
8use embassy_stm32::rcc::*;
9use embassy_stm32::rng::Rng; 8use embassy_stm32::rng::Rng;
10use embassy_stm32::usb::Driver; 9use embassy_stm32::usb::Driver;
11use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config}; 10use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config};
@@ -44,17 +43,22 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
44#[embassy_executor::main] 43#[embassy_executor::main]
45async fn main(spawner: Spawner) { 44async fn main(spawner: Spawner) {
46 let mut config = Config::default(); 45 let mut config = Config::default();
47 config.rcc.hsi = true; 46 {
48 config.rcc.sys = Sysclk::PLL1_R; 47 use embassy_stm32::rcc::*;
49 config.rcc.pll = Some(Pll { 48 config.rcc.hsi = true;
50 // 80Mhz clock (16 / 1 * 10 / 2) 49 config.rcc.sys = Sysclk::PLL1_R;
51 source: PllSource::HSI, 50 config.rcc.pll = Some(Pll {
52 prediv: PllPreDiv::DIV1, 51 // 80Mhz clock (16 / 1 * 10 / 2)
53 mul: PllMul::MUL10, 52 source: PllSource::HSI,
54 divp: None, 53 prediv: PllPreDiv::DIV1,
55 divq: None, 54 mul: PllMul::MUL10,
56 divr: Some(PllRDiv::DIV2), 55 divp: None,
57 }); 56 divq: None,
57 divr: Some(PllRDiv::DIV2),
58 });
59 config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
60 config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
61 }
58 let p = embassy_stm32::init(config); 62 let p = embassy_stm32::init(config);
59 63
60 // Create the driver, from the HAL. 64 // Create the driver, from the HAL.
@@ -75,14 +79,12 @@ async fn main(spawner: Spawner) {
75 config.device_protocol = 0x01; 79 config.device_protocol = 0x01;
76 80
77 // Create embassy-usb DeviceBuilder using the driver and config. 81 // Create embassy-usb DeviceBuilder using the driver and config.
78 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
79 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 82 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
80 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); 83 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
81 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new(); 84 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
82 let mut builder = Builder::new( 85 let mut builder = Builder::new(
83 driver, 86 driver,
84 config, 87 config,
85 &mut DEVICE_DESC.init([0; 256])[..],
86 &mut CONFIG_DESC.init([0; 256])[..], 88 &mut CONFIG_DESC.init([0; 256])[..],
87 &mut BOS_DESC.init([0; 256])[..], 89 &mut BOS_DESC.init([0; 256])[..],
88 &mut [], // no msos descriptors 90 &mut [], // no msos descriptors
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs
index c51ed96e0..9d30205bb 100644
--- a/examples/stm32l5/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::rcc::*;
8use embassy_stm32::usb::Driver; 7use embassy_stm32::usb::Driver;
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 8use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
10use embassy_time::Timer; 9use embassy_time::Timer;
@@ -21,17 +20,22 @@ bind_interrupts!(struct Irqs {
21#[embassy_executor::main] 20#[embassy_executor::main]
22async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
23 let mut config = Config::default(); 22 let mut config = Config::default();
24 config.rcc.hsi = true; 23 {
25 config.rcc.sys = Sysclk::PLL1_R; 24 use embassy_stm32::rcc::*;
26 config.rcc.pll = Some(Pll { 25 config.rcc.hsi = true;
27 // 80Mhz clock (16 / 1 * 10 / 2) 26 config.rcc.sys = Sysclk::PLL1_R;
28 source: PllSource::HSI, 27 config.rcc.pll = Some(Pll {
29 prediv: PllPreDiv::DIV1, 28 // 80Mhz clock (16 / 1 * 10 / 2)
30 mul: PllMul::MUL10, 29 source: PllSource::HSI,
31 divp: None, 30 prediv: PllPreDiv::DIV1,
32 divq: None, 31 mul: PllMul::MUL10,
33 divr: Some(PllRDiv::DIV2), 32 divp: None,
34 }); 33 divq: None,
34 divr: Some(PllRDiv::DIV2),
35 });
36 config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
37 config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
38 }
35 let p = embassy_stm32::init(config); 39 let p = embassy_stm32::init(config);
36 40
37 // Create the driver, from the HAL. 41 // Create the driver, from the HAL.
@@ -47,7 +51,6 @@ async fn main(_spawner: Spawner) {
47 51
48 // Create embassy-usb DeviceBuilder using the driver and config. 52 // Create embassy-usb DeviceBuilder using the driver and config.
49 // It needs some buffers for building the descriptors. 53 // It needs some buffers for building the descriptors.
50 let mut device_descriptor = [0; 256];
51 let mut config_descriptor = [0; 256]; 54 let mut config_descriptor = [0; 256];
52 let mut bos_descriptor = [0; 256]; 55 let mut bos_descriptor = [0; 256];
53 let mut control_buf = [0; 64]; 56 let mut control_buf = [0; 64];
@@ -58,7 +61,6 @@ async fn main(_spawner: Spawner) {
58 let mut builder = Builder::new( 61 let mut builder = Builder::new(
59 driver, 62 driver,
60 config, 63 config,
61 &mut device_descriptor,
62 &mut config_descriptor, 64 &mut config_descriptor,
63 &mut bos_descriptor, 65 &mut bos_descriptor,
64 &mut [], // no msos descriptors 66 &mut [], // no msos descriptors
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs
index 87987f2ce..a64bda31b 100644
--- a/examples/stm32l5/src/bin/usb_serial.rs
+++ b/examples/stm32l5/src/bin/usb_serial.rs
@@ -4,7 +4,6 @@
4use defmt::{panic, *}; 4use defmt::{panic, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::rcc::*;
8use embassy_stm32::usb::{Driver, Instance}; 7use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 8use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
@@ -19,17 +18,22 @@ bind_interrupts!(struct Irqs {
19#[embassy_executor::main] 18#[embassy_executor::main]
20async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
21 let mut config = Config::default(); 20 let mut config = Config::default();
22 config.rcc.hsi = true; 21 {
23 config.rcc.sys = Sysclk::PLL1_R; 22 use embassy_stm32::rcc::*;
24 config.rcc.pll = Some(Pll { 23 config.rcc.hsi = true;
25 // 80Mhz clock (16 / 1 * 10 / 2) 24 config.rcc.sys = Sysclk::PLL1_R;
26 source: PllSource::HSI, 25 config.rcc.pll = Some(Pll {
27 prediv: PllPreDiv::DIV1, 26 // 80Mhz clock (16 / 1 * 10 / 2)
28 mul: PllMul::MUL10, 27 source: PllSource::HSI,
29 divp: None, 28 prediv: PllPreDiv::DIV1,
30 divq: None, 29 mul: PllMul::MUL10,
31 divr: Some(PllRDiv::DIV2), 30 divp: None,
32 }); 31 divq: None,
32 divr: Some(PllRDiv::DIV2),
33 });
34 config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
35 config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
36 }
33 let p = embassy_stm32::init(config); 37 let p = embassy_stm32::init(config);
34 38
35 info!("Hello World!"); 39 info!("Hello World!");
@@ -43,7 +47,6 @@ async fn main(_spawner: Spawner) {
43 47
44 // Create embassy-usb DeviceBuilder using the driver and config. 48 // Create embassy-usb DeviceBuilder using the driver and config.
45 // It needs some buffers for building the descriptors. 49 // It needs some buffers for building the descriptors.
46 let mut device_descriptor = [0; 256];
47 let mut config_descriptor = [0; 256]; 50 let mut config_descriptor = [0; 256];
48 let mut bos_descriptor = [0; 256]; 51 let mut bos_descriptor = [0; 256];
49 let mut control_buf = [0; 7]; 52 let mut control_buf = [0; 7];
@@ -53,7 +56,6 @@ async fn main(_spawner: Spawner) {
53 let mut builder = Builder::new( 56 let mut builder = Builder::new(
54 driver, 57 driver,
55 config, 58 config,
56 &mut device_descriptor,
57 &mut config_descriptor, 59 &mut config_descriptor,
58 &mut bos_descriptor, 60 &mut bos_descriptor,
59 &mut [], // no msos descriptors 61 &mut [], // no msos descriptors
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs
index 61851e5a2..6a313efb0 100644
--- a/examples/stm32u5/src/bin/usb_serial.rs
+++ b/examples/stm32u5/src/bin/usb_serial.rs
@@ -4,8 +4,8 @@
4use defmt::{panic, *}; 4use defmt::{panic, *};
5use defmt_rtt as _; // global logger 5use defmt_rtt as _; // global logger
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::usb_otg::{Driver, Instance}; 7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 8use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 10use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder; 11use embassy_usb::Builder;
@@ -13,7 +13,7 @@ use futures::future::join;
13use panic_probe as _; 13use panic_probe as _;
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
16 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 16 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
17}); 17});
18 18
19#[embassy_executor::main] 19#[embassy_executor::main]
@@ -35,13 +35,14 @@ async fn main(_spawner: Spawner) {
35 config.rcc.sys = Sysclk::PLL1_R; 35 config.rcc.sys = Sysclk::PLL1_R;
36 config.rcc.voltage_range = VoltageScale::RANGE1; 36 config.rcc.voltage_range = VoltageScale::RANGE1;
37 config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB 37 config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
38 config.rcc.mux.iclksel = mux::Iclksel::HSI48; // USB uses ICLK
38 } 39 }
39 40
40 let p = embassy_stm32::init(config); 41 let p = embassy_stm32::init(config);
41 42
42 // Create the driver, from the HAL. 43 // Create the driver, from the HAL.
43 let mut ep_out_buffer = [0u8; 256]; 44 let mut ep_out_buffer = [0u8; 256];
44 let mut config = embassy_stm32::usb_otg::Config::default(); 45 let mut config = embassy_stm32::usb::Config::default();
45 config.vbus_detection = false; 46 config.vbus_detection = false;
46 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 47 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
47 48
@@ -60,7 +61,6 @@ async fn main(_spawner: Spawner) {
60 61
61 // Create embassy-usb DeviceBuilder using the driver and config. 62 // Create embassy-usb DeviceBuilder using the driver and config.
62 // It needs some buffers for building the descriptors. 63 // It needs some buffers for building the descriptors.
63 let mut device_descriptor = [0; 256];
64 let mut config_descriptor = [0; 256]; 64 let mut config_descriptor = [0; 256];
65 let mut bos_descriptor = [0; 256]; 65 let mut bos_descriptor = [0; 256];
66 let mut control_buf = [0; 64]; 66 let mut control_buf = [0; 64];
@@ -70,7 +70,6 @@ async fn main(_spawner: Spawner) {
70 let mut builder = Builder::new( 70 let mut builder = Builder::new(
71 driver, 71 driver,
72 config, 72 config,
73 &mut device_descriptor,
74 &mut config_descriptor, 73 &mut config_descriptor,
75 &mut bos_descriptor, 74 &mut bos_descriptor,
76 &mut [], // no msos descriptors 75 &mut [], // no msos descriptors
diff --git a/rust-toolchain-nightly.toml b/rust-toolchain-nightly.toml
index b8a7db353..98696fd2b 100644
--- a/rust-toolchain-nightly.toml
+++ b/rust-toolchain-nightly.toml
@@ -1,5 +1,5 @@
1[toolchain] 1[toolchain]
2channel = "nightly-2023-12-20" 2channel = "nightly-2024-03-20"
3components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ] 3components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ]
4targets = [ 4targets = [
5 "thumbv7em-none-eabi", 5 "thumbv7em-none-eabi",
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index a6fe52ee2..2f5d17069 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,5 +1,5 @@
1[toolchain] 1[toolchain]
2channel = "1.75" 2channel = "1.77"
3components = [ "rust-src", "rustfmt", "llvm-tools" ] 3components = [ "rust-src", "rustfmt", "llvm-tools" ]
4targets = [ 4targets = [
5 "thumbv7em-none-eabi", 5 "thumbv7em-none-eabi",
diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs
index 8aed9b80c..e9c6f3122 100644
--- a/tests/rp/src/bin/gpio_multicore.rs
+++ b/tests/rp/src/bin/gpio_multicore.rs
@@ -21,10 +21,14 @@ static CHANNEL1: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
21#[cortex_m_rt::entry] 21#[cortex_m_rt::entry]
22fn main() -> ! { 22fn main() -> ! {
23 let p = embassy_rp::init(Default::default()); 23 let p = embassy_rp::init(Default::default());
24 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { 24 spawn_core1(
25 let executor1 = EXECUTOR1.init(Executor::new()); 25 p.CORE1,
26 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1)))); 26 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
27 }); 27 move || {
28 let executor1 = EXECUTOR1.init(Executor::new());
29 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1))));
30 },
31 );
28 let executor0 = EXECUTOR0.init(Executor::new()); 32 let executor0 = EXECUTOR0.init(Executor::new());
29 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0)))); 33 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0))));
30} 34}
diff --git a/tests/rp/src/bin/i2c.rs b/tests/rp/src/bin/i2c.rs
index 153b37999..9615007bd 100644
--- a/tests/rp/src/bin/i2c.rs
+++ b/tests/rp/src/bin/i2c.rs
@@ -210,10 +210,14 @@ async fn controller_task(con: &mut i2c::I2c<'static, I2C0, i2c::Async>) {
210 config.addr = DEV_ADDR as u16; 210 config.addr = DEV_ADDR as u16;
211 let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); 211 let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config);
212 212
213 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { 213 spawn_core1(
214 let executor1 = EXECUTOR1.init(Executor::new()); 214 p.CORE1,
215 executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device)))); 215 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
216 }); 216 move || {
217 let executor1 = EXECUTOR1.init(Executor::new());
218 executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device))));
219 },
220 );
217 221
218 let c_sda = p.PIN_21; 222 let c_sda = p.PIN_21;
219 let c_scl = p.PIN_20; 223 let c_scl = p.PIN_20;
diff --git a/tests/rp/src/bin/multicore.rs b/tests/rp/src/bin/multicore.rs
index 60d9f85ec..783ea0f27 100644
--- a/tests/rp/src/bin/multicore.rs
+++ b/tests/rp/src/bin/multicore.rs
@@ -19,10 +19,14 @@ static CHANNEL1: Channel<CriticalSectionRawMutex, bool, 1> = Channel::new();
19#[cortex_m_rt::entry] 19#[cortex_m_rt::entry]
20fn main() -> ! { 20fn main() -> ! {
21 let p = embassy_rp::init(Default::default()); 21 let p = embassy_rp::init(Default::default());
22 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { 22 spawn_core1(
23 let executor1 = EXECUTOR1.init(Executor::new()); 23 p.CORE1,
24 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task()))); 24 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
25 }); 25 move || {
26 let executor1 = EXECUTOR1.init(Executor::new());
27 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task())));
28 },
29 );
26 let executor0 = EXECUTOR0.init(Executor::new()); 30 let executor0 = EXECUTOR0.init(Executor::new());
27 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); 31 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task())));
28} 32}