aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchemicstry <[email protected]>2023-07-31 10:29:20 +0300
committerchemicstry <[email protected]>2023-07-31 10:29:20 +0300
commit780569c08ab089dae67c5d57dd1852d5419d4577 (patch)
tree021965b7c9ac34fb33507c3998b3a6b6e7cecae7
parenta56ef685f3bfd9148a79c9dbbdde83a2c1642ba5 (diff)
parent6c6bd11c1a28eb8985518a10bd723c622d82f4b6 (diff)
Merge remote-tracking branch 'origin/main' into bxcan_timestamp
-rwxr-xr-x.github/ci/test.sh2
-rw-r--r--.vscode/settings.json1
-rwxr-xr-xci.sh3
-rwxr-xr-xcyw43-firmware/43439A0.binbin224190 -> 230321 bytes
-rwxr-xr-xcyw43-firmware/43439A0_clm.binbin4752 -> 4752 bytes
-rw-r--r--cyw43-firmware/README.md6
-rw-r--r--cyw43-pio/src/lib.rs8
-rw-r--r--embassy-boot/rp/src/lib.rs14
-rw-r--r--embassy-hal-internal/Cargo.toml (renamed from embassy-hal-common/Cargo.toml)2
-rw-r--r--embassy-hal-internal/README.md16
-rw-r--r--embassy-hal-internal/build.rs (renamed from embassy-hal-common/build.rs)0
-rw-r--r--embassy-hal-internal/src/atomic_ring_buffer.rs (renamed from embassy-hal-common/src/atomic_ring_buffer.rs)0
-rw-r--r--embassy-hal-internal/src/drop.rs (renamed from embassy-hal-common/src/drop.rs)0
-rw-r--r--embassy-hal-internal/src/fmt.rs (renamed from embassy-hal-common/src/fmt.rs)0
-rw-r--r--embassy-hal-internal/src/interrupt.rs (renamed from embassy-hal-common/src/interrupt.rs)0
-rw-r--r--embassy-hal-internal/src/lib.rs (renamed from embassy-hal-common/src/lib.rs)1
-rw-r--r--embassy-hal-internal/src/macros.rs (renamed from embassy-hal-common/src/macros.rs)0
-rw-r--r--embassy-hal-internal/src/peripheral.rs (renamed from embassy-hal-common/src/peripheral.rs)0
-rw-r--r--embassy-hal-internal/src/ratio.rs (renamed from embassy-hal-common/src/ratio.rs)0
-rw-r--r--embassy-hal-internal/src/ring_buffer.rs (renamed from embassy-hal-common/src/ring_buffer.rs)0
-rw-r--r--embassy-lora/Cargo.toml14
-rw-r--r--embassy-net-esp-hosted/src/control.rs2
-rw-r--r--embassy-net/src/lib.rs10
-rw-r--r--embassy-nrf/Cargo.toml2
-rw-r--r--embassy-nrf/src/buffered_uarte.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52820.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs4
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs4
-rw-r--r--embassy-nrf/src/chips/nrf5340_net.rs4
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs4
-rw-r--r--embassy-nrf/src/gpio.rs2
-rw-r--r--embassy-nrf/src/gpiote.rs2
-rw-r--r--embassy-nrf/src/i2s.rs4
-rw-r--r--embassy-nrf/src/lib.rs4
-rw-r--r--embassy-nrf/src/nvmc.rs2
-rw-r--r--embassy-nrf/src/pdm.rs4
-rw-r--r--embassy-nrf/src/ppi/dppi.rs2
-rw-r--r--embassy-nrf/src/ppi/mod.rs2
-rw-r--r--embassy-nrf/src/ppi/ppi.rs2
-rw-r--r--embassy-nrf/src/pwm.rs2
-rw-r--r--embassy-nrf/src/qdec.rs2
-rw-r--r--embassy-nrf/src/qspi.rs4
-rw-r--r--embassy-nrf/src/rng.rs4
-rw-r--r--embassy-nrf/src/saadc.rs4
-rw-r--r--embassy-nrf/src/spim.rs2
-rw-r--r--embassy-nrf/src/spis.rs2
-rw-r--r--embassy-nrf/src/temp.rs4
-rw-r--r--embassy-nrf/src/timer.rs2
-rw-r--r--embassy-nrf/src/twim.rs2
-rw-r--r--embassy-nrf/src/twis.rs2
-rw-r--r--embassy-nrf/src/uarte.rs4
-rw-r--r--embassy-nrf/src/usb/mod.rs2
-rw-r--r--embassy-rp/Cargo.toml7
-rw-r--r--embassy-rp/src/adc.rs2
-rw-r--r--embassy-rp/src/clocks.rs2
-rw-r--r--embassy-rp/src/dma.rs2
-rw-r--r--embassy-rp/src/flash.rs203
-rw-r--r--embassy-rp/src/gpio.rs2
-rw-r--r--embassy-rp/src/i2c.rs2
-rw-r--r--embassy-rp/src/lib.rs78
-rw-r--r--embassy-rp/src/multicore.rs33
-rw-r--r--embassy-rp/src/pio.rs62
-rw-r--r--embassy-rp/src/pwm.rs2
-rw-r--r--embassy-rp/src/relocate.rs5
-rw-r--r--embassy-rp/src/rtc/mod.rs2
-rw-r--r--embassy-rp/src/spi.rs2
-rw-r--r--embassy-rp/src/uart/buffered.rs2
-rw-r--r--embassy-rp/src/uart/mod.rs2
-rw-r--r--embassy-stm32-wpan/Cargo.toml6
-rw-r--r--embassy-stm32-wpan/src/lib.rs2
-rw-r--r--embassy-stm32/Cargo.toml60
-rw-r--r--embassy-stm32/build.rs50
-rw-r--r--embassy-stm32/src/adc/f1.rs2
-rw-r--r--embassy-stm32/src/adc/v1.rs2
-rw-r--r--embassy-stm32/src/adc/v2.rs2
-rw-r--r--embassy-stm32/src/adc/v3.rs2
-rw-r--r--embassy-stm32/src/adc/v4.rs2
-rw-r--r--embassy-stm32/src/can/bxcan.rs156
-rw-r--r--embassy-stm32/src/can/fdcan.rs2
-rw-r--r--embassy-stm32/src/crc/v1.rs2
-rw-r--r--embassy-stm32/src/crc/v2v3.rs2
-rw-r--r--embassy-stm32/src/dac/mod.rs2
-rw-r--r--embassy-stm32/src/dcmi.rs2
-rw-r--r--embassy-stm32/src/dma/bdma.rs46
-rw-r--r--embassy-stm32/src/dma/dma.rs46
-rw-r--r--embassy-stm32/src/dma/gpdma.rs2
-rw-r--r--embassy-stm32/src/dma/mod.rs2
-rw-r--r--embassy-stm32/src/dma/ringbuffer.rs18
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs2
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs2
-rw-r--r--embassy-stm32/src/exti.rs2
-rw-r--r--embassy-stm32/src/flash/asynch.rs4
-rw-r--r--embassy-stm32/src/flash/common.rs4
-rw-r--r--embassy-stm32/src/flash/f4.rs2
-rw-r--r--embassy-stm32/src/fmc.rs2
-rw-r--r--embassy-stm32/src/gpio.rs16
-rw-r--r--embassy-stm32/src/hrtim/mod.rs409
-rw-r--r--embassy-stm32/src/hrtim/traits.rs193
-rw-r--r--embassy-stm32/src/i2c/timeout.rs20
-rw-r--r--embassy-stm32/src/i2c/v1.rs2
-rw-r--r--embassy-stm32/src/i2c/v2.rs4
-rw-r--r--embassy-stm32/src/i2s.rs6
-rw-r--r--embassy-stm32/src/lib.rs17
-rw-r--r--embassy-stm32/src/pwm/mod.rs269
-rw-r--r--embassy-stm32/src/qspi/mod.rs2
-rw-r--r--embassy-stm32/src/rcc/c0.rs55
-rw-r--r--embassy-stm32/src/rcc/common.rs174
-rw-r--r--embassy-stm32/src/rcc/f2.rs120
-rw-r--r--embassy-stm32/src/rcc/f3.rs1
-rw-r--r--embassy-stm32/src/rcc/f4.rs2
-rw-r--r--embassy-stm32/src/rcc/g0.rs74
-rw-r--r--embassy-stm32/src/rcc/g4.rs25
-rw-r--r--embassy-stm32/src/rcc/h5.rs104
-rw-r--r--embassy-stm32/src/rcc/h7.rs18
-rw-r--r--embassy-stm32/src/rcc/l0.rs53
-rw-r--r--embassy-stm32/src/rcc/l1.rs53
-rw-r--r--embassy-stm32/src/rcc/l4.rs55
-rw-r--r--embassy-stm32/src/rcc/l5.rs53
-rw-r--r--embassy-stm32/src/rcc/mod.rs2
-rw-r--r--embassy-stm32/src/rcc/u5.rs79
-rw-r--r--embassy-stm32/src/rcc/wb.rs63
-rw-r--r--embassy-stm32/src/rcc/wl.rs85
-rw-r--r--embassy-stm32/src/rng.rs206
-rw-r--r--embassy-stm32/src/rtc/mod.rs2
-rw-r--r--embassy-stm32/src/rtc/v2.rs8
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs4
-rw-r--r--embassy-stm32/src/spi/mod.rs68
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs (renamed from embassy-stm32/src/pwm/complementary_pwm.rs)18
-rw-r--r--embassy-stm32/src/timer/mod.rs271
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs (renamed from embassy-stm32/src/pwm/simple_pwm.rs)8
-rw-r--r--embassy-stm32/src/usart/buffered.rs2
-rw-r--r--embassy-stm32/src/usart/mod.rs6
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs2
-rw-r--r--embassy-stm32/src/usb/usb.rs2
-rw-r--r--embassy-stm32/src/usb_otg/usb.rs2
-rw-r--r--embassy-stm32/src/wdg/mod.rs2
-rw-r--r--examples/boot/application/rp/src/bin/a.rs4
-rw-r--r--examples/nrf-rtos-trace/Cargo.toml3
-rw-r--r--examples/nrf52840-rtic/Cargo.toml3
-rw-r--r--examples/nrf52840/Cargo.toml4
-rw-r--r--examples/nrf5340/Cargo.toml3
-rw-r--r--examples/rp/Cargo.toml5
-rw-r--r--examples/rp/src/bin/flash.rs42
-rw-r--r--examples/rp/src/bin/pio_async.rs10
-rw-r--r--examples/rp/src/bin/pio_dma.rs4
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs7
-rw-r--r--examples/rp/src/bin/pio_uart.rs394
-rw-r--r--examples/rp/src/bin/pio_ws2812.rs4
-rw-r--r--examples/std/Cargo.toml3
-rw-r--r--examples/stm32c0/Cargo.toml3
-rw-r--r--examples/stm32f0/Cargo.toml3
-rw-r--r--examples/stm32f1/Cargo.toml3
-rw-r--r--examples/stm32f2/Cargo.toml3
-rw-r--r--examples/stm32f3/Cargo.toml3
-rw-r--r--examples/stm32f3/src/bin/spi_dma.rs14
-rw-r--r--examples/stm32f334/.cargo/config.toml9
-rw-r--r--examples/stm32f334/Cargo.toml26
-rw-r--r--examples/stm32f334/build.rs5
-rw-r--r--examples/stm32f334/src/bin/button.rs27
-rw-r--r--examples/stm32f334/src/bin/hello.rs23
-rw-r--r--examples/stm32f334/src/bin/pwm.rs71
-rw-r--r--examples/stm32f4/src/bin/eth.rs6
-rw-r--r--examples/stm32f4/src/bin/pwm.rs7
-rw-r--r--examples/stm32f4/src/bin/pwm_complementary.rs11
-rw-r--r--examples/stm32f4/src/bin/spi.rs14
-rw-r--r--examples/stm32f4/src/bin/spi_dma.rs14
-rw-r--r--examples/stm32f4/src/bin/usb_ethernet.rs5
-rw-r--r--examples/stm32f7/Cargo.toml5
-rw-r--r--examples/stm32f7/build.rs40
-rw-r--r--examples/stm32f7/memory.x12
-rw-r--r--examples/stm32f7/src/bin/eth.rs6
-rw-r--r--examples/stm32g0/Cargo.toml3
-rw-r--r--examples/stm32g0/src/bin/spi_neopixel.rs4
-rw-r--r--examples/stm32g4/Cargo.toml4
-rw-r--r--examples/stm32g4/src/bin/pwm.rs7
-rw-r--r--examples/stm32h5/Cargo.toml2
-rw-r--r--examples/stm32h5/memory.x5
-rw-r--r--examples/stm32h5/src/bin/eth.rs6
-rw-r--r--examples/stm32h5/src/bin/rng.rs7
-rw-r--r--examples/stm32h7/.cargo/config.toml2
-rw-r--r--examples/stm32h7/Cargo.toml2
-rw-r--r--examples/stm32h7/memory.x5
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs140
-rw-r--r--examples/stm32h7/src/bin/eth.rs6
-rw-r--r--examples/stm32h7/src/bin/eth_client.rs6
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs2
-rw-r--r--examples/stm32h7/src/bin/pwm.rs7
-rw-r--r--examples/stm32h7/src/bin/rng.rs7
-rw-r--r--examples/stm32h7/src/bin/spi.rs14
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs14
-rw-r--r--examples/stm32l0/Cargo.toml4
-rw-r--r--examples/stm32l0/src/bin/lora_cad.rs14
-rw-r--r--examples/stm32l0/src/bin/lora_lorawan.rs22
-rw-r--r--examples/stm32l0/src/bin/lora_p2p_receive.rs14
-rw-r--r--examples/stm32l0/src/bin/lora_p2p_send.rs14
-rw-r--r--examples/stm32l0/src/bin/spi.rs14
-rw-r--r--examples/stm32l1/Cargo.toml3
-rw-r--r--examples/stm32l1/src/bin/spi.rs14
-rw-r--r--examples/stm32l4/Cargo.toml5
-rw-r--r--examples/stm32l4/build.rs30
-rw-r--r--examples/stm32l4/memory.x7
-rw-r--r--examples/stm32l4/src/bin/rng.rs8
-rw-r--r--examples/stm32l4/src/bin/spi.rs14
-rw-r--r--examples/stm32l4/src/bin/spi_blocking_async.rs14
-rw-r--r--examples/stm32l4/src/bin/spi_dma.rs14
-rw-r--r--examples/stm32l5/Cargo.toml3
-rw-r--r--examples/stm32l5/src/bin/rng.rs8
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs5
-rw-r--r--examples/stm32u5/Cargo.toml3
-rw-r--r--examples/stm32wb/Cargo.toml3
-rw-r--r--examples/stm32wb/src/bin/eddystone_beacon.rs5
-rw-r--r--examples/stm32wb/src/bin/gatt_server.rs5
-rw-r--r--examples/stm32wb/src/bin/mac_ffd.rs9
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs9
-rw-r--r--examples/stm32wb/src/bin/mac_rfd.rs9
-rw-r--r--examples/stm32wb/src/bin/tl_mbox.rs5
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_ble.rs5
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_mac.rs9
-rw-r--r--examples/stm32wl/Cargo.toml4
-rw-r--r--examples/stm32wl/src/bin/lora_lorawan.rs7
-rw-r--r--examples/stm32wl/src/bin/random.rs10
-rw-r--r--examples/wasm/Cargo.toml3
-rw-r--r--tests/nrf/src/bin/wifi_esp_hosted_perf.rs6
-rw-r--r--tests/rp/src/bin/cyw43-perf.rs4
-rw-r--r--tests/rp/src/bin/flash.rs14
-rw-r--r--tests/rp/src/bin/pio_irq.rs4
-rw-r--r--tests/rp/src/bin/pio_multi_load.rs126
-rw-r--r--tests/stm32/Cargo.toml13
-rw-r--r--tests/stm32/src/bin/dac.rs81
-rw-r--r--tests/stm32/src/bin/spi.rs11
-rw-r--r--tests/stm32/src/bin/spi_dma.rs11
-rw-r--r--tests/stm32/src/common.rs1
237 files changed, 3310 insertions, 1867 deletions
diff --git a/.github/ci/test.sh b/.github/ci/test.sh
index d014e4bd7..2892bcf8d 100755
--- a/.github/ci/test.sh
+++ b/.github/ci/test.sh
@@ -13,7 +13,7 @@ hashtime save /ci/cache/filetime.json
13 13
14cargo test --manifest-path ./embassy-sync/Cargo.toml 14cargo test --manifest-path ./embassy-sync/Cargo.toml
15cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml 15cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml
16cargo test --manifest-path ./embassy-hal-common/Cargo.toml 16cargo test --manifest-path ./embassy-hal-internal/Cargo.toml
17cargo test --manifest-path ./embassy-time/Cargo.toml --features generic-queue 17cargo test --manifest-path ./embassy-time/Cargo.toml --features generic-queue
18 18
19cargo test --manifest-path ./embassy-boot/boot/Cargo.toml 19cargo test --manifest-path ./embassy-boot/boot/Cargo.toml
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 725fb69d0..29e8812e3 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -25,6 +25,7 @@
25 // "examples/stm32f1/Cargo.toml", 25 // "examples/stm32f1/Cargo.toml",
26 // "examples/stm32f2/Cargo.toml", 26 // "examples/stm32f2/Cargo.toml",
27 // "examples/stm32f3/Cargo.toml", 27 // "examples/stm32f3/Cargo.toml",
28 // "examples/stm32f334/Cargo.toml",
28 // "examples/stm32f4/Cargo.toml", 29 // "examples/stm32f4/Cargo.toml",
29 // "examples/stm32f7/Cargo.toml", 30 // "examples/stm32f7/Cargo.toml",
30 // "examples/stm32g0/Cargo.toml", 31 // "examples/stm32g0/Cargo.toml",
diff --git a/ci.sh b/ci.sh
index 376cc8f44..32ae7855e 100755
--- a/ci.sh
+++ b/ci.sh
@@ -27,6 +27,8 @@ cargo batch \
27 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly \ 27 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly \
28 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits,nightly \ 28 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits,nightly \
29 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ 29 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \
30 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \
31 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \
30 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits \ 32 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits \
31 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,nightly \ 33 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,nightly \
32 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits,nightly \ 34 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits,nightly \
@@ -115,6 +117,7 @@ cargo batch \
115 --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \ 117 --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \
116 --- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f2 \ 118 --- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f2 \
117 --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \ 119 --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \
120 --- build --release --manifest-path examples/stm32f334/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f334 \
118 --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \ 121 --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \
119 --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \ 122 --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \
120 --- build --release --manifest-path examples/stm32c0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32c0 \ 123 --- build --release --manifest-path examples/stm32c0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32c0 \
diff --git a/cyw43-firmware/43439A0.bin b/cyw43-firmware/43439A0.bin
index b46b3beff..017375277 100755
--- a/cyw43-firmware/43439A0.bin
+++ b/cyw43-firmware/43439A0.bin
Binary files differ
diff --git a/cyw43-firmware/43439A0_clm.bin b/cyw43-firmware/43439A0_clm.bin
index 6e3ba786b..1fedd753a 100755
--- a/cyw43-firmware/43439A0_clm.bin
+++ b/cyw43-firmware/43439A0_clm.bin
Binary files differ
diff --git a/cyw43-firmware/README.md b/cyw43-firmware/README.md
index 7381fdc56..db3d9c9cf 100644
--- a/cyw43-firmware/README.md
+++ b/cyw43-firmware/README.md
@@ -2,4 +2,8 @@
2 2
3Firmware obtained from https://github.com/Infineon/wifi-host-driver/tree/master/WiFi_Host_Driver/resources/firmware/COMPONENT_43439 3Firmware obtained from https://github.com/Infineon/wifi-host-driver/tree/master/WiFi_Host_Driver/resources/firmware/COMPONENT_43439
4 4
5Licensed under the [Infineon Permissive Binary License](./LICENSE-permissive-binary-license-1.0.txt) \ No newline at end of file 5Licensed under the [Infineon Permissive Binary License](./LICENSE-permissive-binary-license-1.0.txt)
6
7## Changelog
8
9* 2023-07-28: synced with `ad3bad0` - Update 43439 fw from 7.95.55 ot 7.95.62
diff --git a/cyw43-pio/src/lib.rs b/cyw43-pio/src/lib.rs
index dca30c74d..830a5b44a 100644
--- a/cyw43-pio/src/lib.rs
+++ b/cyw43-pio/src/lib.rs
@@ -8,7 +8,6 @@ use cyw43::SpiBusCyw43;
8use embassy_rp::dma::Channel; 8use embassy_rp::dma::Channel;
9use embassy_rp::gpio::{Drive, Level, Output, Pin, Pull, SlewRate}; 9use embassy_rp::gpio::{Drive, Level, Output, Pin, Pull, SlewRate};
10use embassy_rp::pio::{Common, Config, Direction, Instance, Irq, PioPin, ShiftDirection, StateMachine}; 10use embassy_rp::pio::{Common, Config, Direction, Instance, Irq, PioPin, ShiftDirection, StateMachine};
11use embassy_rp::relocate::RelocatedProgram;
12use embassy_rp::{pio_instr_util, Peripheral, PeripheralRef}; 11use embassy_rp::{pio_instr_util, Peripheral, PeripheralRef};
13use fixed::FixedU32; 12use fixed::FixedU32;
14use pio_proc::pio_asm; 13use pio_proc::pio_asm;
@@ -88,8 +87,6 @@ where
88 ".wrap" 87 ".wrap"
89 ); 88 );
90 89
91 let relocated = RelocatedProgram::new(&program.program);
92
93 let mut pin_io: embassy_rp::pio::Pin<PIO> = common.make_pio_pin(dio); 90 let mut pin_io: embassy_rp::pio::Pin<PIO> = common.make_pio_pin(dio);
94 pin_io.set_pull(Pull::None); 91 pin_io.set_pull(Pull::None);
95 pin_io.set_schmitt(true); 92 pin_io.set_schmitt(true);
@@ -102,7 +99,8 @@ where
102 pin_clk.set_slew_rate(SlewRate::Fast); 99 pin_clk.set_slew_rate(SlewRate::Fast);
103 100
104 let mut cfg = Config::default(); 101 let mut cfg = Config::default();
105 cfg.use_program(&common.load_program(&relocated), &[&pin_clk]); 102 let loaded_program = common.load_program(&program.program);
103 cfg.use_program(&loaded_program, &[&pin_clk]);
106 cfg.set_out_pins(&[&pin_io]); 104 cfg.set_out_pins(&[&pin_io]);
107 cfg.set_in_pins(&[&pin_io]); 105 cfg.set_in_pins(&[&pin_io]);
108 cfg.set_set_pins(&[&pin_io]); 106 cfg.set_set_pins(&[&pin_io]);
@@ -142,7 +140,7 @@ where
142 sm, 140 sm,
143 irq, 141 irq,
144 dma: dma.into_ref(), 142 dma: dma.into_ref(),
145 wrap_target: relocated.wrap().target, 143 wrap_target: loaded_program.wrap.target,
146 } 144 }
147 } 145 }
148 146
diff --git a/embassy-boot/rp/src/lib.rs b/embassy-boot/rp/src/lib.rs
index 25329f9e9..35fc104ec 100644
--- a/embassy-boot/rp/src/lib.rs
+++ b/embassy-boot/rp/src/lib.rs
@@ -6,7 +6,7 @@ mod fmt;
6#[cfg(feature = "nightly")] 6#[cfg(feature = "nightly")]
7pub use embassy_boot::FirmwareUpdater; 7pub use embassy_boot::FirmwareUpdater;
8pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State}; 8pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State};
9use embassy_rp::flash::{Flash, ERASE_SIZE}; 9use embassy_rp::flash::{Blocking, Flash, ERASE_SIZE};
10use embassy_rp::peripherals::{FLASH, WATCHDOG}; 10use embassy_rp::peripherals::{FLASH, WATCHDOG};
11use embassy_rp::watchdog::Watchdog; 11use embassy_rp::watchdog::Watchdog;
12use embassy_time::Duration; 12use embassy_time::Duration;
@@ -58,14 +58,14 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
58 58
59/// A flash implementation that will feed a watchdog when touching flash. 59/// A flash implementation that will feed a watchdog when touching flash.
60pub struct WatchdogFlash<'d, const SIZE: usize> { 60pub struct WatchdogFlash<'d, const SIZE: usize> {
61 flash: Flash<'d, FLASH, SIZE>, 61 flash: Flash<'d, FLASH, Blocking, SIZE>,
62 watchdog: Watchdog, 62 watchdog: Watchdog,
63} 63}
64 64
65impl<'d, const SIZE: usize> WatchdogFlash<'d, SIZE> { 65impl<'d, const SIZE: usize> WatchdogFlash<'d, SIZE> {
66 /// Start a new watchdog with a given flash and watchdog peripheral and a timeout 66 /// Start a new watchdog with a given flash and watchdog peripheral and a timeout
67 pub fn start(flash: FLASH, watchdog: WATCHDOG, timeout: Duration) -> Self { 67 pub fn start(flash: FLASH, watchdog: WATCHDOG, timeout: Duration) -> Self {
68 let flash: Flash<'_, FLASH, SIZE> = Flash::new(flash); 68 let flash = Flash::<_, Blocking, SIZE>::new(flash);
69 let mut watchdog = Watchdog::new(watchdog); 69 let mut watchdog = Watchdog::new(watchdog);
70 watchdog.start(timeout); 70 watchdog.start(timeout);
71 Self { flash, watchdog } 71 Self { flash, watchdog }
@@ -73,12 +73,12 @@ impl<'d, const SIZE: usize> WatchdogFlash<'d, SIZE> {
73} 73}
74 74
75impl<'d, const SIZE: usize> ErrorType for WatchdogFlash<'d, SIZE> { 75impl<'d, const SIZE: usize> ErrorType for WatchdogFlash<'d, SIZE> {
76 type Error = <Flash<'d, FLASH, SIZE> as ErrorType>::Error; 76 type Error = <Flash<'d, FLASH, Blocking, SIZE> as ErrorType>::Error;
77} 77}
78 78
79impl<'d, const SIZE: usize> NorFlash for WatchdogFlash<'d, SIZE> { 79impl<'d, const SIZE: usize> NorFlash for WatchdogFlash<'d, SIZE> {
80 const WRITE_SIZE: usize = <Flash<'d, FLASH, SIZE> as NorFlash>::WRITE_SIZE; 80 const WRITE_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as NorFlash>::WRITE_SIZE;
81 const ERASE_SIZE: usize = <Flash<'d, FLASH, SIZE> as NorFlash>::ERASE_SIZE; 81 const ERASE_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as NorFlash>::ERASE_SIZE;
82 82
83 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { 83 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
84 self.watchdog.feed(); 84 self.watchdog.feed();
@@ -91,7 +91,7 @@ impl<'d, const SIZE: usize> NorFlash for WatchdogFlash<'d, SIZE> {
91} 91}
92 92
93impl<'d, const SIZE: usize> ReadNorFlash for WatchdogFlash<'d, SIZE> { 93impl<'d, const SIZE: usize> ReadNorFlash for WatchdogFlash<'d, SIZE> {
94 const READ_SIZE: usize = <Flash<'d, FLASH, SIZE> as ReadNorFlash>::READ_SIZE; 94 const READ_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as ReadNorFlash>::READ_SIZE;
95 fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> { 95 fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> {
96 self.watchdog.feed(); 96 self.watchdog.feed();
97 self.flash.read(offset, data) 97 self.flash.read(offset, data)
diff --git a/embassy-hal-common/Cargo.toml b/embassy-hal-internal/Cargo.toml
index 18c758d7b..42e03199c 100644
--- a/embassy-hal-common/Cargo.toml
+++ b/embassy-hal-internal/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2name = "embassy-hal-common" 2name = "embassy-hal-internal"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/embassy-hal-internal/README.md b/embassy-hal-internal/README.md
new file mode 100644
index 000000000..d6539701b
--- /dev/null
+++ b/embassy-hal-internal/README.md
@@ -0,0 +1,16 @@
1# embassy-macros
2
3An [Embassy](https://embassy.dev) project.
4
5Internal implementation details for Embassy HALs. DO NOT USE DIRECTLY. Embassy HALs (`embassy-nrf`, `embassy-stm32`, `embassy-rp`) already reexport
6everything you need to use them effectively.
7
8## License
9
10This work is licensed under either of
11
12- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
13 <http://www.apache.org/licenses/LICENSE-2.0>)
14- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
15
16at your option.
diff --git a/embassy-hal-common/build.rs b/embassy-hal-internal/build.rs
index 6fe82b44f..6fe82b44f 100644
--- a/embassy-hal-common/build.rs
+++ b/embassy-hal-internal/build.rs
diff --git a/embassy-hal-common/src/atomic_ring_buffer.rs b/embassy-hal-internal/src/atomic_ring_buffer.rs
index ea84925c4..ea84925c4 100644
--- a/embassy-hal-common/src/atomic_ring_buffer.rs
+++ b/embassy-hal-internal/src/atomic_ring_buffer.rs
diff --git a/embassy-hal-common/src/drop.rs b/embassy-hal-internal/src/drop.rs
index 7cd16aaec..7cd16aaec 100644
--- a/embassy-hal-common/src/drop.rs
+++ b/embassy-hal-internal/src/drop.rs
diff --git a/embassy-hal-common/src/fmt.rs b/embassy-hal-internal/src/fmt.rs
index 066970813..066970813 100644
--- a/embassy-hal-common/src/fmt.rs
+++ b/embassy-hal-internal/src/fmt.rs
diff --git a/embassy-hal-common/src/interrupt.rs b/embassy-hal-internal/src/interrupt.rs
index b970aa2cd..b970aa2cd 100644
--- a/embassy-hal-common/src/interrupt.rs
+++ b/embassy-hal-internal/src/interrupt.rs
diff --git a/embassy-hal-common/src/lib.rs b/embassy-hal-internal/src/lib.rs
index 235964aa4..3640ea184 100644
--- a/embassy-hal-common/src/lib.rs
+++ b/embassy-hal-internal/src/lib.rs
@@ -1,5 +1,6 @@
1#![no_std] 1#![no_std]
2#![allow(clippy::new_without_default)] 2#![allow(clippy::new_without_default)]
3#![doc = include_str!("../README.md")]
3 4
4// This mod MUST go first, so that the others see its macros. 5// This mod MUST go first, so that the others see its macros.
5pub(crate) mod fmt; 6pub(crate) mod fmt;
diff --git a/embassy-hal-common/src/macros.rs b/embassy-hal-internal/src/macros.rs
index f06b46002..f06b46002 100644
--- a/embassy-hal-common/src/macros.rs
+++ b/embassy-hal-internal/src/macros.rs
diff --git a/embassy-hal-common/src/peripheral.rs b/embassy-hal-internal/src/peripheral.rs
index 38b4c452e..38b4c452e 100644
--- a/embassy-hal-common/src/peripheral.rs
+++ b/embassy-hal-internal/src/peripheral.rs
diff --git a/embassy-hal-common/src/ratio.rs b/embassy-hal-internal/src/ratio.rs
index 9a8808a33..9a8808a33 100644
--- a/embassy-hal-common/src/ratio.rs
+++ b/embassy-hal-internal/src/ratio.rs
diff --git a/embassy-hal-common/src/ring_buffer.rs b/embassy-hal-internal/src/ring_buffer.rs
index fcad68bb1..fcad68bb1 100644
--- a/embassy-hal-common/src/ring_buffer.rs
+++ b/embassy-hal-internal/src/ring_buffer.rs
diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml
index e4524af5b..402ad2d70 100644
--- a/embassy-lora/Cargo.toml
+++ b/embassy-lora/Cargo.toml
@@ -12,7 +12,7 @@ target = "thumbv7em-none-eabi"
12 12
13[features] 13[features]
14stm32wl = ["dep:embassy-stm32"] 14stm32wl = ["dep:embassy-stm32"]
15time = [] 15time = ["embassy-time", "lorawan-device"]
16defmt = ["dep:defmt", "lorawan-device/defmt"] 16defmt = ["dep:defmt", "lorawan-device/defmt"]
17 17
18[dependencies] 18[dependencies]
@@ -20,18 +20,12 @@ defmt = ["dep:defmt", "lorawan-device/defmt"]
20defmt = { version = "0.3", optional = true } 20defmt = { version = "0.3", optional = true }
21log = { version = "0.4.14", optional = true } 21log = { version = "0.4.14", optional = true }
22 22
23embassy-time = { version = "0.1.2", path = "../embassy-time" } 23embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true }
24embassy-sync = { version = "0.2.0", path = "../embassy-sync" } 24embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
25embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } 25embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true }
26embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
27embedded-hal-async = { version = "=0.2.0-alpha.2" } 26embedded-hal-async = { version = "=0.2.0-alpha.2" }
28embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false }
29futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
30embedded-hal = { version = "0.2", features = ["unproven"] } 27embedded-hal = { version = "0.2", features = ["unproven"] }
31bit_field = { version = "0.10" }
32 28
29futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
33lora-phy = { version = "1" } 30lora-phy = { version = "1" }
34lorawan-device = { version = "0.10.0", default-features = false, features = ["async"] } 31lorawan-device = { version = "0.10.0", default-features = false, features = ["async"], optional = true }
35
36[patch.crates-io]
37lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" }
diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs
index 79f8cde7b..37f220da0 100644
--- a/embassy-net-esp-hosted/src/control.rs
+++ b/embassy-net-esp-hosted/src/control.rs
@@ -1,5 +1,4 @@
1use ch::driver::LinkState; 1use ch::driver::LinkState;
2use defmt::Debug2Format;
3use embassy_net_driver_channel as ch; 2use embassy_net_driver_channel as ch;
4use heapless::String; 3use heapless::String;
5 4
@@ -57,7 +56,6 @@ impl<'a> Control<'a> {
57 let proto::CtrlMsgPayload::RespConnectAp(resp) = resp.payload.unwrap() else { 56 let proto::CtrlMsgPayload::RespConnectAp(resp) = resp.payload.unwrap() else {
58 panic!("unexpected resp") 57 panic!("unexpected resp")
59 }; 58 };
60 debug!("======= {:?}", Debug2Format(&resp));
61 assert_eq!(resp.resp, 0); 59 assert_eq!(resp.resp, 0);
62 self.state_ch.set_link_state(LinkState::Up); 60 self.state_ch.set_link_state(LinkState::Up);
63 } 61 }
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs
index 81c751a2c..3f9150168 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -32,12 +32,14 @@ pub use smoltcp::iface::MulticastError;
32use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; 32use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage};
33#[cfg(feature = "dhcpv4")] 33#[cfg(feature = "dhcpv4")]
34use smoltcp::socket::dhcpv4::{self, RetryConfig}; 34use smoltcp::socket::dhcpv4::{self, RetryConfig};
35#[cfg(feature = "medium-ethernet")]
36pub use smoltcp::wire::EthernetAddress;
37#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
38pub use smoltcp::wire::HardwareAddress;
35#[cfg(feature = "udp")] 39#[cfg(feature = "udp")]
36pub use smoltcp::wire::IpListenEndpoint; 40pub use smoltcp::wire::IpListenEndpoint;
37#[cfg(feature = "medium-ethernet")]
38pub use smoltcp::wire::{EthernetAddress, HardwareAddress};
39#[cfg(feature = "medium-ieee802154")] 41#[cfg(feature = "medium-ieee802154")]
40pub use smoltcp::wire::{HardwareAddress, Ieee802154Address}; 42pub use smoltcp::wire::{Ieee802154Address, Ieee802154Frame};
41pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint}; 43pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint};
42#[cfg(feature = "proto-ipv4")] 44#[cfg(feature = "proto-ipv4")]
43pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; 45pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr};
@@ -583,7 +585,7 @@ impl SocketStack {
583impl<D: Driver + 'static> Inner<D> { 585impl<D: Driver + 'static> Inner<D> {
584 #[cfg(feature = "proto-ipv4")] 586 #[cfg(feature = "proto-ipv4")]
585 fn apply_config_v4(&mut self, s: &mut SocketStack, config: StaticConfigV4) { 587 fn apply_config_v4(&mut self, s: &mut SocketStack, config: StaticConfigV4) {
586 #[cfg(feature = "medium-ethernet")] 588 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
587 let medium = self.device.capabilities().medium; 589 let medium = self.device.capabilities().medium;
588 590
589 debug!("Acquired IP configuration:"); 591 debug!("Acquired IP configuration:");
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 57dd22f1c..d10cd2c34 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -93,7 +93,7 @@ _gpio-p1 = []
93[dependencies] 93[dependencies]
94embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } 94embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true }
95embassy-sync = { version = "0.2.0", path = "../embassy-sync" } 95embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
96embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-3"] } 96embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] }
97embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 97embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
98embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional=true } 98embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional=true }
99 99
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 9bc1c1e7a..5a0a3c7c0 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -15,8 +15,8 @@ use core::slice;
15use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering}; 15use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering};
16use core::task::Poll; 16use core::task::Poll;
17 17
18use embassy_hal_common::atomic_ring_buffer::RingBuffer; 18use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
19use embassy_hal_common::{into_ref, PeripheralRef}; 19use embassy_hal_internal::{into_ref, PeripheralRef};
20use embassy_sync::waitqueue::AtomicWaker; 20use embassy_sync::waitqueue::AtomicWaker;
21// Re-export SVD variants to allow user to directly set values 21// Re-export SVD variants to allow user to directly set values
22pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 22pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index 8776000c8..70e4b4863 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 192 * 1024;
8 8
9pub const RESET_PIN: u32 = 21; 9pub const RESET_PIN: u32 = 21;
10 10
11embassy_hal_common::peripherals! { 11embassy_hal_internal::peripherals! {
12 // RTC 12 // RTC
13 RTC0, 13 RTC0,
14 RTC1, 14 RTC1,
@@ -208,7 +208,7 @@ impl_ppi_channel!(PPI_CH31, 31 => static);
208impl_saadc_input!(P0_04, ANALOG_INPUT2); 208impl_saadc_input!(P0_04, ANALOG_INPUT2);
209impl_saadc_input!(P0_05, ANALOG_INPUT3); 209impl_saadc_input!(P0_05, ANALOG_INPUT3);
210 210
211embassy_hal_common::interrupt_mod!( 211embassy_hal_internal::interrupt_mod!(
212 POWER_CLOCK, 212 POWER_CLOCK,
213 RADIO, 213 RADIO,
214 UARTE0_UART0, 214 UARTE0_UART0,
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index 5519e8953..7416d3912 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 192 * 1024;
8 8
9pub const RESET_PIN: u32 = 21; 9pub const RESET_PIN: u32 = 21;
10 10
11embassy_hal_common::peripherals! { 11embassy_hal_internal::peripherals! {
12 // RTC 12 // RTC
13 RTC0, 13 RTC0,
14 RTC1, 14 RTC1,
@@ -234,7 +234,7 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5);
234impl_saadc_input!(P0_30, ANALOG_INPUT6); 234impl_saadc_input!(P0_30, ANALOG_INPUT6);
235impl_saadc_input!(P0_31, ANALOG_INPUT7); 235impl_saadc_input!(P0_31, ANALOG_INPUT7);
236 236
237embassy_hal_common::interrupt_mod!( 237embassy_hal_internal::interrupt_mod!(
238 POWER_CLOCK, 238 POWER_CLOCK,
239 RADIO, 239 RADIO,
240 UARTE0_UART0, 240 UARTE0_UART0,
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index d5367c59a..588010685 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 192 * 1024;
8 8
9pub const RESET_PIN: u32 = 21; 9pub const RESET_PIN: u32 = 21;
10 10
11embassy_hal_common::peripherals! { 11embassy_hal_internal::peripherals! {
12 // RTC 12 // RTC
13 RTC0, 13 RTC0,
14 RTC1, 14 RTC1,
@@ -236,7 +236,7 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5);
236impl_saadc_input!(P0_30, ANALOG_INPUT6); 236impl_saadc_input!(P0_30, ANALOG_INPUT6);
237impl_saadc_input!(P0_31, ANALOG_INPUT7); 237impl_saadc_input!(P0_31, ANALOG_INPUT7);
238 238
239embassy_hal_common::interrupt_mod!( 239embassy_hal_internal::interrupt_mod!(
240 POWER_CLOCK, 240 POWER_CLOCK,
241 RADIO, 241 RADIO,
242 UARTE0_UART0, 242 UARTE0_UART0,
diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs
index 785170447..0ecddaf31 100644
--- a/embassy-nrf/src/chips/nrf52820.rs
+++ b/embassy-nrf/src/chips/nrf52820.rs
@@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 256 * 1024;
8 8
9pub const RESET_PIN: u32 = 18; 9pub const RESET_PIN: u32 = 18;
10 10
11embassy_hal_common::peripherals! { 11embassy_hal_internal::peripherals! {
12 // USB 12 // USB
13 USBD, 13 USBD,
14 14
@@ -224,7 +224,7 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
224impl_ppi_channel!(PPI_CH30, 30 => static); 224impl_ppi_channel!(PPI_CH30, 30 => static);
225impl_ppi_channel!(PPI_CH31, 31 => static); 225impl_ppi_channel!(PPI_CH31, 31 => static);
226 226
227embassy_hal_common::interrupt_mod!( 227embassy_hal_internal::interrupt_mod!(
228 POWER_CLOCK, 228 POWER_CLOCK,
229 RADIO, 229 RADIO,
230 UARTE0_UART0, 230 UARTE0_UART0,
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index b77564a5c..ae39628d2 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -12,7 +12,7 @@ pub const FLASH_SIZE: usize = 512 * 1024;
12 12
13pub const RESET_PIN: u32 = 21; 13pub const RESET_PIN: u32 = 21;
14 14
15embassy_hal_common::peripherals! { 15embassy_hal_internal::peripherals! {
16 // RTC 16 // RTC
17 RTC0, 17 RTC0,
18 RTC1, 18 RTC1,
@@ -263,7 +263,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7);
263 263
264impl_i2s!(I2S, I2S, I2S); 264impl_i2s!(I2S, I2S, I2S);
265 265
266embassy_hal_common::interrupt_mod!( 266embassy_hal_internal::interrupt_mod!(
267 POWER_CLOCK, 267 POWER_CLOCK,
268 RADIO, 268 RADIO,
269 UARTE0_UART0, 269 UARTE0_UART0,
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index bff7f4ebb..b8830b338 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 512 * 1024;
8 8
9pub const RESET_PIN: u32 = 18; 9pub const RESET_PIN: u32 = 18;
10 10
11embassy_hal_common::peripherals! { 11embassy_hal_internal::peripherals! {
12 // USB 12 // USB
13 USBD, 13 USBD,
14 14
@@ -306,7 +306,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7);
306 306
307impl_i2s!(I2S, I2S, I2S); 307impl_i2s!(I2S, I2S, I2S);
308 308
309embassy_hal_common::interrupt_mod!( 309embassy_hal_internal::interrupt_mod!(
310 POWER_CLOCK, 310 POWER_CLOCK,
311 RADIO, 311 RADIO,
312 UARTE0_UART0, 312 UARTE0_UART0,
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index 9b0050823..a490cb079 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 1024 * 1024;
8 8
9pub const RESET_PIN: u32 = 18; 9pub const RESET_PIN: u32 = 18;
10 10
11embassy_hal_common::peripherals! { 11embassy_hal_internal::peripherals! {
12 // USB 12 // USB
13 USBD, 13 USBD,
14 14
@@ -311,7 +311,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7);
311 311
312impl_i2s!(I2S, I2S, I2S); 312impl_i2s!(I2S, I2S, I2S);
313 313
314embassy_hal_common::interrupt_mod!( 314embassy_hal_internal::interrupt_mod!(
315 POWER_CLOCK, 315 POWER_CLOCK,
316 RADIO, 316 RADIO,
317 UARTE0_UART0, 317 UARTE0_UART0,
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index 410ae921c..afc2c4a7e 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -218,7 +218,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
218 218
219pub const FLASH_SIZE: usize = 1024 * 1024; 219pub const FLASH_SIZE: usize = 1024 * 1024;
220 220
221embassy_hal_common::peripherals! { 221embassy_hal_internal::peripherals! {
222 // USB 222 // USB
223 USBD, 223 USBD,
224 224
@@ -506,7 +506,7 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5);
506impl_saadc_input!(P0_19, ANALOG_INPUT6); 506impl_saadc_input!(P0_19, ANALOG_INPUT6);
507impl_saadc_input!(P0_20, ANALOG_INPUT7); 507impl_saadc_input!(P0_20, ANALOG_INPUT7);
508 508
509embassy_hal_common::interrupt_mod!( 509embassy_hal_internal::interrupt_mod!(
510 FPU, 510 FPU,
511 CACHE, 511 CACHE,
512 SPU, 512 SPU,
diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs
index 6ac783085..dee666a61 100644
--- a/embassy-nrf/src/chips/nrf5340_net.rs
+++ b/embassy-nrf/src/chips/nrf5340_net.rs
@@ -109,7 +109,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
109 109
110pub const FLASH_SIZE: usize = 256 * 1024; 110pub const FLASH_SIZE: usize = 256 * 1024;
111 111
112embassy_hal_common::peripherals! { 112embassy_hal_internal::peripherals! {
113 // RTC 113 // RTC
114 RTC0, 114 RTC0,
115 RTC1, 115 RTC1,
@@ -342,7 +342,7 @@ impl_ppi_channel!(PPI_CH29, 29 => configurable);
342impl_ppi_channel!(PPI_CH30, 30 => configurable); 342impl_ppi_channel!(PPI_CH30, 30 => configurable);
343impl_ppi_channel!(PPI_CH31, 31 => configurable); 343impl_ppi_channel!(PPI_CH31, 31 => configurable);
344 344
345embassy_hal_common::interrupt_mod!( 345embassy_hal_internal::interrupt_mod!(
346 CLOCK_POWER, 346 CLOCK_POWER,
347 RADIO, 347 RADIO,
348 RNG, 348 RNG,
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index 67ea032ff..495285ba3 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -169,7 +169,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
169 169
170pub const FLASH_SIZE: usize = 1024 * 1024; 170pub const FLASH_SIZE: usize = 1024 * 1024;
171 171
172embassy_hal_common::peripherals! { 172embassy_hal_internal::peripherals! {
173 // RTC 173 // RTC
174 RTC0, 174 RTC0,
175 RTC1, 175 RTC1,
@@ -368,7 +368,7 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5);
368impl_saadc_input!(P0_19, ANALOG_INPUT6); 368impl_saadc_input!(P0_19, ANALOG_INPUT6);
369impl_saadc_input!(P0_20, ANALOG_INPUT7); 369impl_saadc_input!(P0_20, ANALOG_INPUT7);
370 370
371embassy_hal_common::interrupt_mod!( 371embassy_hal_internal::interrupt_mod!(
372 SPU, 372 SPU,
373 CLOCK_POWER, 373 CLOCK_POWER,
374 UARTE0_SPIM0_SPIS0_TWIM0_TWIS0, 374 UARTE0_SPIM0_SPIS0_TWIM0_TWIS0,
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 895ab9340..ea2b76096 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -5,7 +5,7 @@ use core::convert::Infallible;
5use core::hint::unreachable_unchecked; 5use core::hint::unreachable_unchecked;
6 6
7use cfg_if::cfg_if; 7use cfg_if::cfg_if;
8use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 8use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
9 9
10use self::sealed::Pin as _; 10use self::sealed::Pin as _;
11use crate::pac::p0 as gpio; 11use crate::pac::p0 as gpio;
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index 6550f2abd..7488bc085 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -4,7 +4,7 @@ use core::convert::Infallible;
4use core::future::{poll_fn, Future}; 4use core::future::{poll_fn, Future};
5use core::task::{Context, Poll}; 5use core::task::{Context, Poll};
6 6
7use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; 7use embassy_hal_internal::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9 9
10use crate::gpio::sealed::Pin as _; 10use crate::gpio::sealed::Pin as _;
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs
index fea38c4c0..907acdf4c 100644
--- a/embassy-nrf/src/i2s.rs
+++ b/embassy-nrf/src/i2s.rs
@@ -9,8 +9,8 @@ use core::ops::{Deref, DerefMut};
9use core::sync::atomic::{compiler_fence, Ordering}; 9use core::sync::atomic::{compiler_fence, Ordering};
10use core::task::Poll; 10use core::task::Poll;
11 11
12use embassy_hal_common::drop::OnDrop; 12use embassy_hal_internal::drop::OnDrop;
13use embassy_hal_common::{into_ref, PeripheralRef}; 13use embassy_hal_internal::{into_ref, PeripheralRef};
14 14
15use crate::gpio::{AnyPin, Pin as GpioPin}; 15use crate::gpio::{AnyPin, Pin as GpioPin};
16use crate::interrupt::typelevel::Interrupt; 16use crate::interrupt::typelevel::Interrupt;
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index d23759f9d..355a00497 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -98,7 +98,7 @@ mod chip;
98/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) 98/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
99/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to 99/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
100/// prove at compile-time that the right interrupts have been bound. 100/// prove at compile-time that the right interrupts have been bound.
101// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. 101// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
102#[macro_export] 102#[macro_export]
103macro_rules! bind_interrupts { 103macro_rules! bind_interrupts {
104 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { 104 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
@@ -127,7 +127,7 @@ pub use chip::pac;
127#[cfg(not(feature = "unstable-pac"))] 127#[cfg(not(feature = "unstable-pac"))]
128pub(crate) use chip::pac; 128pub(crate) use chip::pac;
129pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE}; 129pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE};
130pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 130pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
131 131
132pub use crate::chip::interrupt; 132pub use crate::chip::interrupt;
133pub use crate::pac::NVIC_PRIO_BITS; 133pub use crate::pac::NVIC_PRIO_BITS;
diff --git a/embassy-nrf/src/nvmc.rs b/embassy-nrf/src/nvmc.rs
index 91a5a272f..de840b886 100644
--- a/embassy-nrf/src/nvmc.rs
+++ b/embassy-nrf/src/nvmc.rs
@@ -2,7 +2,7 @@
2 2
3use core::{ptr, slice}; 3use core::{ptr, slice};
4 4
5use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use embedded_storage::nor_flash::{ 6use embedded_storage::nor_flash::{
7 ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, 7 ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash,
8}; 8};
diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs
index 217884d1c..01f41e9f9 100644
--- a/embassy-nrf/src/pdm.rs
+++ b/embassy-nrf/src/pdm.rs
@@ -6,8 +6,8 @@ use core::marker::PhantomData;
6use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
7use core::task::Poll; 7use core::task::Poll;
8 8
9use embassy_hal_common::drop::OnDrop; 9use embassy_hal_internal::drop::OnDrop;
10use embassy_hal_common::{into_ref, PeripheralRef}; 10use embassy_hal_internal::{into_ref, PeripheralRef};
11use fixed::types::I7F1; 11use fixed::types::I7F1;
12use futures::future::poll_fn; 12use futures::future::poll_fn;
13 13
diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs
index 40ccb2f09..0bc7f821e 100644
--- a/embassy-nrf/src/ppi/dppi.rs
+++ b/embassy-nrf/src/ppi/dppi.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::into_ref; 1use embassy_hal_internal::into_ref;
2 2
3use super::{Channel, ConfigurableChannel, Event, Ppi, Task}; 3use super::{Channel, ConfigurableChannel, Event, Ppi, Task};
4use crate::{pac, Peripheral}; 4use crate::{pac, Peripheral};
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs
index ff6593bd5..5b4a64388 100644
--- a/embassy-nrf/src/ppi/mod.rs
+++ b/embassy-nrf/src/ppi/mod.rs
@@ -18,7 +18,7 @@
18use core::marker::PhantomData; 18use core::marker::PhantomData;
19use core::ptr::NonNull; 19use core::ptr::NonNull;
20 20
21use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 21use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
22 22
23use crate::{peripherals, Peripheral}; 23use crate::{peripherals, Peripheral};
24 24
diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs
index 1fe898625..3e9e9fc81 100644
--- a/embassy-nrf/src/ppi/ppi.rs
+++ b/embassy-nrf/src/ppi/ppi.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::into_ref; 1use embassy_hal_internal::into_ref;
2 2
3use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; 3use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task};
4use crate::{pac, Peripheral}; 4use crate::{pac, Peripheral};
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index c8c81fa01..2f0397632 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -4,7 +4,7 @@
4 4
5use core::sync::atomic::{compiler_fence, Ordering}; 5use core::sync::atomic::{compiler_fence, Ordering};
6 6
7use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8 8
9use crate::gpio::sealed::Pin as _; 9use crate::gpio::sealed::Pin as _;
10use crate::gpio::{AnyPin, Pin as GpioPin, PselBits}; 10use crate::gpio::{AnyPin, Pin as GpioPin, PselBits};
diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs
index 8bac87d37..2aa50a2ba 100644
--- a/embassy-nrf/src/qdec.rs
+++ b/embassy-nrf/src/qdec.rs
@@ -6,7 +6,7 @@ use core::future::poll_fn;
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::task::Poll; 7use core::task::Poll;
8 8
9use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10 10
11use crate::gpio::sealed::Pin as _; 11use crate::gpio::sealed::Pin as _;
12use crate::gpio::{AnyPin, Pin as GpioPin}; 12use crate::gpio::{AnyPin, Pin as GpioPin};
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index baefc7967..36ee33f6d 100644
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -7,8 +7,8 @@ use core::marker::PhantomData;
7use core::ptr; 7use core::ptr;
8use core::task::Poll; 8use core::task::Poll;
9 9
10use embassy_hal_common::drop::OnDrop; 10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_common::{into_ref, PeripheralRef}; 11use embassy_hal_internal::{into_ref, PeripheralRef};
12use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; 12use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash};
13 13
14use crate::gpio::{self, Pin as GpioPin}; 14use crate::gpio::{self, Pin as GpioPin};
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs
index 923b8b467..e2803f0d3 100644
--- a/embassy-nrf/src/rng.rs
+++ b/embassy-nrf/src/rng.rs
@@ -8,8 +8,8 @@ use core::ptr;
8use core::sync::atomic::{AtomicPtr, Ordering}; 8use core::sync::atomic::{AtomicPtr, Ordering};
9use core::task::Poll; 9use core::task::Poll;
10 10
11use embassy_hal_common::drop::OnDrop; 11use embassy_hal_internal::drop::OnDrop;
12use embassy_hal_common::{into_ref, PeripheralRef}; 12use embassy_hal_internal::{into_ref, PeripheralRef};
13use embassy_sync::waitqueue::AtomicWaker; 13use embassy_sync::waitqueue::AtomicWaker;
14 14
15use crate::interrupt::typelevel::Interrupt; 15use crate::interrupt::typelevel::Interrupt;
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index 23292924c..662b05614 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -6,8 +6,8 @@ use core::future::poll_fn;
6use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
7use core::task::Poll; 7use core::task::Poll;
8 8
9use embassy_hal_common::drop::OnDrop; 9use embassy_hal_internal::drop::OnDrop;
10use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 10use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
11use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
12use pac::{saadc, SAADC}; 12use pac::{saadc, SAADC};
13use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A}; 13use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A};
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index b7dc332e9..4673a0175 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -8,7 +8,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
8use core::task::Poll; 8use core::task::Poll;
9 9
10use embassy_embedded_hal::SetConfig; 10use embassy_embedded_hal::SetConfig;
11use embassy_hal_common::{into_ref, PeripheralRef}; 11use embassy_hal_internal::{into_ref, PeripheralRef};
12pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 12pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
13pub use pac::spim0::frequency::FREQUENCY_A as Frequency; 13pub use pac::spim0::frequency::FREQUENCY_A as Frequency;
14 14
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
index aa438415a..212825121 100644
--- a/embassy-nrf/src/spis.rs
+++ b/embassy-nrf/src/spis.rs
@@ -7,7 +7,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
7use core::task::Poll; 7use core::task::Poll;
8 8
9use embassy_embedded_hal::SetConfig; 9use embassy_embedded_hal::SetConfig;
10use embassy_hal_common::{into_ref, PeripheralRef}; 10use embassy_hal_internal::{into_ref, PeripheralRef};
11pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 11pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
12 12
13use crate::chip::FORCE_COPY_BUFFER_SIZE; 13use crate::chip::FORCE_COPY_BUFFER_SIZE;
diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs
index 491e92c04..cec46d8d0 100644
--- a/embassy-nrf/src/temp.rs
+++ b/embassy-nrf/src/temp.rs
@@ -3,8 +3,8 @@
3use core::future::poll_fn; 3use core::future::poll_fn;
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_hal_common::drop::OnDrop; 6use embassy_hal_internal::drop::OnDrop;
7use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use fixed::types::I30F2; 9use fixed::types::I30F2;
10 10
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index 04748238d..3dbfdac42 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -6,7 +6,7 @@
6 6
7#![macro_use] 7#![macro_use]
8 8
9use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10 10
11use crate::ppi::{Event, Task}; 11use crate::ppi::{Event, Task};
12use crate::{pac, Peripheral}; 12use crate::{pac, Peripheral};
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 2ad0d19b1..fdea480e3 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -9,7 +9,7 @@ use core::sync::atomic::Ordering::SeqCst;
9use core::task::Poll; 9use core::task::Poll;
10 10
11use embassy_embedded_hal::SetConfig; 11use embassy_embedded_hal::SetConfig;
12use embassy_hal_common::{into_ref, PeripheralRef}; 12use embassy_hal_internal::{into_ref, PeripheralRef};
13use embassy_sync::waitqueue::AtomicWaker; 13use embassy_sync::waitqueue::AtomicWaker;
14#[cfg(feature = "time")] 14#[cfg(feature = "time")]
15use embassy_time::{Duration, Instant}; 15use embassy_time::{Duration, Instant};
diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs
index a115d5616..c6c020557 100644
--- a/embassy-nrf/src/twis.rs
+++ b/embassy-nrf/src/twis.rs
@@ -8,7 +8,7 @@ use core::sync::atomic::compiler_fence;
8use core::sync::atomic::Ordering::SeqCst; 8use core::sync::atomic::Ordering::SeqCst;
9use core::task::Poll; 9use core::task::Poll;
10 10
11use embassy_hal_common::{into_ref, PeripheralRef}; 11use embassy_hal_internal::{into_ref, PeripheralRef};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(feature = "time")] 13#[cfg(feature = "time")]
14use embassy_time::{Duration, Instant}; 14use embassy_time::{Duration, Instant};
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 48d57fea4..e79df3561 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -18,8 +18,8 @@ use core::marker::PhantomData;
18use core::sync::atomic::{compiler_fence, Ordering}; 18use core::sync::atomic::{compiler_fence, Ordering};
19use core::task::Poll; 19use core::task::Poll;
20 20
21use embassy_hal_common::drop::OnDrop; 21use embassy_hal_internal::drop::OnDrop;
22use embassy_hal_common::{into_ref, PeripheralRef}; 22use embassy_hal_internal::{into_ref, PeripheralRef};
23use pac::uarte0::RegisterBlock; 23use pac::uarte0::RegisterBlock;
24// Re-export SVD variants to allow user to directly set values. 24// Re-export SVD variants to allow user to directly set values.
25pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 25pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
diff --git a/embassy-nrf/src/usb/mod.rs b/embassy-nrf/src/usb/mod.rs
index 76cf40ac7..e26b49db3 100644
--- a/embassy-nrf/src/usb/mod.rs
+++ b/embassy-nrf/src/usb/mod.rs
@@ -11,7 +11,7 @@ use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
11use core::task::Poll; 11use core::task::Poll;
12 12
13use cortex_m::peripheral::NVIC; 13use cortex_m::peripheral::NVIC;
14use embassy_hal_common::{into_ref, PeripheralRef}; 14use embassy_hal_internal::{into_ref, PeripheralRef};
15use embassy_sync::waitqueue::AtomicWaker; 15use embassy_sync::waitqueue::AtomicWaker;
16use embassy_usb_driver as driver; 16use embassy_usb_driver as driver;
17use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported}; 17use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported};
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index 8f3ed885d..6310ffb62 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -16,7 +16,7 @@ flavors = [
16default = [ "rt" ] 16default = [ "rt" ]
17rt = [ "rp-pac/rt" ] 17rt = [ "rp-pac/rt" ]
18 18
19defmt = ["dep:defmt", "embassy-usb-driver?/defmt", "embassy-hal-common/defmt"] 19defmt = ["dep:defmt", "embassy-usb-driver?/defmt", "embassy-hal-internal/defmt"]
20 20
21# critical section that is safe for multicore use 21# critical section that is safe for multicore use
22critical-section-impl = ["critical-section/restore-state-u8"] 22critical-section-impl = ["critical-section/restore-state-u8"]
@@ -48,7 +48,7 @@ boot2-w25x10cl = []
48run-from-ram = [] 48run-from-ram = []
49 49
50# Enable nightly-only features 50# Enable nightly-only features
51nightly = ["embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb-driver", "dep:embedded-io"] 51nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "embassy-embedded-hal/nightly", "dep:embassy-usb-driver", "dep:embedded-io"]
52 52
53# Implement embedded-hal 1.0 alpha traits. 53# Implement embedded-hal 1.0 alpha traits.
54# Implement embedded-hal-async traits if `nightly` is set as well. 54# Implement embedded-hal-async traits if `nightly` is set as well.
@@ -58,7 +58,7 @@ unstable-traits = ["embedded-hal-1", "embedded-hal-nb"]
58embassy-sync = { version = "0.2.0", path = "../embassy-sync" } 58embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
59embassy-time = { version = "0.1.2", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } 59embassy-time = { version = "0.1.2", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] }
60embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 60embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
61embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-2"] } 61embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] }
62embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 62embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
63embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } 63embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true }
64atomic-polyfill = "1.0.1" 64atomic-polyfill = "1.0.1"
@@ -73,6 +73,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
73chrono = { version = "0.4", default-features = false, optional = true } 73chrono = { version = "0.4", default-features = false, optional = true }
74embedded-io = { version = "0.4.0", features = ["async"], optional = true } 74embedded-io = { version = "0.4.0", features = ["async"], optional = true }
75embedded-storage = { version = "0.3" } 75embedded-storage = { version = "0.3" }
76embedded-storage-async = { version = "0.4.0", optional = true }
76rand_core = "0.6.4" 77rand_core = "0.6.4"
77fixed = "1.23.1" 78fixed = "1.23.1"
78 79
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs
index 95780c068..4fba31169 100644
--- a/embassy-rp/src/adc.rs
+++ b/embassy-rp/src/adc.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
3use core::sync::atomic::{compiler_fence, Ordering}; 3use core::sync::atomic::{compiler_fence, Ordering};
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use embassy_hal_internal::{into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8 8
9use crate::gpio::sealed::Pin as GpioPin; 9use crate::gpio::sealed::Pin as GpioPin;
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index acb21dce5..976d06de7 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -1,7 +1,7 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; 2use core::sync::atomic::{AtomicU16, AtomicU32, Ordering};
3 3
4use embassy_hal_common::{into_ref, PeripheralRef}; 4use embassy_hal_internal::{into_ref, PeripheralRef};
5use pac::clocks::vals::*; 5use pac::clocks::vals::*;
6 6
7use crate::gpio::sealed::Pin; 7use crate::gpio::sealed::Pin;
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 1a458778c..c8f741804 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -4,7 +4,7 @@ use core::pin::Pin;
4use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::{Context, Poll}; 5use core::task::{Context, Poll};
6 6
7use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; 7use embassy_hal_internal::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use pac::dma::vals::DataSize; 9use pac::dma::vals::DataSize;
10 10
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
index 96d2d4541..70d867319 100644
--- a/embassy-rp/src/flash.rs
+++ b/embassy-rp/src/flash.rs
@@ -1,11 +1,15 @@
1use core::future::Future;
1use core::marker::PhantomData; 2use core::marker::PhantomData;
3use core::pin::Pin;
4use core::task::{Context, Poll};
2 5
3use embassy_hal_common::Peripheral; 6use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
4use embedded_storage::nor_flash::{ 7use embedded_storage::nor_flash::{
5 check_erase, check_read, check_write, ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, 8 check_erase, check_read, check_write, ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind,
6 ReadNorFlash, 9 ReadNorFlash,
7}; 10};
8 11
12use crate::dma::{AnyChannel, Channel, Transfer};
9use crate::pac; 13use crate::pac;
10use crate::peripherals::FLASH; 14use crate::peripherals::FLASH;
11 15
@@ -24,6 +28,7 @@ pub const PAGE_SIZE: usize = 256;
24pub const WRITE_SIZE: usize = 1; 28pub const WRITE_SIZE: usize = 1;
25pub const READ_SIZE: usize = 1; 29pub const READ_SIZE: usize = 1;
26pub const ERASE_SIZE: usize = 4096; 30pub const ERASE_SIZE: usize = 4096;
31pub const ASYNC_READ_SIZE: usize = 4;
27 32
28/// Error type for NVMC operations. 33/// Error type for NVMC operations.
29#[derive(Debug, Copy, Clone, PartialEq, Eq)] 34#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -57,13 +62,46 @@ impl NorFlashError for Error {
57 } 62 }
58} 63}
59 64
60pub struct Flash<'d, T: Instance, const FLASH_SIZE: usize>(PhantomData<&'d mut T>); 65/// Future that waits for completion of a background read
66#[must_use = "futures do nothing unless you `.await` or poll them"]
67pub struct BackgroundRead<'a, 'd, T: Instance, const FLASH_SIZE: usize> {
68 flash: PhantomData<&'a mut Flash<'d, T, Async, FLASH_SIZE>>,
69 transfer: Transfer<'a, AnyChannel>,
70}
61 71
62impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { 72impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Future for BackgroundRead<'a, 'd, T, FLASH_SIZE> {
63 pub fn new(_flash: impl Peripheral<P = T> + 'd) -> Self { 73 type Output = ();
64 Self(PhantomData) 74 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
75 Pin::new(&mut self.transfer).poll(cx)
65 } 76 }
77}
66 78
79impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Drop for BackgroundRead<'a, 'd, T, FLASH_SIZE> {
80 fn drop(&mut self) {
81 if pac::XIP_CTRL.stream_ctr().read().0 == 0 {
82 return;
83 }
84 pac::XIP_CTRL
85 .stream_ctr()
86 .write_value(pac::xip_ctrl::regs::StreamCtr(0));
87 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
88 // Errata RP2040-E8: Perform an uncached read to make sure there's not a transfer in
89 // flight that might effect an address written to start a new transfer. This stalls
90 // until after any transfer is complete, so the address will not change anymore.
91 const XIP_NOCACHE_NOALLOC_BASE: *const u32 = 0x13000000 as *const _;
92 unsafe {
93 core::ptr::read_volatile(XIP_NOCACHE_NOALLOC_BASE);
94 }
95 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
96 }
97}
98
99pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> {
100 dma: Option<PeripheralRef<'d, AnyChannel>>,
101 phantom: PhantomData<(&'d mut T, M)>,
102}
103
104impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> {
67 pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 105 pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
68 trace!( 106 trace!(
69 "Reading from 0x{:x} to 0x{:x}", 107 "Reading from 0x{:x} to 0x{:x}",
@@ -182,6 +220,8 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> {
182 let ch = crate::pac::DMA.ch(n); 220 let ch = crate::pac::DMA.ch(n);
183 while ch.read_addr().read() < SRAM_LOWER && ch.ctrl_trig().read().busy() {} 221 while ch.read_addr().read() < SRAM_LOWER && ch.ctrl_trig().read().busy() {}
184 } 222 }
223 // Wait for completion of any background reads
224 while pac::XIP_CTRL.stream_ctr().read().0 > 0 {}
185 225
186 // Run our flash operation in RAM 226 // Run our flash operation in RAM
187 operation(); 227 operation();
@@ -210,11 +250,73 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> {
210 } 250 }
211} 251}
212 252
213impl<'d, T: Instance, const FLASH_SIZE: usize> ErrorType for Flash<'d, T, FLASH_SIZE> { 253impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> {
254 pub fn new(_flash: impl Peripheral<P = T> + 'd) -> Self {
255 Self {
256 dma: None,
257 phantom: PhantomData,
258 }
259 }
260}
261
262impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
263 pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self {
264 into_ref!(dma);
265 Self {
266 dma: Some(dma.map_into()),
267 phantom: PhantomData,
268 }
269 }
270
271 pub fn background_read<'a>(
272 &'a mut self,
273 offset: u32,
274 data: &'a mut [u32],
275 ) -> Result<BackgroundRead<'a, 'd, T, FLASH_SIZE>, Error> {
276 trace!(
277 "Reading in background from 0x{:x} to 0x{:x}",
278 FLASH_BASE as u32 + offset,
279 FLASH_BASE as u32 + offset + (data.len() * 4) as u32
280 );
281 // Can't use check_read because we need to enforce 4-byte alignment
282 let offset = offset as usize;
283 let length = data.len() * 4;
284 if length > self.capacity() || offset > self.capacity() - length {
285 return Err(Error::OutOfBounds);
286 }
287 if offset % 4 != 0 {
288 return Err(Error::Unaligned);
289 }
290
291 while !pac::XIP_CTRL.stat().read().fifo_empty() {
292 pac::XIP_CTRL.stream_fifo().read();
293 }
294
295 pac::XIP_CTRL
296 .stream_addr()
297 .write_value(pac::xip_ctrl::regs::StreamAddr(FLASH_BASE as u32 + offset as u32));
298 pac::XIP_CTRL
299 .stream_ctr()
300 .write_value(pac::xip_ctrl::regs::StreamCtr(data.len() as u32));
301
302 // Use the XIP AUX bus port, rather than the FIFO register access (e.x.
303 // pac::XIP_CTRL.stream_fifo().as_ptr()) to avoid DMA stalling on
304 // general XIP access.
305 const XIP_AUX_BASE: *const u32 = 0x50400000 as *const _;
306 let transfer = unsafe { crate::dma::read(self.dma.as_mut().unwrap(), XIP_AUX_BASE, data, 37) };
307
308 Ok(BackgroundRead {
309 flash: PhantomData,
310 transfer,
311 })
312 }
313}
314
315impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> ErrorType for Flash<'d, T, M, FLASH_SIZE> {
214 type Error = Error; 316 type Error = Error;
215} 317}
216 318
217impl<'d, T: Instance, const FLASH_SIZE: usize> ReadNorFlash for Flash<'d, T, FLASH_SIZE> { 319impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> ReadNorFlash for Flash<'d, T, M, FLASH_SIZE> {
218 const READ_SIZE: usize = READ_SIZE; 320 const READ_SIZE: usize = READ_SIZE;
219 321
220 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 322 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
@@ -226,9 +328,9 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> ReadNorFlash for Flash<'d, T, FLA
226 } 328 }
227} 329}
228 330
229impl<'d, T: Instance, const FLASH_SIZE: usize> MultiwriteNorFlash for Flash<'d, T, FLASH_SIZE> {} 331impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> MultiwriteNorFlash for Flash<'d, T, M, FLASH_SIZE> {}
230 332
231impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Flash<'d, T, FLASH_SIZE> { 333impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> NorFlash for Flash<'d, T, M, FLASH_SIZE> {
232 const WRITE_SIZE: usize = WRITE_SIZE; 334 const WRITE_SIZE: usize = WRITE_SIZE;
233 335
234 const ERASE_SIZE: usize = ERASE_SIZE; 336 const ERASE_SIZE: usize = ERASE_SIZE;
@@ -242,6 +344,74 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Flash<'d, T, FLASH_S
242 } 344 }
243} 345}
244 346
347#[cfg(feature = "nightly")]
348impl<'d, T: Instance, const FLASH_SIZE: usize> embedded_storage_async::nor_flash::ReadNorFlash
349 for Flash<'d, T, Async, FLASH_SIZE>
350{
351 const READ_SIZE: usize = ASYNC_READ_SIZE;
352
353 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
354 use core::mem::MaybeUninit;
355
356 // Checked early to simplify address validity checks
357 if bytes.len() % 4 != 0 {
358 return Err(Error::Unaligned);
359 }
360
361 // If the destination address is already aligned, then we can just DMA directly
362 if (bytes.as_ptr() as u32) % 4 == 0 {
363 // Safety: alignment and size have been checked for compatibility
364 let mut buf: &mut [u32] =
365 unsafe { core::slice::from_raw_parts_mut(bytes.as_mut_ptr() as *mut u32, bytes.len() / 4) };
366 self.background_read(offset, &mut buf)?.await;
367 return Ok(());
368 }
369
370 // Destination address is unaligned, so use an intermediate buffer
371 const REALIGN_CHUNK: usize = PAGE_SIZE;
372 // Safety: MaybeUninit requires no initialization
373 let mut buf: [MaybeUninit<u32>; REALIGN_CHUNK / 4] = unsafe { MaybeUninit::uninit().assume_init() };
374 let mut chunk_offset: usize = 0;
375 while chunk_offset < bytes.len() {
376 let chunk_size = (bytes.len() - chunk_offset).min(REALIGN_CHUNK);
377 let buf = &mut buf[..(chunk_size / 4)];
378
379 // Safety: this is written to completely by DMA before any reads
380 let buf = unsafe { &mut *(buf as *mut [MaybeUninit<u32>] as *mut [u32]) };
381 self.background_read(offset + chunk_offset as u32, buf)?.await;
382
383 // Safety: [u8] has more relaxed alignment and size requirements than [u32], so this is just aliasing
384 let buf = unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const _, buf.len() * 4) };
385 bytes[chunk_offset..(chunk_offset + chunk_size)].copy_from_slice(&buf[..chunk_size]);
386
387 chunk_offset += chunk_size;
388 }
389
390 Ok(())
391 }
392
393 fn capacity(&self) -> usize {
394 self.capacity()
395 }
396}
397
398#[cfg(feature = "nightly")]
399impl<'d, T: Instance, const FLASH_SIZE: usize> embedded_storage_async::nor_flash::NorFlash
400 for Flash<'d, T, Async, FLASH_SIZE>
401{
402 const WRITE_SIZE: usize = WRITE_SIZE;
403
404 const ERASE_SIZE: usize = ERASE_SIZE;
405
406 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
407 self.erase(from, to)
408 }
409
410 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
411 self.write(offset, bytes)
412 }
413}
414
245#[allow(dead_code)] 415#[allow(dead_code)]
246mod ram_helpers { 416mod ram_helpers {
247 use core::marker::PhantomData; 417 use core::marker::PhantomData;
@@ -699,9 +869,24 @@ mod ram_helpers {
699 869
700mod sealed { 870mod sealed {
701 pub trait Instance {} 871 pub trait Instance {}
872 pub trait Mode {}
702} 873}
703 874
704pub trait Instance: sealed::Instance {} 875pub trait Instance: sealed::Instance {}
876pub trait Mode: sealed::Mode {}
705 877
706impl sealed::Instance for FLASH {} 878impl sealed::Instance for FLASH {}
707impl Instance for FLASH {} 879impl Instance for FLASH {}
880
881macro_rules! impl_mode {
882 ($name:ident) => {
883 impl sealed::Mode for $name {}
884 impl Mode for $name {}
885 };
886}
887
888pub struct Blocking;
889pub struct Async;
890
891impl_mode!(Blocking);
892impl_mode!(Async);
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index a3d330cdc..2807eb678 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -3,7 +3,7 @@ use core::future::Future;
3use core::pin::Pin as FuturePin; 3use core::pin::Pin as FuturePin;
4use core::task::{Context, Poll}; 4use core::task::{Context, Poll};
5 5
6use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 6use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8 8
9use crate::interrupt::InterruptExt; 9use crate::interrupt::InterruptExt;
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index 9b85b2345..536ad747d 100644
--- a/embassy-rp/src/i2c.rs
+++ b/embassy-rp/src/i2c.rs
@@ -2,7 +2,7 @@ use core::future;
2use core::marker::PhantomData; 2use core::marker::PhantomData;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use embassy_sync::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
7use pac::i2c; 7use pac::i2c;
8 8
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 4f205a16e..45156458d 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -33,10 +33,10 @@ pub mod watchdog;
33// TODO: move `pio_instr_util` and `relocate` to inside `pio` 33// TODO: move `pio_instr_util` and `relocate` to inside `pio`
34pub mod pio; 34pub mod pio;
35pub mod pio_instr_util; 35pub mod pio_instr_util;
36pub mod relocate; 36pub(crate) mod relocate;
37 37
38// Reexports 38// Reexports
39pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 39pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
40#[cfg(feature = "unstable-pac")] 40#[cfg(feature = "unstable-pac")]
41pub use rp_pac as pac; 41pub use rp_pac as pac;
42#[cfg(not(feature = "unstable-pac"))] 42#[cfg(not(feature = "unstable-pac"))]
@@ -45,7 +45,7 @@ pub(crate) use rp_pac as pac;
45#[cfg(feature = "rt")] 45#[cfg(feature = "rt")]
46pub use crate::pac::NVIC_PRIO_BITS; 46pub use crate::pac::NVIC_PRIO_BITS;
47 47
48embassy_hal_common::interrupt_mod!( 48embassy_hal_internal::interrupt_mod!(
49 TIMER_IRQ_0, 49 TIMER_IRQ_0,
50 TIMER_IRQ_1, 50 TIMER_IRQ_1,
51 TIMER_IRQ_2, 51 TIMER_IRQ_2,
@@ -85,7 +85,7 @@ embassy_hal_common::interrupt_mod!(
85/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) 85/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
86/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to 86/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
87/// prove at compile-time that the right interrupts have been bound. 87/// prove at compile-time that the right interrupts have been bound.
88// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. 88// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
89#[macro_export] 89#[macro_export]
90macro_rules! bind_interrupts { 90macro_rules! bind_interrupts {
91 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { 91 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
@@ -107,7 +107,7 @@ macro_rules! bind_interrupts {
107 }; 107 };
108} 108}
109 109
110embassy_hal_common::peripherals! { 110embassy_hal_internal::peripherals! {
111 PIN_0, 111 PIN_0,
112 PIN_1, 112 PIN_1,
113 PIN_2, 113 PIN_2,
@@ -219,6 +219,74 @@ select_bootloader! {
219 default => BOOT_LOADER_W25Q080 219 default => BOOT_LOADER_W25Q080
220} 220}
221 221
222/// Installs a stack guard for the CORE0 stack in MPU region 0.
223/// Will fail if the MPU is already confgigured. This function requires
224/// a `_stack_end` symbol to be defined by the linker script, and expexcts
225/// `_stack_end` to be located at the lowest address (largest depth) of
226/// the stack.
227///
228/// This method can *only* set up stack guards on the currently
229/// executing core. Stack guards for CORE1 are set up automatically,
230/// only CORE0 should ever use this.
231///
232/// # Usage
233///
234/// ```no_run
235/// #![feature(type_alias_impl_trait)]
236/// use embassy_rp::install_core0_stack_guard;
237/// use embassy_executor::{Executor, Spawner};
238///
239/// #[embassy_executor::main]
240/// async fn main(_spawner: Spawner) {
241/// // set up by the linker as follows:
242/// //
243/// // MEMORY {
244/// // STACK0: ORIGIN = 0x20040000, LENGTH = 4K
245/// // }
246/// //
247/// // _stack_end = ORIGIN(STACK0);
248/// // _stack_start = _stack_end + LENGTH(STACK0);
249/// //
250/// install_core0_stack_guard().expect("MPU already configured");
251/// let p = embassy_rp::init(Default::default());
252///
253/// // ...
254/// }
255/// ```
256pub fn install_core0_stack_guard() -> Result<(), ()> {
257 extern "C" {
258 static mut _stack_end: usize;
259 }
260 unsafe { install_stack_guard(&mut _stack_end as *mut usize) }
261}
262
263#[inline(always)]
264fn install_stack_guard(stack_bottom: *mut usize) -> Result<(), ()> {
265 let core = unsafe { cortex_m::Peripherals::steal() };
266
267 // Fail if MPU is already configured
268 if core.MPU.ctrl.read() != 0 {
269 return Err(());
270 }
271
272 // The minimum we can protect is 32 bytes on a 32 byte boundary, so round up which will
273 // just shorten the valid stack range a tad.
274 let addr = (stack_bottom as u32 + 31) & !31;
275 // Mask is 1 bit per 32 bytes of the 256 byte range... clear the bit for the segment we want
276 let subregion_select = 0xff ^ (1 << ((addr >> 5) & 7));
277 unsafe {
278 core.MPU.ctrl.write(5); // enable mpu with background default map
279 core.MPU.rbar.write((addr & !0xff) | (1 << 4)); // set address and update RNR
280 core.MPU.rasr.write(
281 1 // enable region
282 | (0x7 << 1) // size 2^(7 + 1) = 256
283 | (subregion_select << 8)
284 | 0x10000000, // XN = disable instruction fetch; no other bits means no permissions
285 );
286 }
287 Ok(())
288}
289
222pub mod config { 290pub mod config {
223 use crate::clocks::ClockConfig; 291 use crate::clocks::ClockConfig;
224 292
diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs
index 468e8470a..915761801 100644
--- a/embassy-rp/src/multicore.rs
+++ b/embassy-rp/src/multicore.rs
@@ -52,41 +52,20 @@ use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
52 52
53use crate::interrupt::InterruptExt; 53use crate::interrupt::InterruptExt;
54use crate::peripherals::CORE1; 54use crate::peripherals::CORE1;
55use crate::{gpio, interrupt, pac}; 55use crate::{gpio, install_stack_guard, interrupt, pac};
56 56
57const PAUSE_TOKEN: u32 = 0xDEADBEEF; 57const PAUSE_TOKEN: u32 = 0xDEADBEEF;
58const RESUME_TOKEN: u32 = !0xDEADBEEF; 58const RESUME_TOKEN: u32 = !0xDEADBEEF;
59static IS_CORE1_INIT: AtomicBool = AtomicBool::new(false); 59static IS_CORE1_INIT: AtomicBool = AtomicBool::new(false);
60 60
61#[inline(always)] 61#[inline(always)]
62fn install_stack_guard(stack_bottom: *mut usize) { 62fn core1_setup(stack_bottom: *mut usize) {
63 let core = unsafe { cortex_m::Peripherals::steal() }; 63 if let Err(_) = install_stack_guard(stack_bottom) {
64 64 // currently only happens if the MPU was already set up, which
65 // Trap if MPU is already configured 65 // would indicate that the core is already in use from outside
66 if core.MPU.ctrl.read() != 0 { 66 // embassy, somehow. trap if so since we can't deal with that.
67 cortex_m::asm::udf(); 67 cortex_m::asm::udf();
68 } 68 }
69
70 // The minimum we can protect is 32 bytes on a 32 byte boundary, so round up which will
71 // just shorten the valid stack range a tad.
72 let addr = (stack_bottom as u32 + 31) & !31;
73 // Mask is 1 bit per 32 bytes of the 256 byte range... clear the bit for the segment we want
74 let subregion_select = 0xff ^ (1 << ((addr >> 5) & 7));
75 unsafe {
76 core.MPU.ctrl.write(5); // enable mpu with background default map
77 core.MPU.rbar.write((addr & !0xff) | 0x8);
78 core.MPU.rasr.write(
79 1 // enable region
80 | (0x7 << 1) // size 2^(7 + 1) = 256
81 | (subregion_select << 8)
82 | 0x10000000, // XN = disable instruction fetch; no other bits means no permissions
83 );
84 }
85}
86
87#[inline(always)]
88fn core1_setup(stack_bottom: *mut usize) {
89 install_stack_guard(stack_bottom);
90 unsafe { 69 unsafe {
91 gpio::init(); 70 gpio::init();
92 } 71 }
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 72a2f44ed..3de398af7 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -5,13 +5,13 @@ use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::{Context, Poll}; 5use core::task::{Context, Poll};
6 6
7use atomic_polyfill::{AtomicU32, AtomicU8}; 7use atomic_polyfill::{AtomicU32, AtomicU8};
8use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 8use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10use fixed::types::extra::U8; 10use fixed::types::extra::U8;
11use fixed::FixedU32; 11use fixed::FixedU32;
12use pac::io::vals::Gpio0ctrlFuncsel; 12use pac::io::vals::Gpio0ctrlFuncsel;
13use pac::pio::vals::SmExecctrlStatusSel; 13use pac::pio::vals::SmExecctrlStatusSel;
14use pio::{SideSet, Wrap}; 14use pio::{Program, SideSet, Wrap};
15 15
16use crate::dma::{Channel, Transfer, Word}; 16use crate::dma::{Channel, Transfer, Word};
17use crate::gpio::sealed::Pin as SealedPin; 17use crate::gpio::sealed::Pin as SealedPin;
@@ -734,23 +734,67 @@ pub struct InstanceMemory<'d, PIO: Instance> {
734 734
735pub struct LoadedProgram<'d, PIO: Instance> { 735pub struct LoadedProgram<'d, PIO: Instance> {
736 pub used_memory: InstanceMemory<'d, PIO>, 736 pub used_memory: InstanceMemory<'d, PIO>,
737 origin: u8, 737 pub origin: u8,
738 wrap: Wrap, 738 pub wrap: Wrap,
739 side_set: SideSet, 739 pub side_set: SideSet,
740}
741
742#[derive(Clone, Copy, PartialEq, Eq, Debug)]
743#[cfg_attr(feature = "defmt", derive(defmt::Format))]
744pub enum LoadError {
745 /// Insufficient consecutive free instruction space to load program.
746 InsufficientSpace,
747 /// Loading the program would overwrite an instruction address already
748 /// used by another program.
749 AddressInUse(usize),
740} 750}
741 751
742impl<'d, PIO: Instance> Common<'d, PIO> { 752impl<'d, PIO: Instance> Common<'d, PIO> {
743 pub fn load_program<const SIZE: usize>(&mut self, prog: &RelocatedProgram<SIZE>) -> LoadedProgram<'d, PIO> { 753 /// Load a PIO program. This will automatically relocate the program to
754 /// an available chunk of free instruction memory if the program origin
755 /// was not explicitly specified, otherwise it will attempt to load the
756 /// program only at its origin.
757 pub fn load_program<const SIZE: usize>(&mut self, prog: &Program<SIZE>) -> LoadedProgram<'d, PIO> {
744 match self.try_load_program(prog) { 758 match self.try_load_program(prog) {
745 Ok(r) => r, 759 Ok(r) => r,
746 Err(at) => panic!("Trying to write already used PIO instruction memory at {}", at), 760 Err(e) => panic!("Failed to load PIO program: {:?}", e),
747 } 761 }
748 } 762 }
749 763
764 /// Load a PIO program. This will automatically relocate the program to
765 /// an available chunk of free instruction memory if the program origin
766 /// was not explicitly specified, otherwise it will attempt to load the
767 /// program only at its origin.
750 pub fn try_load_program<const SIZE: usize>( 768 pub fn try_load_program<const SIZE: usize>(
751 &mut self, 769 &mut self,
752 prog: &RelocatedProgram<SIZE>, 770 prog: &Program<SIZE>,
771 ) -> Result<LoadedProgram<'d, PIO>, LoadError> {
772 match prog.origin {
773 Some(origin) => self
774 .try_load_program_at(prog, origin)
775 .map_err(|a| LoadError::AddressInUse(a)),
776 None => {
777 // naively search for free space, allowing wraparound since
778 // PIO does support that. with only 32 instruction slots it
779 // doesn't make much sense to do anything more fancy.
780 let mut origin = 0;
781 while origin < 32 {
782 match self.try_load_program_at(prog, origin as _) {
783 Ok(r) => return Ok(r),
784 Err(a) => origin = a + 1,
785 }
786 }
787 Err(LoadError::InsufficientSpace)
788 }
789 }
790 }
791
792 fn try_load_program_at<const SIZE: usize>(
793 &mut self,
794 prog: &Program<SIZE>,
795 origin: u8,
753 ) -> Result<LoadedProgram<'d, PIO>, usize> { 796 ) -> Result<LoadedProgram<'d, PIO>, usize> {
797 let prog = RelocatedProgram::new_with_origin(prog, origin);
754 let used_memory = self.try_write_instr(prog.origin() as _, prog.code())?; 798 let used_memory = self.try_write_instr(prog.origin() as _, prog.code())?;
755 Ok(LoadedProgram { 799 Ok(LoadedProgram {
756 used_memory, 800 used_memory,
@@ -760,7 +804,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
760 }) 804 })
761 } 805 }
762 806
763 pub fn try_write_instr<I>(&mut self, start: usize, instrs: I) -> Result<InstanceMemory<'d, PIO>, usize> 807 fn try_write_instr<I>(&mut self, start: usize, instrs: I) -> Result<InstanceMemory<'d, PIO>, usize>
764 where 808 where
765 I: Iterator<Item = u16>, 809 I: Iterator<Item = u16>,
766 { 810 {
diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs
index 20bb88446..c0ddb2a90 100644
--- a/embassy-rp/src/pwm.rs
+++ b/embassy-rp/src/pwm.rs
@@ -1,6 +1,6 @@
1//! Pulse Width Modulation (PWM) 1//! Pulse Width Modulation (PWM)
2 2
3use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 3use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
4use fixed::traits::ToFixed; 4use fixed::traits::ToFixed;
5use fixed::FixedU16; 5use fixed::FixedU16;
6use pac::pwm::regs::{ChDiv, Intr}; 6use pac::pwm::regs::{ChDiv, Intr};
diff --git a/embassy-rp/src/relocate.rs b/embassy-rp/src/relocate.rs
index 9cb279ccd..b35b4ed72 100644
--- a/embassy-rp/src/relocate.rs
+++ b/embassy-rp/src/relocate.rs
@@ -41,11 +41,6 @@ pub struct RelocatedProgram<'a, const PROGRAM_SIZE: usize> {
41} 41}
42 42
43impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> { 43impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> {
44 pub fn new(program: &Program<PROGRAM_SIZE>) -> RelocatedProgram<PROGRAM_SIZE> {
45 let origin = program.origin.unwrap_or(0);
46 RelocatedProgram { program, origin }
47 }
48
49 pub fn new_with_origin(program: &Program<PROGRAM_SIZE>, origin: u8) -> RelocatedProgram<PROGRAM_SIZE> { 44 pub fn new_with_origin(program: &Program<PROGRAM_SIZE>, origin: u8) -> RelocatedProgram<PROGRAM_SIZE> {
50 RelocatedProgram { program, origin } 45 RelocatedProgram { program, origin }
51 } 46 }
diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs
index 1b33fdf8d..60ca8627b 100644
--- a/embassy-rp/src/rtc/mod.rs
+++ b/embassy-rp/src/rtc/mod.rs
@@ -1,6 +1,6 @@
1mod filter; 1mod filter;
2 2
3use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 3use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
4 4
5pub use self::filter::DateTimeFilter; 5pub use self::filter::DateTimeFilter;
6 6
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index af101cf4a..544b542e8 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
3 3
4use embassy_embedded_hal::SetConfig; 4use embassy_embedded_hal::SetConfig;
5use embassy_futures::join::join; 5use embassy_futures::join::join;
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use embassy_hal_internal::{into_ref, PeripheralRef};
7pub use embedded_hal_02::spi::{Phase, Polarity}; 7pub use embedded_hal_02::spi::{Phase, Polarity};
8 8
9use crate::dma::{AnyChannel, Channel}; 9use crate::dma::{AnyChannel, Channel};
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index 30eeb5476..9d96db12c 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -3,7 +3,7 @@ use core::slice;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use atomic_polyfill::{AtomicU8, Ordering}; 5use atomic_polyfill::{AtomicU8, Ordering};
6use embassy_hal_common::atomic_ring_buffer::RingBuffer; 6use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use embassy_time::{Duration, Timer}; 8use embassy_time::{Duration, Timer};
9 9
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 7b94bce5e..69c6ac2f1 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -4,7 +4,7 @@ use core::task::Poll;
4 4
5use atomic_polyfill::{AtomicU16, Ordering}; 5use atomic_polyfill::{AtomicU16, Ordering};
6use embassy_futures::select::{select, Either}; 6use embassy_futures::select::{select, Either};
7use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
10use pac::uart::regs::Uartris; 10use pac::uart::regs::Uartris;
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml
index 6cd122200..96c474845 100644
--- a/embassy-stm32-wpan/Cargo.toml
+++ b/embassy-stm32-wpan/Cargo.toml
@@ -15,7 +15,7 @@ embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" }
15embassy-sync = { version = "0.2.0", path = "../embassy-sync" } 15embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
16embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } 16embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true }
17embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
18embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } 18embassy-hal-internal = { version = "0.1.0", path = "../embassy-hal-internal" }
19embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } 19embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" }
20embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true } 20embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true }
21 21
@@ -26,12 +26,12 @@ aligned = "0.4.1"
26 26
27bit_field = "0.10.2" 27bit_field = "0.10.2"
28stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } 28stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
29stm32wb-hci = { version = "0.1.3", optional = true } 29stm32wb-hci = { version = "0.1.4", optional = true }
30futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 30futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
31bitflags = { version = "2.3.3", optional = true } 31bitflags = { version = "2.3.3", optional = true }
32 32
33[features] 33[features]
34defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] 34defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "stm32wb-hci?/defmt"]
35 35
36ble = ["dep:stm32wb-hci"] 36ble = ["dep:stm32wb-hci"]
37mac = ["dep:bitflags", "dep:embassy-net-driver" ] 37mac = ["dep:bitflags", "dep:embassy-net-driver" ]
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs
index 6836d7a8b..5ecce2cc2 100644
--- a/embassy-stm32-wpan/src/lib.rs
+++ b/embassy-stm32-wpan/src/lib.rs
@@ -8,7 +8,7 @@ pub mod fmt;
8use core::mem::MaybeUninit; 8use core::mem::MaybeUninit;
9use core::sync::atomic::{compiler_fence, Ordering}; 9use core::sync::atomic::{compiler_fence, Ordering};
10 10
11use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 11use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
12use embassy_stm32::interrupt; 12use embassy_stm32::interrupt;
13use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler}; 13use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler};
14use embassy_stm32::peripherals::IPCC; 14use embassy_stm32::peripherals::IPCC;
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index cb0644338..8c7dd38c2 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -34,7 +34,7 @@ flavors = [
34embassy-sync = { version = "0.2.0", path = "../embassy-sync" } 34embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
35embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } 35embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true }
36embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 36embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
37embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-4"] } 37embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] }
38embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 38embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
39embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } 39embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }
40embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } 40embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true }
@@ -57,7 +57,7 @@ sdio-host = "0.5.0"
57embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 57embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
58critical-section = "1.1" 58critical-section = "1.1"
59atomic-polyfill = "1.0.1" 59atomic-polyfill = "1.0.1"
60stm32-metapac = "13" 60stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1f8ab493e029fc601edebc6bac105a63cc9858fe" }
61vcell = "0.1.3" 61vcell = "0.1.3"
62bxcan = "0.7.0" 62bxcan = "0.7.0"
63nb = "1.0.0" 63nb = "1.0.0"
@@ -67,6 +67,7 @@ cfg-if = "1.0.0"
67embedded-io = { version = "0.4.0", features = ["async"], optional = true } 67embedded-io = { version = "0.4.0", features = ["async"], optional = true }
68chrono = { version = "^0.4", default-features = false, optional = true} 68chrono = { version = "^0.4", default-features = false, optional = true}
69bit_field = "0.10.2" 69bit_field = "0.10.2"
70document-features = "0.2.7"
70 71
71[dev-dependencies] 72[dev-dependencies]
72critical-section = { version = "1.1", features = ["std"] } 73critical-section = { version = "1.1", features = ["std"] }
@@ -74,44 +75,67 @@ critical-section = { version = "1.1", features = ["std"] }
74[build-dependencies] 75[build-dependencies]
75proc-macro2 = "1.0.36" 76proc-macro2 = "1.0.36"
76quote = "1.0.15" 77quote = "1.0.15"
77stm32-metapac = { version = "13", default-features = false, features = ["metadata"]} 78stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1f8ab493e029fc601edebc6bac105a63cc9858fe", default-features = false, features = ["metadata"]}
78 79
79[features] 80[features]
80default = ["rt"] 81default = ["rt"]
82
83## Enable `stm32-metapac`'s `rt` feature
81rt = ["stm32-metapac/rt"] 84rt = ["stm32-metapac/rt"]
82 85
83defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] 86## Use [`defmt`](https://docs.rs/defmt/latest/defmt/) for logging
84memory-x = ["stm32-metapac/memory-x"] 87defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"]
88
85exti = [] 89exti = []
86 90
87# Enables additional driver features that depend on embassy-time 91## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/)
92memory-x = ["stm32-metapac/memory-x"]
93
94## Enable nightly-only features
95nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"]
96
97## Re-export stm32-metapac at `embassy_stm32::pac`.
98## This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version.
99## If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC.
100## There are no plans to make this stable.
101unstable-pac = []
102
103## Implement embedded-hal 1.0 alpha traits.
104## Implement embedded-hal-async traits if `nightly` is set as well.
105unstable-traits = ["embedded-hal-1", "dep:embedded-hal-nb"]
106
107#! ## Time
108
109## Enables additional driver features that depend on embassy-time
88time = ["dep:embassy-time"] 110time = ["dep:embassy-time"]
89 111
90# Features starting with `_` are for internal use only. They're not intended 112# Features starting with `_` are for internal use only. They're not intended
91# to be enabled by other crates, and are not covered by semver guarantees. 113# to be enabled by other crates, and are not covered by semver guarantees.
92_time-driver = ["time"] 114_time-driver = ["time"]
115
116## Use any time driver
93time-driver-any = ["_time-driver"] 117time-driver-any = ["_time-driver"]
118## Use TIM2 as time driver
94time-driver-tim2 = ["_time-driver"] 119time-driver-tim2 = ["_time-driver"]
120## Use TIM3 as time driver
95time-driver-tim3 = ["_time-driver"] 121time-driver-tim3 = ["_time-driver"]
122## Use TIM4 as time driver
96time-driver-tim4 = ["_time-driver"] 123time-driver-tim4 = ["_time-driver"]
124## Use TIM5 as time driver
97time-driver-tim5 = ["_time-driver"] 125time-driver-tim5 = ["_time-driver"]
126## Use TIM12 as time driver
98time-driver-tim12 = ["_time-driver"] 127time-driver-tim12 = ["_time-driver"]
128## Use TIM15 as time driver
99time-driver-tim15 = ["_time-driver"] 129time-driver-tim15 = ["_time-driver"]
100 130
101# Enable nightly-only features
102nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"]
103
104# Reexport stm32-metapac at `embassy_stm32::pac`.
105# This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version.
106# If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC.
107# There are no plans to make this stable.
108unstable-pac = []
109 131
110# Implement embedded-hal 1.0 alpha traits. 132#! ## Chip-selection features
111# Implement embedded-hal-async traits if `nightly` is set as well. 133#! Select your chip by specifying the model as a feature, e.g. `stm32c011d6`.
112unstable-traits = ["embedded-hal-1", "dep:embedded-hal-nb"] 134#! Check the `Cargo.toml` for the latest list of supported chips.
135#!
136#! **Important:** Do not forget to adapt the target chip in your toolchain,
137#! e.g. in `.cargo/config.toml`.
113 138
114# Chip-selection features
115stm32c011d6 = [ "stm32-metapac/stm32c011d6" ] 139stm32c011d6 = [ "stm32-metapac/stm32c011d6" ]
116stm32c011f4 = [ "stm32-metapac/stm32c011f4" ] 140stm32c011f4 = [ "stm32-metapac/stm32c011f4" ]
117stm32c011f6 = [ "stm32-metapac/stm32c011f6" ] 141stm32c011f6 = [ "stm32-metapac/stm32c011f6" ]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 995ad1443..9b3caefd5 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -138,7 +138,7 @@ fn main() {
138 let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect(); 138 let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect();
139 139
140 g.extend(quote! { 140 g.extend(quote! {
141 embassy_hal_common::peripherals_definition!(#(#singleton_tokens),*); 141 embassy_hal_internal::peripherals_definition!(#(#singleton_tokens),*);
142 }); 142 });
143 143
144 let singleton_tokens: Vec<_> = singletons 144 let singleton_tokens: Vec<_> = singletons
@@ -148,7 +148,7 @@ fn main() {
148 .collect(); 148 .collect();
149 149
150 g.extend(quote! { 150 g.extend(quote! {
151 embassy_hal_common::peripherals_struct!(#(#singleton_tokens),*); 151 embassy_hal_internal::peripherals_struct!(#(#singleton_tokens),*);
152 }); 152 });
153 153
154 // ======== 154 // ========
@@ -160,7 +160,7 @@ fn main() {
160 } 160 }
161 161
162 g.extend(quote! { 162 g.extend(quote! {
163 embassy_hal_common::interrupt_mod!( 163 embassy_hal_internal::interrupt_mod!(
164 #( 164 #(
165 #irqs, 165 #irqs,
166 )* 166 )*
@@ -211,7 +211,7 @@ fn main() {
211 let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); 211 let region_type = format_ident!("{}", get_flash_region_type_name(region.name));
212 flash_regions.extend(quote! { 212 flash_regions.extend(quote! {
213 #[cfg(flash)] 213 #[cfg(flash)]
214 pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>); 214 pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_internal::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>);
215 }); 215 });
216 } 216 }
217 217
@@ -243,7 +243,7 @@ fn main() {
243 243
244 #[cfg(flash)] 244 #[cfg(flash)]
245 impl<'d, MODE> FlashLayout<'d, MODE> { 245 impl<'d, MODE> FlashLayout<'d, MODE> {
246 pub(crate) fn new(p: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self { 246 pub(crate) fn new(p: embassy_hal_internal::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self {
247 Self { 247 Self {
248 #(#inits),*, 248 #(#inits),*,
249 _mode: core::marker::PhantomData, 249 _mode: core::marker::PhantomData,
@@ -572,21 +572,31 @@ fn main() {
572 (("fmc", "Clk"), quote!(crate::fmc::ClkPin)), 572 (("fmc", "Clk"), quote!(crate::fmc::ClkPin)),
573 (("fmc", "BA0"), quote!(crate::fmc::BA0Pin)), 573 (("fmc", "BA0"), quote!(crate::fmc::BA0Pin)),
574 (("fmc", "BA1"), quote!(crate::fmc::BA1Pin)), 574 (("fmc", "BA1"), quote!(crate::fmc::BA1Pin)),
575 (("timer", "CH1"), quote!(crate::pwm::Channel1Pin)), 575 (("timer", "CH1"), quote!(crate::timer::Channel1Pin)),
576 (("timer", "CH1N"), quote!(crate::pwm::Channel1ComplementaryPin)), 576 (("timer", "CH1N"), quote!(crate::timer::Channel1ComplementaryPin)),
577 (("timer", "CH2"), quote!(crate::pwm::Channel2Pin)), 577 (("timer", "CH2"), quote!(crate::timer::Channel2Pin)),
578 (("timer", "CH2N"), quote!(crate::pwm::Channel2ComplementaryPin)), 578 (("timer", "CH2N"), quote!(crate::timer::Channel2ComplementaryPin)),
579 (("timer", "CH3"), quote!(crate::pwm::Channel3Pin)), 579 (("timer", "CH3"), quote!(crate::timer::Channel3Pin)),
580 (("timer", "CH3N"), quote!(crate::pwm::Channel3ComplementaryPin)), 580 (("timer", "CH3N"), quote!(crate::timer::Channel3ComplementaryPin)),
581 (("timer", "CH4"), quote!(crate::pwm::Channel4Pin)), 581 (("timer", "CH4"), quote!(crate::timer::Channel4Pin)),
582 (("timer", "CH4N"), quote!(crate::pwm::Channel4ComplementaryPin)), 582 (("timer", "CH4N"), quote!(crate::timer::Channel4ComplementaryPin)),
583 (("timer", "ETR"), quote!(crate::pwm::ExternalTriggerPin)), 583 (("timer", "ETR"), quote!(crate::timer::ExternalTriggerPin)),
584 (("timer", "BKIN"), quote!(crate::pwm::BreakInputPin)), 584 (("timer", "BKIN"), quote!(crate::timer::BreakInputPin)),
585 (("timer", "BKIN_COMP1"), quote!(crate::pwm::BreakInputComparator1Pin)), 585 (("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)),
586 (("timer", "BKIN_COMP2"), quote!(crate::pwm::BreakInputComparator2Pin)), 586 (("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)),
587 (("timer", "BKIN2"), quote!(crate::pwm::BreakInput2Pin)), 587 (("timer", "BKIN2"), quote!(crate::timer::BreakInput2Pin)),
588 (("timer", "BKIN2_COMP1"), quote!(crate::pwm::BreakInput2Comparator1Pin)), 588 (("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)),
589 (("timer", "BKIN2_COMP2"), quote!(crate::pwm::BreakInput2Comparator2Pin)), 589 (("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)),
590 (("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)),
591 (("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)),
592 (("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)),
593 (("hrtim", "CHB2"), quote!(crate::hrtim::ChannelBComplementaryPin)),
594 (("hrtim", "CHC1"), quote!(crate::hrtim::ChannelCPin)),
595 (("hrtim", "CHC2"), quote!(crate::hrtim::ChannelCComplementaryPin)),
596 (("hrtim", "CHD1"), quote!(crate::hrtim::ChannelDPin)),
597 (("hrtim", "CHD2"), quote!(crate::hrtim::ChannelDComplementaryPin)),
598 (("hrtim", "CHE1"), quote!(crate::hrtim::ChannelEPin)),
599 (("hrtim", "CHE2"), quote!(crate::hrtim::ChannelEComplementaryPin)),
590 (("sdmmc", "CK"), quote!(crate::sdmmc::CkPin)), 600 (("sdmmc", "CK"), quote!(crate::sdmmc::CkPin)),
591 (("sdmmc", "CMD"), quote!(crate::sdmmc::CmdPin)), 601 (("sdmmc", "CMD"), quote!(crate::sdmmc::CmdPin)),
592 (("sdmmc", "D0"), quote!(crate::sdmmc::D0Pin)), 602 (("sdmmc", "D0"), quote!(crate::sdmmc::D0Pin)),
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index 2322204d5..e577ec289 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::into_ref; 1use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs; 2use embedded_hal_02::blocking::delay::DelayUs;
3 3
4use crate::adc::{Adc, AdcPin, Instance, SampleTime}; 4use crate::adc::{Adc, AdcPin, Instance, SampleTime};
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index d9af0c55e..e8245884e 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::into_ref; 1use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs; 2use embedded_hal_02::blocking::delay::DelayUs;
3 3
4use crate::adc::{Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime}; 4use crate::adc::{Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime};
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 091c1d447..9a7acea53 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::into_ref; 1use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs; 2use embedded_hal_02::blocking::delay::DelayUs;
3 3
4use super::InternalChannel; 4use super::InternalChannel;
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 3a6e58cf6..821cc7f6a 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::into_ref; 1use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs; 2use embedded_hal_02::blocking::delay::DelayUs;
3 3
4use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime}; 4use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index c51c6840f..64d0f0c75 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -226,7 +226,7 @@ impl Prescaler {
226 226
227impl<'d, T: Instance> Adc<'d, T> { 227impl<'d, T: Instance> Adc<'d, T> {
228 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self { 228 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self {
229 embassy_hal_common::into_ref!(adc); 229 embassy_hal_internal::into_ref!(adc);
230 T::enable(); 230 T::enable();
231 T::reset(); 231 T::reset();
232 232
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 795becabf..448be1cdd 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -6,7 +6,7 @@ use core::task::Poll;
6 6
7pub use bxcan; 7pub use bxcan;
8use bxcan::{Data, ExtendedId, Frame, Id, StandardId}; 8use bxcan::{Data, ExtendedId, Frame, Id, StandardId};
9use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10use futures::FutureExt; 10use futures::FutureExt;
11 11
12use crate::gpio::sealed::AFType; 12use crate::gpio::sealed::AFType;
@@ -88,6 +88,7 @@ pub struct Can<'d, T: Instance> {
88} 88}
89 89
90#[derive(Debug)] 90#[derive(Debug)]
91#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91pub enum BusError { 92pub enum BusError {
92 Stuff, 93 Stuff,
93 Form, 94 Form,
@@ -101,6 +102,22 @@ pub enum BusError {
101 BusWarning, 102 BusWarning,
102} 103}
103 104
105#[derive(Debug)]
106#[cfg_attr(feature = "defmt", derive(defmt::Format))]
107pub enum TryReadError {
108 /// Bus error
109 BusError(BusError),
110 /// Receive buffer is empty
111 Empty,
112}
113
114#[derive(Debug)]
115#[cfg_attr(feature = "defmt", derive(defmt::Format))]
116pub enum TryWriteError {
117 /// All transmit mailboxes are full
118 Full,
119}
120
104impl<'d, T: Instance> Can<'d, T> { 121impl<'d, T: Instance> Can<'d, T> {
105 /// Creates a new Bxcan instance, keeping the peripheral in sleep mode. 122 /// Creates a new Bxcan instance, keeping the peripheral in sleep mode.
106 /// You must call [Can::enable_non_blocking] to use the peripheral. 123 /// You must call [Can::enable_non_blocking] to use the peripheral.
@@ -186,56 +203,46 @@ impl<'d, T: Instance> Can<'d, T> {
186 203
187 /// Queues the message to be sent but exerts backpressure 204 /// Queues the message to be sent but exerts backpressure
188 pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { 205 pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
189 poll_fn(|cx| { 206 CanTx { can: &self.can }.write(frame).await
190 T::state().tx_waker.register(cx.waker()); 207 }
191 if let Ok(status) = self.can.borrow_mut().transmit(frame) {
192 return Poll::Ready(status);
193 }
194 208
195 Poll::Pending 209 /// Attempts to transmit a frame without blocking.
196 }) 210 ///
197 .await 211 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
212 pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
213 CanTx { can: &self.can }.try_write(frame)
198 } 214 }
199 215
216 /// Waits for a specific transmit mailbox to become empty
200 pub async fn flush(&self, mb: bxcan::Mailbox) { 217 pub async fn flush(&self, mb: bxcan::Mailbox) {
201 poll_fn(|cx| { 218 CanTx { can: &self.can }.flush(mb).await
202 T::state().tx_waker.register(cx.waker()); 219 }
203 if T::regs().tsr().read().tme(mb.index()) {
204 return Poll::Ready(());
205 }
206 220
207 Poll::Pending 221 /// Waits until any of the transmit mailboxes become empty
208 }) 222 pub async fn flush_any(&self) {
209 .await; 223 CanTx { can: &self.can }.flush_any().await
224 }
225
226 /// Waits until all of the transmit mailboxes become empty
227 pub async fn flush_all(&self) {
228 CanTx { can: &self.can }.flush_all().await
210 } 229 }
211 230
212 /// Returns a tuple of the time the message was received and the message frame 231 /// Returns a tuple of the time the message was received and the message frame
213 pub async fn read(&mut self) -> Result<Envelope, BusError> { 232 pub async fn read(&mut self) -> Result<Envelope, BusError> {
214 poll_fn(|cx| { 233 CanRx { can: &self.can }.read().await
215 T::state().err_waker.register(cx.waker()); 234 }
216 if let Poll::Ready(envelope) = T::state().rx_queue.recv().poll_unpin(cx) {
217 return Poll::Ready(Ok(envelope));
218 } else if let Some(err) = self.curr_error() {
219 return Poll::Ready(Err(err));
220 }
221 235
222 Poll::Pending 236 /// Attempts to read a can frame without blocking.
223 }) 237 ///
224 .await 238 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
239 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
240 CanRx { can: &self.can }.try_read()
225 } 241 }
226 242
227 fn curr_error(&self) -> Option<BusError> { 243 /// Waits while receive queue is empty.
228 let err = { T::regs().esr().read() }; 244 pub async fn wait_not_empty(&mut self) {
229 if err.boff() { 245 CanRx { can: &self.can }.wait_not_empty().await
230 return Some(BusError::BusOff);
231 } else if err.epvf() {
232 return Some(BusError::BusPassive);
233 } else if err.ewgf() {
234 return Some(BusError::BusWarning);
235 } else if let Some(err) = err.lec().into_bus_err() {
236 return Some(err);
237 }
238 None
239 } 246 }
240 247
241 unsafe fn receive_fifo(fifo: RxFifo) { 248 unsafe fn receive_fifo(fifo: RxFifo) {
@@ -405,6 +412,14 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
405 .await 412 .await
406 } 413 }
407 414
415 /// Attempts to transmit a frame without blocking.
416 ///
417 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
418 pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
419 self.can.borrow_mut().transmit(frame).map_err(|_| TryWriteError::Full)
420 }
421
422 /// Waits for a specific transmit mailbox to become empty
408 pub async fn flush(&self, mb: bxcan::Mailbox) { 423 pub async fn flush(&self, mb: bxcan::Mailbox) {
409 poll_fn(|cx| { 424 poll_fn(|cx| {
410 T::state().tx_waker.register(cx.waker()); 425 T::state().tx_waker.register(cx.waker());
@@ -416,6 +431,42 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
416 }) 431 })
417 .await; 432 .await;
418 } 433 }
434
435 /// Waits until any of the transmit mailboxes become empty
436 pub async fn flush_any(&self) {
437 poll_fn(|cx| {
438 T::state().tx_waker.register(cx.waker());
439
440 let tsr = T::regs().tsr().read();
441 if tsr.tme(bxcan::Mailbox::Mailbox0.index())
442 || tsr.tme(bxcan::Mailbox::Mailbox1.index())
443 || tsr.tme(bxcan::Mailbox::Mailbox2.index())
444 {
445 return Poll::Ready(());
446 }
447
448 Poll::Pending
449 })
450 .await;
451 }
452
453 /// Waits until all of the transmit mailboxes become empty
454 pub async fn flush_all(&self) {
455 poll_fn(|cx| {
456 T::state().tx_waker.register(cx.waker());
457
458 let tsr = T::regs().tsr().read();
459 if tsr.tme(bxcan::Mailbox::Mailbox0.index())
460 && tsr.tme(bxcan::Mailbox::Mailbox1.index())
461 && tsr.tme(bxcan::Mailbox::Mailbox2.index())
462 {
463 return Poll::Ready(());
464 }
465
466 Poll::Pending
467 })
468 .await;
469 }
419} 470}
420 471
421#[allow(dead_code)] 472#[allow(dead_code)]
@@ -438,6 +489,33 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
438 .await 489 .await
439 } 490 }
440 491
492 /// Attempts to read a CAN frame without blocking.
493 ///
494 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
495 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
496 if let Ok(envelope) = T::state().rx_queue.try_recv() {
497 return Ok(envelope);
498 }
499
500 if let Some(err) = self.curr_error() {
501 return Err(TryReadError::BusError(err));
502 }
503
504 Err(TryReadError::Empty)
505 }
506
507 /// Waits while receive queue is empty.
508 pub async fn wait_not_empty(&mut self) {
509 poll_fn(|cx| {
510 if T::state().rx_queue.poll_ready_to_receive(cx) {
511 Poll::Ready(())
512 } else {
513 Poll::Pending
514 }
515 })
516 .await
517 }
518
441 fn curr_error(&self) -> Option<BusError> { 519 fn curr_error(&self) -> Option<BusError> {
442 let err = { T::regs().esr().read() }; 520 let err = { T::regs().esr().read() };
443 if err.boff() { 521 if err.boff() {
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index c31a7fc63..f77788db3 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -1,5 +1,5 @@
1pub use bxcan; 1pub use bxcan;
2use embassy_hal_common::PeripheralRef; 2use embassy_hal_internal::PeripheralRef;
3 3
4use crate::peripherals; 4use crate::peripherals;
5 5
diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs
index 3946a2d47..154f2eb91 100644
--- a/embassy-stm32/src/crc/v1.rs
+++ b/embassy-stm32/src/crc/v1.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::{into_ref, PeripheralRef}; 1use 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;
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs
index f337055a7..de0c08755 100644
--- a/embassy-stm32/src/crc/v2v3.rs
+++ b/embassy-stm32/src/crc/v2v3.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::{into_ref, PeripheralRef}; 1use embassy_hal_internal::{into_ref, PeripheralRef};
2 2
3use crate::pac::crc::vals; 3use crate::pac::crc::vals;
4use crate::pac::CRC as PAC_CRC; 4use crate::pac::CRC as PAC_CRC;
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 979748bb4..a2040b857 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -3,7 +3,7 @@
3//! Provide access to the STM32 digital-to-analog converter (DAC). 3//! Provide access to the STM32 digital-to-analog converter (DAC).
4use core::marker::PhantomData; 4use core::marker::PhantomData;
5 5
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use embassy_hal_internal::{into_ref, PeripheralRef};
7 7
8use crate::pac::dac; 8use crate::pac::dac;
9use crate::rcc::RccPeripheral; 9use crate::rcc::RccPeripheral;
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index 78b026cb6..7497f4aaa 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -2,7 +2,7 @@ use core::future::poll_fn;
2use core::marker::PhantomData; 2use core::marker::PhantomData;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use embassy_sync::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
7 7
8use crate::dma::Transfer; 8use crate::dma::Transfer;
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 5a87888b7..d956047d5 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -6,7 +6,7 @@ use core::sync::atomic::{fence, Ordering};
6use core::task::{Context, Poll, Waker}; 6use core::task::{Context, Poll, Waker};
7 7
8use atomic_polyfill::AtomicUsize; 8use atomic_polyfill::AtomicUsize;
9use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 9use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
10use embassy_sync::waitqueue::AtomicWaker; 10use embassy_sync::waitqueue::AtomicWaker;
11 11
12use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError}; 12use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError};
@@ -466,15 +466,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
466 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); 466 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
467 } 467 }
468 468
469 /// Read bytes from the ring buffer 469 /// Read elements from the ring buffer
470 /// Return a tuple of the length read and the length remaining in the buffer 470 /// Return a tuple of the length read and the length remaining in the buffer
471 /// If not all of the bytes were read, then there will be some bytes in the buffer remaining 471 /// If not all of the elements were read, then there will be some elements in the buffer remaining
472 /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read 472 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
473 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 473 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
474 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 474 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
475 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) 475 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf)
476 } 476 }
477 477
478 /// Read an exact number of elements from the ringbuffer.
479 ///
480 /// Returns the remaining number of elements available for immediate reading.
481 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
482 ///
483 /// Async/Wake Behavior:
484 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
485 /// and when it wraps around. This means that when called with a buffer of length 'M', when this
486 /// ring buffer was created with a buffer of size 'N':
487 /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
488 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
489 pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
490 use core::future::poll_fn;
491 use core::sync::atomic::compiler_fence;
492
493 let mut read_data = 0;
494 let buffer_len = buffer.len();
495
496 poll_fn(|cx| {
497 self.set_waker(cx.waker());
498
499 compiler_fence(Ordering::SeqCst);
500
501 match self.read(&mut buffer[read_data..buffer_len]) {
502 Ok((len, remaining)) => {
503 read_data += len;
504 if read_data == buffer_len {
505 Poll::Ready(Ok(remaining))
506 } else {
507 Poll::Pending
508 }
509 }
510 Err(e) => Poll::Ready(Err(e)),
511 }
512 })
513 .await
514 }
515
478 /// The capacity of the ringbuffer 516 /// The capacity of the ringbuffer
479 pub fn cap(&self) -> usize { 517 pub fn cap(&self) -> usize {
480 self.ringbuf.cap() 518 self.ringbuf.cap()
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index f14084599..219ef2eb0 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -4,7 +4,7 @@ use core::pin::Pin;
4use core::sync::atomic::{fence, AtomicUsize, Ordering}; 4use core::sync::atomic::{fence, AtomicUsize, Ordering};
5use core::task::{Context, Poll, Waker}; 5use core::task::{Context, Poll, Waker};
6 6
7use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 7use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9 9
10use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError}; 10use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError};
@@ -711,15 +711,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
711 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); 711 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
712 } 712 }
713 713
714 /// Read bytes from the ring buffer 714 /// Read elements from the ring buffer
715 /// Return a tuple of the length read and the length remaining in the buffer 715 /// Return a tuple of the length read and the length remaining in the buffer
716 /// If not all of the bytes were read, then there will be some bytes in the buffer remaining 716 /// If not all of the elements were read, then there will be some elements in the buffer remaining
717 /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read 717 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
718 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 718 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
719 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 719 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
720 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) 720 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf)
721 } 721 }
722 722
723 /// Read an exact number of elements from the ringbuffer.
724 ///
725 /// Returns the remaining number of elements available for immediate reading.
726 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
727 ///
728 /// Async/Wake Behavior:
729 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
730 /// and when it wraps around. This means that when called with a buffer of length 'M', when this
731 /// ring buffer was created with a buffer of size 'N':
732 /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
733 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
734 pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
735 use core::future::poll_fn;
736 use core::sync::atomic::compiler_fence;
737
738 let mut read_data = 0;
739 let buffer_len = buffer.len();
740
741 poll_fn(|cx| {
742 self.set_waker(cx.waker());
743
744 compiler_fence(Ordering::SeqCst);
745
746 match self.read(&mut buffer[read_data..buffer_len]) {
747 Ok((len, remaining)) => {
748 read_data += len;
749 if read_data == buffer_len {
750 Poll::Ready(Ok(remaining))
751 } else {
752 Poll::Pending
753 }
754 }
755 Err(e) => Poll::Ready(Err(e)),
756 }
757 })
758 .await
759 }
760
723 // The capacity of the ringbuffer 761 // The capacity of the ringbuffer
724 pub fn cap(&self) -> usize { 762 pub fn cap(&self) -> usize {
725 self.ringbuf.cap() 763 self.ringbuf.cap()
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index b7bcf7795..97cc200d7 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -5,7 +5,7 @@ use core::pin::Pin;
5use core::sync::atomic::{fence, Ordering}; 5use core::sync::atomic::{fence, Ordering};
6use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
7 7
8use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 8use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10 10
11use super::word::{Word, WordSize}; 11use super::word::{Word, WordSize};
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 0858587bd..4f1a58ae2 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -26,7 +26,7 @@ pub mod word;
26 26
27use core::mem; 27use core::mem;
28 28
29use embassy_hal_common::impl_peripheral; 29use embassy_hal_internal::impl_peripheral;
30 30
31#[cfg(dmamux)] 31#[cfg(dmamux)]
32pub use self::dmamux::*; 32pub use self::dmamux::*;
diff --git a/embassy-stm32/src/dma/ringbuffer.rs b/embassy-stm32/src/dma/ringbuffer.rs
index a2bde986f..190793974 100644
--- a/embassy-stm32/src/dma/ringbuffer.rs
+++ b/embassy-stm32/src/dma/ringbuffer.rs
@@ -72,10 +72,10 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
72 self.cap() - remaining_transfers 72 self.cap() - remaining_transfers
73 } 73 }
74 74
75 /// Read bytes from the ring buffer 75 /// Read elements from the ring buffer
76 /// Return a tuple of the length read and the length remaining in the buffer 76 /// Return a tuple of the length read and the length remaining in the buffer
77 /// If not all of the bytes were read, then there will be some bytes in the buffer remaining 77 /// If not all of the elements were read, then there will be some elements in the buffer remaining
78 /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read 78 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
79 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 79 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
80 pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 80 pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
81 /* 81 /*
@@ -95,11 +95,11 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
95 */ 95 */
96 let end = self.pos(dma.get_remaining_transfers()); 96 let end = self.pos(dma.get_remaining_transfers());
97 if self.start == end && dma.get_complete_count() == 0 { 97 if self.start == end && dma.get_complete_count() == 0 {
98 // No bytes are available in the buffer 98 // No elements are available in the buffer
99 Ok((0, self.cap())) 99 Ok((0, self.cap()))
100 } else if self.start < end { 100 } else if self.start < end {
101 // The available, unread portion in the ring buffer DOES NOT wrap 101 // The available, unread portion in the ring buffer DOES NOT wrap
102 // Copy out the bytes from the dma buffer 102 // Copy out the elements from the dma buffer
103 let len = self.copy_to(buf, self.start..end); 103 let len = self.copy_to(buf, self.start..end);
104 104
105 compiler_fence(Ordering::SeqCst); 105 compiler_fence(Ordering::SeqCst);
@@ -128,7 +128,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
128 // The DMA writer has wrapped since we last read and is currently 128 // The DMA writer has wrapped since we last read and is currently
129 // writing (or the next byte added will be) in the beginning of the ring buffer. 129 // writing (or the next byte added will be) in the beginning of the ring buffer.
130 130
131 // The provided read buffer is not large enough to include all bytes from the tail of the dma buffer. 131 // The provided read buffer is not large enough to include all elements from the tail of the dma buffer.
132 132
133 // Copy out from the dma buffer 133 // Copy out from the dma buffer
134 let len = self.copy_to(buf, self.start..self.cap()); 134 let len = self.copy_to(buf, self.start..self.cap());
@@ -154,8 +154,8 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
154 // The DMA writer has wrapped since we last read and is currently 154 // The DMA writer has wrapped since we last read and is currently
155 // writing (or the next byte added will be) in the beginning of the ring buffer. 155 // writing (or the next byte added will be) in the beginning of the ring buffer.
156 156
157 // The provided read buffer is large enough to include all bytes from the tail of the dma buffer, 157 // The provided read buffer is large enough to include all elements from the tail of the dma buffer,
158 // so the next read will not have any unread tail bytes in the ring buffer. 158 // so the next read will not have any unread tail elements in the ring buffer.
159 159
160 // Copy out from the dma buffer 160 // Copy out from the dma buffer
161 let tail = self.copy_to(buf, self.start..self.cap()); 161 let tail = self.copy_to(buf, self.start..self.cap());
@@ -180,7 +180,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
180 } 180 }
181 /// Copy from the dma buffer at `data_range` into `buf` 181 /// Copy from the dma buffer at `data_range` into `buf`
182 fn copy_to(&mut self, buf: &mut [W], data_range: Range<usize>) -> usize { 182 fn copy_to(&mut self, buf: &mut [W], data_range: Range<usize>) -> usize {
183 // Limit the number of bytes that can be copied 183 // Limit the number of elements that can be copied
184 let length = usize::min(data_range.len(), buf.len()); 184 let length = usize::min(data_range.len(), buf.len());
185 185
186 // Copy from dma buffer into read buffer 186 // Copy from dma buffer into read buffer
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 2a6ea35ff..a1e0240c8 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -6,7 +6,7 @@ mod tx_desc;
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::sync::atomic::{fence, Ordering}; 7use core::sync::atomic::{fence, Ordering};
8 8
9use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf}; 10use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf};
11 11
12pub(crate) use self::rx_desc::{RDes, RDesRing}; 12pub(crate) use self::rx_desc::{RDes, RDesRing};
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index bb681c42b..ada495fdb 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -3,7 +3,7 @@ mod descriptors;
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::sync::atomic::{fence, Ordering}; 4use core::sync::atomic::{fence, Ordering};
5 5
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use 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::*;
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 3ff92c9e6..925cf39be 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
3use core::pin::Pin; 3use core::pin::Pin;
4use core::task::{Context, Poll}; 4use core::task::{Context, Poll};
5 5
6use embassy_hal_common::impl_peripheral; 6use embassy_hal_internal::impl_peripheral;
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8 8
9use crate::gpio::{AnyPin, Input, Pin as GpioPin}; 9use crate::gpio::{AnyPin, Input, Pin as GpioPin};
diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs
index f175349cd..e966e2a77 100644
--- a/embassy-stm32/src/flash/asynch.rs
+++ b/embassy-stm32/src/flash/asynch.rs
@@ -1,8 +1,8 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2use core::sync::atomic::{fence, Ordering}; 2use core::sync::atomic::{fence, Ordering};
3 3
4use embassy_hal_common::drop::OnDrop; 4use embassy_hal_internal::drop::OnDrop;
5use embassy_hal_common::into_ref; 5use embassy_hal_internal::into_ref;
6use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 6use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
7use embassy_sync::mutex::Mutex; 7use embassy_sync::mutex::Mutex;
8 8
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs
index 2a374733d..16c511295 100644
--- a/embassy-stm32/src/flash/common.rs
+++ b/embassy-stm32/src/flash/common.rs
@@ -1,8 +1,8 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2use core::sync::atomic::{fence, Ordering}; 2use core::sync::atomic::{fence, Ordering};
3 3
4use embassy_hal_common::drop::OnDrop; 4use embassy_hal_internal::drop::OnDrop;
5use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use stm32_metapac::FLASH_BASE; 6use stm32_metapac::FLASH_BASE;
7 7
8use super::{ 8use super::{
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index 4cb39e033..728f6d604 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -14,7 +14,7 @@ use crate::pac;
14mod alt_regions { 14mod alt_regions {
15 use core::marker::PhantomData; 15 use core::marker::PhantomData;
16 16
17 use embassy_hal_common::PeripheralRef; 17 use embassy_hal_internal::PeripheralRef;
18 use stm32_metapac::FLASH_SIZE; 18 use stm32_metapac::FLASH_SIZE;
19 19
20 use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; 20 use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION};
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs
index 60d7a00ee..177e66a91 100644
--- a/embassy-stm32/src/fmc.rs
+++ b/embassy-stm32/src/fmc.rs
@@ -1,6 +1,6 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_hal_common::into_ref; 3use embassy_hal_internal::into_ref;
4 4
5use crate::gpio::sealed::AFType; 5use crate::gpio::sealed::AFType;
6use crate::gpio::{Pull, Speed}; 6use crate::gpio::{Pull, Speed};
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index af3a8eaca..0cc269cfd 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -1,7 +1,7 @@
1#![macro_use] 1#![macro_use]
2use core::convert::Infallible; 2use core::convert::Infallible;
3 3
4use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 4use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
5 5
6use crate::pac::gpio::{self, vals}; 6use crate::pac::gpio::{self, vals};
7use crate::{pac, peripherals, Peripheral}; 7use crate::{pac, peripherals, Peripheral};
@@ -502,6 +502,20 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
502 } 502 }
503} 503}
504 504
505pub enum OutputType {
506 PushPull,
507 OpenDrain,
508}
509
510impl From<OutputType> for sealed::AFType {
511 fn from(value: OutputType) -> Self {
512 match value {
513 OutputType::OpenDrain => sealed::AFType::OutputOpenDrain,
514 OutputType::PushPull => sealed::AFType::OutputPushPull,
515 }
516 }
517}
518
505pub(crate) mod sealed { 519pub(crate) mod sealed {
506 use super::*; 520 use super::*;
507 521
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
new file mode 100644
index 000000000..a930ff73f
--- /dev/null
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -0,0 +1,409 @@
1mod traits;
2
3use core::marker::PhantomData;
4
5use embassy_hal_internal::{into_ref, PeripheralRef};
6pub use traits::Instance;
7
8#[allow(unused_imports)]
9use crate::gpio::sealed::{AFType, Pin};
10use crate::gpio::AnyPin;
11use crate::time::Hertz;
12use crate::Peripheral;
13
14pub enum Source {
15 Master,
16 ChA,
17 ChB,
18 ChC,
19 ChD,
20 ChE,
21}
22
23pub struct BurstController<T: Instance> {
24 phantom: PhantomData<T>,
25}
26pub struct Master<T: Instance> {
27 phantom: PhantomData<T>,
28}
29pub struct ChA<T: Instance> {
30 phantom: PhantomData<T>,
31}
32pub struct ChB<T: Instance> {
33 phantom: PhantomData<T>,
34}
35pub struct ChC<T: Instance> {
36 phantom: PhantomData<T>,
37}
38pub struct ChD<T: Instance> {
39 phantom: PhantomData<T>,
40}
41pub struct ChE<T: Instance> {
42 phantom: PhantomData<T>,
43}
44
45mod sealed {
46 use super::Instance;
47
48 pub trait AdvancedChannel<T: Instance> {
49 fn raw() -> usize;
50 }
51}
52
53pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {}
54
55pub struct PwmPin<'d, Perip, Channel> {
56 _pin: PeripheralRef<'d, AnyPin>,
57 phantom: PhantomData<(Perip, Channel)>,
58}
59
60pub struct ComplementaryPwmPin<'d, Perip, Channel> {
61 _pin: PeripheralRef<'d, AnyPin>,
62 phantom: PhantomData<(Perip, Channel)>,
63}
64
65macro_rules! advanced_channel_impl {
66 ($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
67 impl<'d, Perip: Instance> PwmPin<'d, Perip, $channel<Perip>> {
68 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
69 into_ref!(pin);
70 critical_section::with(|_| {
71 pin.set_low();
72 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
73 #[cfg(gpio_v2)]
74 pin.set_speed(crate::gpio::Speed::VeryHigh);
75 });
76 PwmPin {
77 _pin: pin.map_into(),
78 phantom: PhantomData,
79 }
80 }
81 }
82
83 impl<'d, Perip: Instance> ComplementaryPwmPin<'d, Perip, $channel<Perip>> {
84 pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self {
85 into_ref!(pin);
86 critical_section::with(|_| {
87 pin.set_low();
88 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
89 #[cfg(gpio_v2)]
90 pin.set_speed(crate::gpio::Speed::VeryHigh);
91 });
92 ComplementaryPwmPin {
93 _pin: pin.map_into(),
94 phantom: PhantomData,
95 }
96 }
97 }
98
99 impl<T: Instance> sealed::AdvancedChannel<T> for $channel<T> {
100 fn raw() -> usize {
101 $ch_num
102 }
103 }
104 impl<T: Instance> AdvancedChannel<T> for $channel<T> {}
105 };
106}
107
108advanced_channel_impl!(new_cha, ChA, 0, ChannelAPin, ChannelAComplementaryPin);
109advanced_channel_impl!(new_chb, ChB, 1, ChannelBPin, ChannelBComplementaryPin);
110advanced_channel_impl!(new_chc, ChC, 2, ChannelCPin, ChannelCComplementaryPin);
111advanced_channel_impl!(new_chd, ChD, 3, ChannelDPin, ChannelDComplementaryPin);
112advanced_channel_impl!(new_che, ChE, 4, ChannelEPin, ChannelEComplementaryPin);
113
114/// Struct used to divide a high resolution timer into multiple channels
115pub struct AdvancedPwm<'d, T: Instance> {
116 _inner: PeripheralRef<'d, T>,
117 pub master: Master<T>,
118 pub burst_controller: BurstController<T>,
119 pub ch_a: ChA<T>,
120 pub ch_b: ChB<T>,
121 pub ch_c: ChC<T>,
122 pub ch_d: ChD<T>,
123 pub ch_e: ChE<T>,
124}
125
126impl<'d, T: Instance> AdvancedPwm<'d, T> {
127 pub fn new(
128 tim: impl Peripheral<P = T> + 'd,
129 _cha: Option<PwmPin<'d, T, ChA<T>>>,
130 _chan: Option<ComplementaryPwmPin<'d, T, ChA<T>>>,
131 _chb: Option<PwmPin<'d, T, ChB<T>>>,
132 _chbn: Option<ComplementaryPwmPin<'d, T, ChB<T>>>,
133 _chc: Option<PwmPin<'d, T, ChC<T>>>,
134 _chcn: Option<ComplementaryPwmPin<'d, T, ChC<T>>>,
135 _chd: Option<PwmPin<'d, T, ChD<T>>>,
136 _chdn: Option<ComplementaryPwmPin<'d, T, ChD<T>>>,
137 _che: Option<PwmPin<'d, T, ChE<T>>>,
138 _chen: Option<ComplementaryPwmPin<'d, T, ChE<T>>>,
139 ) -> Self {
140 Self::new_inner(tim)
141 }
142
143 fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self {
144 into_ref!(tim);
145
146 T::enable();
147 <T as crate::rcc::sealed::RccPeripheral>::reset();
148
149 // // Enable and and stabilize the DLL
150 // T::regs().dllcr().modify(|w| {
151 // // w.set_calen(true);
152 // // w.set_calrte(11);
153 // w.set_cal(true);
154 // });
155 //
156 // debug!("wait for dll calibration");
157 // while !T::regs().isr().read().dllrdy() {}
158 //
159 // debug!("dll calibration complete");
160
161 Self {
162 _inner: tim,
163 master: Master { phantom: PhantomData },
164 burst_controller: BurstController { phantom: PhantomData },
165 ch_a: ChA { phantom: PhantomData },
166 ch_b: ChB { phantom: PhantomData },
167 ch_c: ChC { phantom: PhantomData },
168 ch_d: ChD { phantom: PhantomData },
169 ch_e: ChE { phantom: PhantomData },
170 }
171 }
172}
173
174impl<T: Instance> BurstController<T> {
175 pub fn set_source(&mut self, _source: Source) {
176 todo!("burst mode control registers not implemented")
177 }
178}
179
180/// Represents a fixed-frequency bridge converter
181///
182/// Our implementation of the bridge converter uses a single channel and three compare registers,
183/// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous
184/// conduction mode.
185///
186/// It is important to remember that in synchronous topologies, energy can flow in reverse during
187/// light loading conditions, and that the low-side switch must be active for a short time to drive
188/// a bootstrapped high-side switch.
189pub struct BridgeConverter<T: Instance, C: AdvancedChannel<T>> {
190 timer: PhantomData<T>,
191 channel: PhantomData<C>,
192 dead_time: u16,
193 primary_duty: u16,
194 min_secondary_duty: u16,
195 max_secondary_duty: u16,
196}
197
198impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
199 pub fn new(_channel: C, frequency: Hertz) -> Self {
200 use crate::pac::hrtim::vals::{Activeeffect, Inactiveeffect};
201
202 T::set_channel_frequency(C::raw(), frequency);
203
204 // Always enable preload
205 T::regs().tim(C::raw()).cr().modify(|w| {
206 w.set_preen(true);
207 w.set_repu(true);
208 w.set_cont(true);
209 });
210
211 // Enable timer outputs
212 T::regs().oenr().modify(|w| {
213 w.set_t1oen(C::raw(), true);
214 w.set_t2oen(C::raw(), true);
215 });
216
217 // The dead-time generation unit cannot be used because it forces the other output
218 // to be completely complementary to the first output, which restricts certain waveforms
219 // Therefore, software-implemented dead time must be used when setting the duty cycles
220
221 // Set output 1 to active on a period event
222 T::regs()
223 .tim(C::raw())
224 .setr(0)
225 .modify(|w| w.set_per(Activeeffect::SETACTIVE));
226
227 // Set output 1 to inactive on a compare 1 event
228 T::regs()
229 .tim(C::raw())
230 .rstr(0)
231 .modify(|w| w.set_cmp(0, Inactiveeffect::SETINACTIVE));
232
233 // Set output 2 to active on a compare 2 event
234 T::regs()
235 .tim(C::raw())
236 .setr(1)
237 .modify(|w| w.set_cmp(1, Activeeffect::SETACTIVE));
238
239 // Set output 2 to inactive on a compare 3 event
240 T::regs()
241 .tim(C::raw())
242 .rstr(1)
243 .modify(|w| w.set_cmp(2, Inactiveeffect::SETINACTIVE));
244
245 Self {
246 timer: PhantomData,
247 channel: PhantomData,
248 dead_time: 0,
249 primary_duty: 0,
250 min_secondary_duty: 0,
251 max_secondary_duty: 0,
252 }
253 }
254
255 pub fn start(&mut self) {
256 T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true));
257 }
258
259 pub fn stop(&mut self) {
260 T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false));
261 }
262
263 pub fn enable_burst_mode(&mut self) {
264 T::regs().tim(C::raw()).outr().modify(|w| {
265 // Enable Burst Mode
266 w.set_idlem(0, true);
267 w.set_idlem(1, true);
268
269 // Set output to active during the burst
270 w.set_idles(0, true);
271 w.set_idles(1, true);
272 })
273 }
274
275 pub fn disable_burst_mode(&mut self) {
276 T::regs().tim(C::raw()).outr().modify(|w| {
277 // Disable Burst Mode
278 w.set_idlem(0, false);
279 w.set_idlem(1, false);
280 })
281 }
282
283 fn update_primary_duty_or_dead_time(&mut self) {
284 self.min_secondary_duty = self.primary_duty + self.dead_time;
285
286 T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(self.primary_duty));
287 T::regs()
288 .tim(C::raw())
289 .cmp(1)
290 .modify(|w| w.set_cmp(self.min_secondary_duty));
291 }
292
293 /// Set the dead time as a proportion of the maximum compare value
294 pub fn set_dead_time(&mut self, dead_time: u16) {
295 self.dead_time = dead_time;
296 self.max_secondary_duty = self.get_max_compare_value() - dead_time;
297 self.update_primary_duty_or_dead_time();
298 }
299
300 /// Get the maximum compare value of a duty cycle
301 pub fn get_max_compare_value(&mut self) -> u16 {
302 T::regs().tim(C::raw()).per().read().per()
303 }
304
305 /// The primary duty is the period in which the primary switch is active
306 ///
307 /// In the case of a buck converter, this is the high-side switch
308 /// In the case of a boost converter, this is the low-side switch
309 pub fn set_primary_duty(&mut self, primary_duty: u16) {
310 self.primary_duty = primary_duty;
311 self.update_primary_duty_or_dead_time();
312 }
313
314 /// The secondary duty is the period in any switch is active
315 ///
316 /// If less than or equal to the primary duty, the secondary switch will be active for one tick
317 /// If a fully complementary output is desired, the secondary duty can be set to the max compare
318 pub fn set_secondary_duty(&mut self, secondary_duty: u16) {
319 let secondary_duty = if secondary_duty > self.max_secondary_duty {
320 self.max_secondary_duty
321 } else if secondary_duty <= self.min_secondary_duty {
322 self.min_secondary_duty + 1
323 } else {
324 secondary_duty
325 };
326
327 T::regs().tim(C::raw()).cmp(2).modify(|w| w.set_cmp(secondary_duty));
328 }
329}
330
331/// Represents a variable-frequency resonant converter
332///
333/// This implementation of a resonsant converter is appropriate for a half or full bridge,
334/// but does not include secondary rectification, which is appropriate for applications
335/// with a low-voltage on the secondary side.
336pub struct ResonantConverter<T: Instance, C: AdvancedChannel<T>> {
337 timer: PhantomData<T>,
338 channel: PhantomData<C>,
339 min_period: u16,
340 max_period: u16,
341}
342
343impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
344 pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self {
345 T::set_channel_frequency(C::raw(), min_frequency);
346
347 // Always enable preload
348 T::regs().tim(C::raw()).cr().modify(|w| {
349 w.set_preen(true);
350 w.set_repu(true);
351
352 w.set_cont(true);
353 w.set_half(true);
354 });
355
356 // Enable timer outputs
357 T::regs().oenr().modify(|w| {
358 w.set_t1oen(C::raw(), true);
359 w.set_t2oen(C::raw(), true);
360 });
361
362 // Dead-time generator can be used in this case because the primary fets
363 // of a resonant converter are always complementary
364 T::regs().tim(C::raw()).outr().modify(|w| w.set_dten(true));
365
366 let max_period = T::regs().tim(C::raw()).per().read().per();
367 let min_period = max_period * (min_frequency.0 / max_frequency.0) as u16;
368
369 Self {
370 timer: PhantomData,
371 channel: PhantomData,
372 min_period: min_period,
373 max_period: max_period,
374 }
375 }
376
377 /// Set the dead time as a proportion of the maximum compare value
378 pub fn set_dead_time(&mut self, value: u16) {
379 T::set_channel_dead_time(C::raw(), value);
380 }
381
382 pub fn set_period(&mut self, period: u16) {
383 assert!(period < self.max_period);
384 assert!(period > self.min_period);
385
386 T::regs().tim(C::raw()).per().modify(|w| w.set_per(period));
387 }
388
389 /// Get the minimum compare value of a duty cycle
390 pub fn get_min_period(&mut self) -> u16 {
391 self.min_period
392 }
393
394 /// Get the maximum compare value of a duty cycle
395 pub fn get_max_period(&mut self) -> u16 {
396 self.max_period
397 }
398}
399
400pin_trait!(ChannelAPin, Instance);
401pin_trait!(ChannelAComplementaryPin, Instance);
402pin_trait!(ChannelBPin, Instance);
403pin_trait!(ChannelBComplementaryPin, Instance);
404pin_trait!(ChannelCPin, Instance);
405pin_trait!(ChannelCComplementaryPin, Instance);
406pin_trait!(ChannelDPin, Instance);
407pin_trait!(ChannelDComplementaryPin, Instance);
408pin_trait!(ChannelEPin, Instance);
409pin_trait!(ChannelEComplementaryPin, Instance);
diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs
new file mode 100644
index 000000000..158a68862
--- /dev/null
+++ b/embassy-stm32/src/hrtim/traits.rs
@@ -0,0 +1,193 @@
1use crate::rcc::sealed::RccPeripheral;
2use crate::time::Hertz;
3
4#[derive(Clone, Copy)]
5pub(crate) enum Prescaler {
6 Div1,
7 Div2,
8 Div4,
9 Div8,
10 Div16,
11 Div32,
12 Div64,
13 Div128,
14}
15
16impl From<Prescaler> for u32 {
17 fn from(val: Prescaler) -> Self {
18 match val {
19 Prescaler::Div1 => 1,
20 Prescaler::Div2 => 2,
21 Prescaler::Div4 => 4,
22 Prescaler::Div8 => 8,
23 Prescaler::Div16 => 16,
24 Prescaler::Div32 => 32,
25 Prescaler::Div64 => 64,
26 Prescaler::Div128 => 128,
27 }
28 }
29}
30
31impl From<Prescaler> for u8 {
32 fn from(val: Prescaler) -> Self {
33 match val {
34 Prescaler::Div1 => 0b000,
35 Prescaler::Div2 => 0b001,
36 Prescaler::Div4 => 0b010,
37 Prescaler::Div8 => 0b011,
38 Prescaler::Div16 => 0b100,
39 Prescaler::Div32 => 0b101,
40 Prescaler::Div64 => 0b110,
41 Prescaler::Div128 => 0b111,
42 }
43 }
44}
45
46impl From<u8> for Prescaler {
47 fn from(val: u8) -> Self {
48 match val {
49 0b000 => Prescaler::Div1,
50 0b001 => Prescaler::Div2,
51 0b010 => Prescaler::Div4,
52 0b011 => Prescaler::Div8,
53 0b100 => Prescaler::Div16,
54 0b101 => Prescaler::Div32,
55 0b110 => Prescaler::Div64,
56 0b111 => Prescaler::Div128,
57 _ => unreachable!(),
58 }
59 }
60}
61
62impl Prescaler {
63 pub fn compute_min_high_res(val: u32) -> Self {
64 *[
65 Prescaler::Div1,
66 Prescaler::Div2,
67 Prescaler::Div4,
68 Prescaler::Div8,
69 Prescaler::Div16,
70 Prescaler::Div32,
71 Prescaler::Div64,
72 Prescaler::Div128,
73 ]
74 .iter()
75 .skip_while(|psc| <Prescaler as Into<u32>>::into(**psc) <= val)
76 .next()
77 .unwrap()
78 }
79
80 pub fn compute_min_low_res(val: u32) -> Self {
81 *[Prescaler::Div32, Prescaler::Div64, Prescaler::Div128]
82 .iter()
83 .skip_while(|psc| <Prescaler as Into<u32>>::into(**psc) <= val)
84 .next()
85 .unwrap()
86 }
87}
88
89pub(crate) mod sealed {
90 use super::*;
91
92 pub trait Instance: RccPeripheral {
93 fn regs() -> crate::pac::hrtim::Hrtim;
94
95 fn set_master_frequency(frequency: Hertz);
96
97 fn set_channel_frequency(channnel: usize, frequency: Hertz);
98
99 /// Set the dead time as a proportion of max_duty
100 fn set_channel_dead_time(channnel: usize, dead_time: u16);
101
102 // fn enable_outputs(enable: bool);
103 //
104 // fn enable_channel(&mut self, channel: usize, enable: bool);
105 }
106}
107
108pub trait Instance: sealed::Instance + 'static {}
109
110foreach_interrupt! {
111 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
112 impl sealed::Instance for crate::peripherals::$inst {
113 fn regs() -> crate::pac::hrtim::Hrtim {
114 crate::pac::$inst
115 }
116
117 fn set_master_frequency(frequency: Hertz) {
118 use crate::rcc::sealed::RccPeripheral;
119
120 let f = frequency.0;
121 let timer_f = Self::frequency().0;
122 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
123 let psc = if Self::regs().isr().read().dllrdy() {
124 Prescaler::compute_min_high_res(psc_min)
125 } else {
126 Prescaler::compute_min_low_res(psc_min)
127 };
128
129 let psc_val: u32 = psc.into();
130 let timer_f = 32 * (timer_f / psc_val);
131 let per: u16 = (timer_f / f) as u16;
132
133 let regs = Self::regs();
134
135 regs.mcr().modify(|w| w.set_ckpsc(psc.into()));
136 regs.mper().modify(|w| w.set_mper(per));
137 }
138
139 fn set_channel_frequency(channel: usize, frequency: Hertz) {
140 use crate::rcc::sealed::RccPeripheral;
141
142 let f = frequency.0;
143 let timer_f = Self::frequency().0;
144 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
145 let psc = if Self::regs().isr().read().dllrdy() {
146 Prescaler::compute_min_high_res(psc_min)
147 } else {
148 Prescaler::compute_min_low_res(psc_min)
149 };
150
151 let psc_val: u32 = psc.into();
152 let timer_f = 32 * (timer_f / psc_val);
153 let per: u16 = (timer_f / f) as u16;
154
155 let regs = Self::regs();
156
157 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
158 regs.tim(channel).per().modify(|w| w.set_per(per));
159 }
160
161 fn set_channel_dead_time(channel: usize, dead_time: u16) {
162
163 let regs = Self::regs();
164
165 let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into();
166 let psc_val: u32 = channel_psc.into();
167
168
169 // The dead-time base clock runs 4 times slower than the hrtim base clock
170 // u9::MAX = 511
171 let psc_min = (psc_val * dead_time as u32) / (4 * 511);
172 let psc = if Self::regs().isr().read().dllrdy() {
173 Prescaler::compute_min_high_res(psc_min)
174 } else {
175 Prescaler::compute_min_low_res(psc_min)
176 };
177
178 let dt_psc_val: u32 = psc.into();
179 let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val);
180
181 regs.tim(channel).dt().modify(|w| {
182 w.set_dtprsc(psc.into());
183 w.set_dtf(dt_val as u16);
184 w.set_dtr(dt_val as u16);
185 });
186 }
187 }
188
189 impl Instance for crate::peripherals::$inst {
190
191 }
192 };
193}
diff --git a/embassy-stm32/src/i2c/timeout.rs b/embassy-stm32/src/i2c/timeout.rs
index 939e2750e..8dc228b34 100644
--- a/embassy-stm32/src/i2c/timeout.rs
+++ b/embassy-stm32/src/i2c/timeout.rs
@@ -6,8 +6,8 @@ use super::{Error, I2c, Instance};
6/// 6///
7/// This is useful for recovering from a shorted bus or a device stuck in a clock stretching state. 7/// This is useful for recovering from a shorted bus or a device stuck in a clock stretching state.
8/// A regular [I2c] would freeze until condition is removed. 8/// A regular [I2c] would freeze until condition is removed.
9pub struct TimeoutI2c<'d, T: Instance, TXDMA, RXDMA> { 9pub struct TimeoutI2c<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> {
10 i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>, 10 i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>,
11 timeout: Duration, 11 timeout: Duration,
12} 12}
13 13
@@ -22,8 +22,8 @@ fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
22 } 22 }
23} 23}
24 24
25impl<'d, T: Instance, TXDMA, RXDMA> TimeoutI2c<'d, T, TXDMA, RXDMA> { 25impl<'a, 'd, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
26 pub fn new(i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self { 26 pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self {
27 Self { i2c, timeout } 27 Self { i2c, timeout }
28 } 28 }
29 29
@@ -65,7 +65,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> TimeoutI2c<'d, T, TXDMA, RXDMA> {
65 } 65 }
66} 66}
67 67
68impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'d, T, TXDMA, RXDMA> { 68impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
69 type Error = Error; 69 type Error = Error;
70 70
71 fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> { 71 fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> {
@@ -73,7 +73,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for Tim
73 } 73 }
74} 74}
75 75
76impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'d, T, TXDMA, RXDMA> { 76impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
77 type Error = Error; 77 type Error = Error;
78 78
79 fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> { 79 fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> {
@@ -81,7 +81,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for Ti
81 } 81 }
82} 82}
83 83
84impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead for TimeoutI2c<'d, T, TXDMA, RXDMA> { 84impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead
85 for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA>
86{
85 type Error = Error; 87 type Error = Error;
86 88
87 fn write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { 89 fn write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
@@ -93,11 +95,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead fo
93mod eh1 { 95mod eh1 {
94 use super::*; 96 use super::*;
95 97
96 impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'d, T, TXDMA, RXDMA> { 98 impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
97 type Error = Error; 99 type Error = Error;
98 } 100 }
99 101
100 impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'d, T, TXDMA, RXDMA> { 102 impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
101 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { 103 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
102 self.blocking_read(address, read) 104 self.blocking_read(address, read)
103 } 105 }
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index aa485cd86..e5254a8cd 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -1,7 +1,7 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_embedded_hal::SetConfig; 3use embassy_embedded_hal::SetConfig;
4use embassy_hal_common::{into_ref, PeripheralRef}; 4use embassy_hal_internal::{into_ref, PeripheralRef};
5 5
6use crate::dma::NoDma; 6use crate::dma::NoDma;
7use crate::gpio::sealed::AFType; 7use crate::gpio::sealed::AFType;
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 208d1527d..eaf980a4d 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -4,8 +4,8 @@ use core::marker::PhantomData;
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_embedded_hal::SetConfig; 6use embassy_embedded_hal::SetConfig;
7use embassy_hal_common::drop::OnDrop; 7use embassy_hal_internal::drop::OnDrop;
8use embassy_hal_common::{into_ref, PeripheralRef}; 8use embassy_hal_internal::{into_ref, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10 10
11use crate::dma::{NoDma, Transfer}; 11use crate::dma::{NoDma, Transfer};
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 62dda69b4..8fd3a8c6a 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -1,4 +1,4 @@
1use embassy_hal_common::into_ref; 1use embassy_hal_internal::into_ref;
2 2
3use crate::gpio::sealed::{AFType, Pin as _}; 3use crate::gpio::sealed::{AFType, Pin as _};
4use crate::gpio::AnyPin; 4use crate::gpio::AnyPin;
@@ -165,7 +165,9 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
165 mck.set_as_af(mck.af_num(), AFType::OutputPushPull); 165 mck.set_as_af(mck.af_num(), AFType::OutputPushPull);
166 mck.set_speed(crate::gpio::Speed::VeryHigh); 166 mck.set_speed(crate::gpio::Speed::VeryHigh);
167 167
168 let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default()); 168 let mut spi_cfg = SpiConfig::default();
169 spi_cfg.frequency = freq;
170 let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg);
169 171
170 #[cfg(all(rcc_f4, not(stm32f410)))] 172 #[cfg(all(rcc_f4, not(stm32f410)))]
171 let pclk = unsafe { get_freqs() }.plli2s.unwrap(); 173 let pclk = unsafe { get_freqs() }.plli2s.unwrap();
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 45a7b5476..34220fbf5 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -1,6 +1,9 @@
1#![cfg_attr(not(test), no_std)] 1#![cfg_attr(not(test), no_std)]
2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))] 2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))]
3 3
4//! ## Feature flags
5#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
6
4// This must go FIRST so that all the other modules see its macros. 7// This must go FIRST so that all the other modules see its macros.
5pub mod fmt; 8pub mod fmt;
6include!(concat!(env!("OUT_DIR"), "/_macros.rs")); 9include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
@@ -23,6 +26,8 @@ pub mod timer;
23pub mod adc; 26pub mod adc;
24#[cfg(can)] 27#[cfg(can)]
25pub mod can; 28pub mod can;
29#[cfg(crc)]
30pub mod crc;
26#[cfg(dac)] 31#[cfg(dac)]
27pub mod dac; 32pub mod dac;
28#[cfg(dcmi)] 33#[cfg(dcmi)]
@@ -31,19 +36,17 @@ pub mod dcmi;
31pub mod eth; 36pub mod eth;
32#[cfg(feature = "exti")] 37#[cfg(feature = "exti")]
33pub mod exti; 38pub mod exti;
39pub mod flash;
34#[cfg(fmc)] 40#[cfg(fmc)]
35pub mod fmc; 41pub mod fmc;
42#[cfg(hrtim_v1)]
43pub mod hrtim;
36#[cfg(i2c)] 44#[cfg(i2c)]
37pub mod i2c; 45pub mod i2c;
38
39#[cfg(crc)]
40pub mod crc;
41pub mod flash;
42#[cfg(all(spi_v1, rcc_f4))] 46#[cfg(all(spi_v1, rcc_f4))]
43pub mod i2s; 47pub mod i2s;
44#[cfg(stm32wb)] 48#[cfg(stm32wb)]
45pub mod ipcc; 49pub mod ipcc;
46pub mod pwm;
47#[cfg(quadspi)] 50#[cfg(quadspi)]
48pub mod qspi; 51pub mod qspi;
49#[cfg(rng)] 52#[cfg(rng)]
@@ -79,7 +82,7 @@ pub use crate::_generated::interrupt;
79/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) 82/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
80/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to 83/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
81/// prove at compile-time that the right interrupts have been bound. 84/// prove at compile-time that the right interrupts have been bound.
82// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. 85// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
83#[macro_export] 86#[macro_export]
84macro_rules! bind_interrupts { 87macro_rules! bind_interrupts {
85 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { 88 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
@@ -103,7 +106,7 @@ macro_rules! bind_interrupts {
103 106
104// Reexports 107// Reexports
105pub use _generated::{peripherals, Peripherals}; 108pub use _generated::{peripherals, Peripherals};
106pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 109pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
107#[cfg(feature = "unstable-pac")] 110#[cfg(feature = "unstable-pac")]
108pub use stm32_metapac as pac; 111pub use stm32_metapac as pac;
109#[cfg(not(feature = "unstable-pac"))] 112#[cfg(not(feature = "unstable-pac"))]
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs
deleted file mode 100644
index 5aba2663e..000000000
--- a/embassy-stm32/src/pwm/mod.rs
+++ /dev/null
@@ -1,269 +0,0 @@
1pub mod complementary_pwm;
2pub mod simple_pwm;
3
4use stm32_metapac::timer::vals::Ckd;
5
6#[cfg(feature = "unstable-pac")]
7pub mod low_level {
8 pub use super::sealed::*;
9}
10
11#[derive(Clone, Copy)]
12pub enum Channel {
13 Ch1,
14 Ch2,
15 Ch3,
16 Ch4,
17}
18
19impl Channel {
20 pub fn raw(&self) -> usize {
21 match self {
22 Channel::Ch1 => 0,
23 Channel::Ch2 => 1,
24 Channel::Ch3 => 2,
25 Channel::Ch4 => 3,
26 }
27 }
28}
29
30#[derive(Clone, Copy)]
31pub enum OutputCompareMode {
32 Frozen,
33 ActiveOnMatch,
34 InactiveOnMatch,
35 Toggle,
36 ForceInactive,
37 ForceActive,
38 PwmMode1,
39 PwmMode2,
40}
41
42impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
43 fn from(mode: OutputCompareMode) -> Self {
44 match mode {
45 OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN,
46 OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH,
47 OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH,
48 OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE,
49 OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE,
50 OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE,
51 OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1,
52 OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2,
53 }
54 }
55}
56
57pub(crate) mod sealed {
58 use super::*;
59
60 pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance {
61 /// Global output enable. Does not do anything on non-advanced timers.
62 fn enable_outputs(&mut self, enable: bool);
63
64 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
65
66 fn enable_channel(&mut self, channel: Channel, enable: bool);
67
68 fn set_compare_value(&mut self, channel: Channel, value: u16);
69
70 fn get_max_compare_value(&self) -> u16;
71 }
72
73 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance {
74 fn set_dead_time_clock_division(&mut self, value: Ckd);
75
76 fn set_dead_time_value(&mut self, value: u8);
77
78 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool);
79 }
80
81 pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance {
82 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
83
84 fn enable_channel(&mut self, channel: Channel, enable: bool);
85
86 fn set_compare_value(&mut self, channel: Channel, value: u32);
87
88 fn get_max_compare_value(&self) -> u32;
89 }
90}
91
92pub trait CaptureCompare16bitInstance:
93 sealed::CaptureCompare16bitInstance + crate::timer::GeneralPurpose16bitInstance + 'static
94{
95}
96
97pub trait ComplementaryCaptureCompare16bitInstance:
98 sealed::ComplementaryCaptureCompare16bitInstance + crate::timer::AdvancedControlInstance + 'static
99{
100}
101
102pub trait CaptureCompare32bitInstance:
103 sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + crate::timer::GeneralPurpose32bitInstance + 'static
104{
105}
106
107#[allow(unused)]
108macro_rules! impl_compare_capable_16bit {
109 ($inst:ident) => {
110 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
111 fn enable_outputs(&mut self, _enable: bool) {}
112
113 fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) {
114 use crate::timer::sealed::GeneralPurpose16bitInstance;
115 let r = Self::regs_gp16();
116 let raw_channel: usize = channel.raw();
117 r.ccmr_output(raw_channel / 2)
118 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
119 }
120
121 fn enable_channel(&mut self, channel: Channel, enable: bool) {
122 use crate::timer::sealed::GeneralPurpose16bitInstance;
123 Self::regs_gp16()
124 .ccer()
125 .modify(|w| w.set_cce(channel.raw(), enable));
126 }
127
128 fn set_compare_value(&mut self, channel: Channel, value: u16) {
129 use crate::timer::sealed::GeneralPurpose16bitInstance;
130 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
131 }
132
133 fn get_max_compare_value(&self) -> u16 {
134 use crate::timer::sealed::GeneralPurpose16bitInstance;
135 Self::regs_gp16().arr().read().arr()
136 }
137 }
138 };
139}
140
141foreach_interrupt! {
142 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
143 impl_compare_capable_16bit!($inst);
144
145 impl CaptureCompare16bitInstance for crate::peripherals::$inst {
146
147 }
148 };
149
150 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
151 impl_compare_capable_16bit!($inst);
152 impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {
153 fn set_output_compare_mode(
154 &mut self,
155 channel: crate::pwm::Channel,
156 mode: OutputCompareMode,
157 ) {
158 use crate::timer::sealed::GeneralPurpose32bitInstance;
159 let raw_channel = channel.raw();
160 Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
161 }
162
163 fn enable_channel(&mut self, channel: Channel, enable: bool) {
164 use crate::timer::sealed::GeneralPurpose32bitInstance;
165 Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable));
166 }
167
168 fn set_compare_value(&mut self, channel: Channel, value: u32) {
169 use crate::timer::sealed::GeneralPurpose32bitInstance;
170 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
171 }
172
173 fn get_max_compare_value(&self) -> u32 {
174 use crate::timer::sealed::GeneralPurpose32bitInstance;
175 Self::regs_gp32().arr().read().arr() as u32
176 }
177 }
178 impl CaptureCompare16bitInstance for crate::peripherals::$inst {
179
180 }
181 impl CaptureCompare32bitInstance for crate::peripherals::$inst {
182
183 }
184 };
185
186 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
187 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
188 fn enable_outputs(&mut self, enable: bool) {
189 use crate::timer::sealed::AdvancedControlInstance;
190 let r = Self::regs_advanced();
191 r.bdtr().modify(|w| w.set_moe(enable));
192 }
193
194 fn set_output_compare_mode(
195 &mut self,
196 channel: crate::pwm::Channel,
197 mode: OutputCompareMode,
198 ) {
199 use crate::timer::sealed::AdvancedControlInstance;
200 let r = Self::regs_advanced();
201 let raw_channel: usize = channel.raw();
202 r.ccmr_output(raw_channel / 2)
203 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
204 }
205
206 fn enable_channel(&mut self, channel: Channel, enable: bool) {
207 use crate::timer::sealed::AdvancedControlInstance;
208 Self::regs_advanced()
209 .ccer()
210 .modify(|w| w.set_cce(channel.raw(), enable));
211 }
212
213 fn set_compare_value(&mut self, channel: Channel, value: u16) {
214 use crate::timer::sealed::AdvancedControlInstance;
215 Self::regs_advanced()
216 .ccr(channel.raw())
217 .modify(|w| w.set_ccr(value));
218 }
219
220 fn get_max_compare_value(&self) -> u16 {
221 use crate::timer::sealed::AdvancedControlInstance;
222 Self::regs_advanced().arr().read().arr()
223 }
224 }
225
226 impl CaptureCompare16bitInstance for crate::peripherals::$inst {
227
228 }
229
230 impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
231 fn set_dead_time_clock_division(&mut self, value: Ckd) {
232 use crate::timer::sealed::AdvancedControlInstance;
233 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
234 }
235
236 fn set_dead_time_value(&mut self, value: u8) {
237 use crate::timer::sealed::AdvancedControlInstance;
238 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
239 }
240
241 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
242 use crate::timer::sealed::AdvancedControlInstance;
243 Self::regs_advanced()
244 .ccer()
245 .modify(|w| w.set_ccne(channel.raw(), enable));
246 }
247 }
248
249 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
250
251 }
252 };
253}
254
255pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
256pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance);
257pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
258pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance);
259pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
260pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance);
261pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
262pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance);
263pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
264pin_trait!(BreakInputPin, CaptureCompare16bitInstance);
265pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance);
266pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance);
267pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance);
268pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance);
269pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance);
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index 31b676088..32382fb28 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -2,7 +2,7 @@
2 2
3pub mod enums; 3pub mod enums;
4 4
5use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
6use enums::*; 6use enums::*;
7 7
8use crate::dma::Transfer; 8use crate::dma::Transfer;
diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs
index df6e9047c..6a9326347 100644
--- a/embassy-stm32/src/rcc/c0.rs
+++ b/embassy-stm32/src/rcc/c0.rs
@@ -1,5 +1,6 @@
1pub use super::common::{AHBPrescaler, APBPrescaler};
1use crate::pac::flash::vals::Latency; 2use crate::pac::flash::vals::Latency;
2use crate::pac::rcc::vals::{Hpre, Hsidiv, Ppre, Sw}; 3use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw};
3use crate::pac::{FLASH, RCC}; 4use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz; 6use crate::time::Hertz;
@@ -45,58 +46,6 @@ impl Into<Hsidiv> for HSIPrescaler {
45 } 46 }
46} 47}
47 48
48/// AHB prescaler
49#[derive(Clone, Copy, PartialEq)]
50pub enum AHBPrescaler {
51 NotDivided,
52 Div2,
53 Div4,
54 Div8,
55 Div16,
56 Div64,
57 Div128,
58 Div256,
59 Div512,
60}
61
62/// APB prescaler
63#[derive(Clone, Copy)]
64pub enum APBPrescaler {
65 NotDivided,
66 Div2,
67 Div4,
68 Div8,
69 Div16,
70}
71
72impl Into<Ppre> for APBPrescaler {
73 fn into(self) -> Ppre {
74 match self {
75 APBPrescaler::NotDivided => Ppre::DIV1,
76 APBPrescaler::Div2 => Ppre::DIV2,
77 APBPrescaler::Div4 => Ppre::DIV4,
78 APBPrescaler::Div8 => Ppre::DIV8,
79 APBPrescaler::Div16 => Ppre::DIV16,
80 }
81 }
82}
83
84impl Into<Hpre> for AHBPrescaler {
85 fn into(self) -> Hpre {
86 match self {
87 AHBPrescaler::NotDivided => Hpre::DIV1,
88 AHBPrescaler::Div2 => Hpre::DIV2,
89 AHBPrescaler::Div4 => Hpre::DIV4,
90 AHBPrescaler::Div8 => Hpre::DIV8,
91 AHBPrescaler::Div16 => Hpre::DIV16,
92 AHBPrescaler::Div64 => Hpre::DIV64,
93 AHBPrescaler::Div128 => Hpre::DIV128,
94 AHBPrescaler::Div256 => Hpre::DIV256,
95 AHBPrescaler::Div512 => Hpre::DIV512,
96 }
97 }
98}
99
100/// Clocks configutation 49/// Clocks configutation
101pub struct Config { 50pub struct Config {
102 pub mux: ClockSrc, 51 pub mux: ClockSrc,
diff --git a/embassy-stm32/src/rcc/common.rs b/embassy-stm32/src/rcc/common.rs
new file mode 100644
index 000000000..62736a43a
--- /dev/null
+++ b/embassy-stm32/src/rcc/common.rs
@@ -0,0 +1,174 @@
1use core::ops::Div;
2
3#[allow(unused_imports)]
4use crate::pac::rcc;
5use crate::time::Hertz;
6
7/// Voltage Scale
8///
9/// Represents the voltage range feeding the CPU core. The maximum core
10/// clock frequency depends on this value.
11///
12/// Scale0 represents the highest voltage range
13#[derive(Copy, Clone, PartialEq)]
14pub enum VoltageScale {
15 Scale0,
16 Scale1,
17 #[cfg(not(any(rcc_wl5, rcc_wle)))]
18 Scale2,
19 #[cfg(not(any(rcc_wl5, rcc_wle)))]
20 Scale3,
21}
22
23/// AHB prescaler
24#[derive(Clone, Copy, PartialEq)]
25pub enum AHBPrescaler {
26 NotDivided,
27 Div2,
28 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
29 Div3,
30 Div4,
31 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
32 Div5,
33 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
34 Div6,
35 Div8,
36 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
37 Div10,
38 Div16,
39 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
40 Div32,
41 Div64,
42 Div128,
43 Div256,
44 Div512,
45}
46
47impl Div<AHBPrescaler> for Hertz {
48 type Output = Hertz;
49
50 fn div(self, rhs: AHBPrescaler) -> Self::Output {
51 let divisor = match rhs {
52 AHBPrescaler::NotDivided => 1,
53 AHBPrescaler::Div2 => 2,
54 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
55 AHBPrescaler::Div3 => 3,
56 AHBPrescaler::Div4 => 4,
57 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
58 AHBPrescaler::Div5 => 5,
59 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
60 AHBPrescaler::Div6 => 6,
61 AHBPrescaler::Div8 => 8,
62 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
63 AHBPrescaler::Div10 => 10,
64 AHBPrescaler::Div16 => 16,
65 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
66 AHBPrescaler::Div32 => 32,
67 AHBPrescaler::Div64 => 64,
68 AHBPrescaler::Div128 => 128,
69 AHBPrescaler::Div256 => 256,
70 AHBPrescaler::Div512 => 512,
71 };
72 Hertz(self.0 / divisor)
73 }
74}
75
76#[cfg(not(any(rcc_g4, rcc_wb, rcc_wl5, rcc_wle)))]
77impl From<AHBPrescaler> for rcc::vals::Hpre {
78 fn from(val: AHBPrescaler) -> rcc::vals::Hpre {
79 use rcc::vals::Hpre;
80
81 match val {
82 #[cfg(not(rcc_u5))]
83 AHBPrescaler::NotDivided => Hpre::DIV1,
84 #[cfg(rcc_u5)]
85 AHBPrescaler::NotDivided => Hpre::NONE,
86 AHBPrescaler::Div2 => Hpre::DIV2,
87 AHBPrescaler::Div4 => Hpre::DIV4,
88 AHBPrescaler::Div8 => Hpre::DIV8,
89 AHBPrescaler::Div16 => Hpre::DIV16,
90 AHBPrescaler::Div64 => Hpre::DIV64,
91 AHBPrescaler::Div128 => Hpre::DIV128,
92 AHBPrescaler::Div256 => Hpre::DIV256,
93 AHBPrescaler::Div512 => Hpre::DIV512,
94 }
95 }
96}
97
98#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
99impl From<AHBPrescaler> for u8 {
100 fn from(val: AHBPrescaler) -> u8 {
101 match val {
102 AHBPrescaler::NotDivided => 0x0,
103 AHBPrescaler::Div2 => 0x08,
104 AHBPrescaler::Div3 => 0x01,
105 AHBPrescaler::Div4 => 0x09,
106 AHBPrescaler::Div5 => 0x02,
107 AHBPrescaler::Div6 => 0x05,
108 AHBPrescaler::Div8 => 0x0a,
109 AHBPrescaler::Div10 => 0x06,
110 AHBPrescaler::Div16 => 0x0b,
111 AHBPrescaler::Div32 => 0x07,
112 AHBPrescaler::Div64 => 0x0c,
113 AHBPrescaler::Div128 => 0x0d,
114 AHBPrescaler::Div256 => 0x0e,
115 AHBPrescaler::Div512 => 0x0f,
116 }
117 }
118}
119
120/// APB prescaler
121#[derive(Clone, Copy)]
122pub enum APBPrescaler {
123 NotDivided,
124 Div2,
125 Div4,
126 Div8,
127 Div16,
128}
129
130impl Div<APBPrescaler> for Hertz {
131 type Output = Hertz;
132
133 fn div(self, rhs: APBPrescaler) -> Self::Output {
134 let divisor = match rhs {
135 APBPrescaler::NotDivided => 1,
136 APBPrescaler::Div2 => 2,
137 APBPrescaler::Div4 => 4,
138 APBPrescaler::Div8 => 8,
139 APBPrescaler::Div16 => 16,
140 };
141 Hertz(self.0 / divisor)
142 }
143}
144
145#[cfg(not(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_g4, rcc_h7, rcc_h7ab, rcc_wb, rcc_wl5, rcc_wle)))]
146impl From<APBPrescaler> for rcc::vals::Ppre {
147 fn from(val: APBPrescaler) -> rcc::vals::Ppre {
148 use rcc::vals::Ppre;
149
150 match val {
151 #[cfg(not(rcc_u5))]
152 APBPrescaler::NotDivided => Ppre::DIV1,
153 #[cfg(rcc_u5)]
154 APBPrescaler::NotDivided => Ppre::NONE,
155 APBPrescaler::Div2 => Ppre::DIV2,
156 APBPrescaler::Div4 => Ppre::DIV4,
157 APBPrescaler::Div8 => Ppre::DIV8,
158 APBPrescaler::Div16 => Ppre::DIV16,
159 }
160 }
161}
162
163#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
164impl From<APBPrescaler> for u8 {
165 fn from(val: APBPrescaler) -> u8 {
166 match val {
167 APBPrescaler::NotDivided => 1,
168 APBPrescaler::Div2 => 0x04,
169 APBPrescaler::Div4 => 0x05,
170 APBPrescaler::Div8 => 0x06,
171 APBPrescaler::Div16 => 0x07,
172 }
173 }
174}
diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs
index 1525cc3c3..d016d1dea 100644
--- a/embassy-stm32/src/rcc/f2.rs
+++ b/embassy-stm32/src/rcc/f2.rs
@@ -1,8 +1,9 @@
1use core::convert::TryFrom; 1use core::convert::TryFrom;
2use core::ops::{Div, Mul}; 2use core::ops::{Div, Mul};
3 3
4pub use super::common::{AHBPrescaler, APBPrescaler};
4use crate::pac::flash::vals::Latency; 5use crate::pac::flash::vals::Latency;
5use crate::pac::rcc::vals::{Hpre, Pllp, Pllsrc, Ppre, Sw}; 6use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw};
6use crate::pac::{FLASH, RCC}; 7use crate::pac::{FLASH, RCC};
7use crate::rcc::{set_freqs, Clocks}; 8use crate::rcc::{set_freqs, Clocks};
8use crate::time::Hertz; 9use crate::time::Hertz;
@@ -58,7 +59,7 @@ impl Default for PLLConfig {
58impl PLLConfig { 59impl PLLConfig {
59 pub fn clocks(&self, src_freq: Hertz) -> PLLClocks { 60 pub fn clocks(&self, src_freq: Hertz) -> PLLClocks {
60 let in_freq = src_freq / self.pre_div; 61 let in_freq = src_freq / self.pre_div;
61 let vco_freq = src_freq * self.mul / self.pre_div; 62 let vco_freq = Hertz((src_freq.0 as u64 * self.mul.0 as u64 / self.pre_div.0 as u64) as u32);
62 let main_freq = vco_freq / self.main_div; 63 let main_freq = vco_freq / self.main_div;
63 let pll48_freq = vco_freq / self.pll48_div; 64 let pll48_freq = vco_freq / self.pll48_div;
64 PLLClocks { 65 PLLClocks {
@@ -200,114 +201,15 @@ pub struct PLLClocks {
200 pub pll48_freq: Hertz, 201 pub pll48_freq: Hertz,
201} 202}
202 203
203/// AHB prescaler 204pub use super::common::VoltageScale;
204#[derive(Clone, Copy, PartialEq)]
205pub enum AHBPrescaler {
206 NotDivided,
207 Div2,
208 Div4,
209 Div8,
210 Div16,
211 Div64,
212 Div128,
213 Div256,
214 Div512,
215}
216
217impl Div<AHBPrescaler> for Hertz {
218 type Output = Hertz;
219
220 fn div(self, rhs: AHBPrescaler) -> Self::Output {
221 let divisor = match rhs {
222 AHBPrescaler::NotDivided => 1,
223 AHBPrescaler::Div2 => 2,
224 AHBPrescaler::Div4 => 4,
225 AHBPrescaler::Div8 => 8,
226 AHBPrescaler::Div16 => 16,
227 AHBPrescaler::Div64 => 64,
228 AHBPrescaler::Div128 => 128,
229 AHBPrescaler::Div256 => 256,
230 AHBPrescaler::Div512 => 512,
231 };
232 Hertz(self.0 / divisor)
233 }
234}
235
236/// APB prescaler
237#[derive(Clone, Copy)]
238pub enum APBPrescaler {
239 NotDivided,
240 Div2,
241 Div4,
242 Div8,
243 Div16,
244}
245
246impl Div<APBPrescaler> for Hertz {
247 type Output = Hertz;
248
249 fn div(self, rhs: APBPrescaler) -> Self::Output {
250 let divisor = match rhs {
251 APBPrescaler::NotDivided => 1,
252 APBPrescaler::Div2 => 2,
253 APBPrescaler::Div4 => 4,
254 APBPrescaler::Div8 => 8,
255 APBPrescaler::Div16 => 16,
256 };
257 Hertz(self.0 / divisor)
258 }
259}
260
261impl Into<Ppre> for APBPrescaler {
262 fn into(self) -> Ppre {
263 match self {
264 APBPrescaler::NotDivided => Ppre::DIV1,
265 APBPrescaler::Div2 => Ppre::DIV2,
266 APBPrescaler::Div4 => Ppre::DIV4,
267 APBPrescaler::Div8 => Ppre::DIV8,
268 APBPrescaler::Div16 => Ppre::DIV16,
269 }
270 }
271}
272
273impl Into<Hpre> for AHBPrescaler {
274 fn into(self) -> Hpre {
275 match self {
276 AHBPrescaler::NotDivided => Hpre::DIV1,
277 AHBPrescaler::Div2 => Hpre::DIV2,
278 AHBPrescaler::Div4 => Hpre::DIV4,
279 AHBPrescaler::Div8 => Hpre::DIV8,
280 AHBPrescaler::Div16 => Hpre::DIV16,
281 AHBPrescaler::Div64 => Hpre::DIV64,
282 AHBPrescaler::Div128 => Hpre::DIV128,
283 AHBPrescaler::Div256 => Hpre::DIV256,
284 AHBPrescaler::Div512 => Hpre::DIV512,
285 }
286 }
287}
288
289/// Voltage Range
290///
291/// Represents the system supply voltage range
292#[derive(Copy, Clone, PartialEq)]
293pub enum VoltageRange {
294 /// 1.8 to 3.6 V
295 Min1V8,
296 /// 2.1 to 3.6 V
297 Min2V1,
298 /// 2.4 to 3.6 V
299 Min2V4,
300 /// 2.7 to 3.6 V
301 Min2V7,
302}
303 205
304impl VoltageRange { 206impl VoltageScale {
305 const fn wait_states(&self, ahb_freq: Hertz) -> Option<Latency> { 207 const fn wait_states(&self, ahb_freq: Hertz) -> Option<Latency> {
306 let ahb_freq = ahb_freq.0; 208 let ahb_freq = ahb_freq.0;
307 // Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock 209 // Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock
308 // frequency 210 // frequency
309 match self { 211 match self {
310 VoltageRange::Min1V8 => { 212 VoltageScale::Scale3 => {
311 if ahb_freq <= 16_000_000 { 213 if ahb_freq <= 16_000_000 {
312 Some(Latency::WS0) 214 Some(Latency::WS0)
313 } else if ahb_freq <= 32_000_000 { 215 } else if ahb_freq <= 32_000_000 {
@@ -328,7 +230,7 @@ impl VoltageRange {
328 None 230 None
329 } 231 }
330 } 232 }
331 VoltageRange::Min2V1 => { 233 VoltageScale::Scale2 => {
332 if ahb_freq <= 18_000_000 { 234 if ahb_freq <= 18_000_000 {
333 Some(Latency::WS0) 235 Some(Latency::WS0)
334 } else if ahb_freq <= 36_000_000 { 236 } else if ahb_freq <= 36_000_000 {
@@ -347,7 +249,7 @@ impl VoltageRange {
347 None 249 None
348 } 250 }
349 } 251 }
350 VoltageRange::Min2V4 => { 252 VoltageScale::Scale1 => {
351 if ahb_freq <= 24_000_000 { 253 if ahb_freq <= 24_000_000 {
352 Some(Latency::WS0) 254 Some(Latency::WS0)
353 } else if ahb_freq <= 48_000_000 { 255 } else if ahb_freq <= 48_000_000 {
@@ -362,7 +264,7 @@ impl VoltageRange {
362 None 264 None
363 } 265 }
364 } 266 }
365 VoltageRange::Min2V7 => { 267 VoltageScale::Scale0 => {
366 if ahb_freq <= 30_000_000 { 268 if ahb_freq <= 30_000_000 {
367 Some(Latency::WS0) 269 Some(Latency::WS0)
368 } else if ahb_freq <= 60_000_000 { 270 } else if ahb_freq <= 60_000_000 {
@@ -386,7 +288,7 @@ pub struct Config {
386 pub pll_mux: PLLSrc, 288 pub pll_mux: PLLSrc,
387 pub pll: PLLConfig, 289 pub pll: PLLConfig,
388 pub mux: ClockSrc, 290 pub mux: ClockSrc,
389 pub voltage: VoltageRange, 291 pub voltage: VoltageScale,
390 pub ahb_pre: AHBPrescaler, 292 pub ahb_pre: AHBPrescaler,
391 pub apb1_pre: APBPrescaler, 293 pub apb1_pre: APBPrescaler,
392 pub apb2_pre: APBPrescaler, 294 pub apb2_pre: APBPrescaler,
@@ -400,7 +302,7 @@ impl Default for Config {
400 hsi: true, 302 hsi: true,
401 pll_mux: PLLSrc::HSI, 303 pll_mux: PLLSrc::HSI,
402 pll: PLLConfig::default(), 304 pll: PLLConfig::default(),
403 voltage: VoltageRange::Min1V8, 305 voltage: VoltageScale::Scale3,
404 mux: ClockSrc::HSI, 306 mux: ClockSrc::HSI,
405 ahb_pre: AHBPrescaler::NotDivided, 307 ahb_pre: AHBPrescaler::NotDivided,
406 apb1_pre: APBPrescaler::NotDivided, 308 apb1_pre: APBPrescaler::NotDivided,
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index 2deee80d6..321270a70 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -264,6 +264,7 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
264} 264}
265 265
266#[inline] 266#[inline]
267#[allow(unused_variables)]
267fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre { 268fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre {
268 cfg_if::cfg_if! { 269 cfg_if::cfg_if! {
269 // Some chips do not have USB 270 // Some chips do not have USB
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
index b84470440..7aa9f0fd2 100644
--- a/embassy-stm32/src/rcc/f4.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -1,6 +1,6 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_hal_common::into_ref; 3use embassy_hal_internal::into_ref;
4use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre}; 4use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre};
5 5
6use super::sealed::RccPeripheral; 6use super::sealed::RccPeripheral;
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index 5e3a7911a..bf2d5199e 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -1,5 +1,6 @@
1pub use super::common::{AHBPrescaler, APBPrescaler};
1use crate::pac::flash::vals::Latency; 2use crate::pac::flash::vals::Latency;
2use crate::pac::rcc::vals::{self, Hpre, Hsidiv, Ppre, Sw}; 3use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw};
3use crate::pac::{FLASH, PWR, RCC}; 4use crate::pac::{FLASH, PWR, RCC};
4use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz; 6use crate::time::Hertz;
@@ -172,58 +173,6 @@ impl From<Pllr> for u32 {
172 } 173 }
173} 174}
174 175
175/// AHB prescaler
176#[derive(Clone, Copy, PartialEq)]
177pub enum AHBPrescaler {
178 NotDivided,
179 Div2,
180 Div4,
181 Div8,
182 Div16,
183 Div64,
184 Div128,
185 Div256,
186 Div512,
187}
188
189/// APB prescaler
190#[derive(Clone, Copy)]
191pub enum APBPrescaler {
192 NotDivided,
193 Div2,
194 Div4,
195 Div8,
196 Div16,
197}
198
199impl Into<Ppre> for APBPrescaler {
200 fn into(self) -> Ppre {
201 match self {
202 APBPrescaler::NotDivided => Ppre::DIV1,
203 APBPrescaler::Div2 => Ppre::DIV2,
204 APBPrescaler::Div4 => Ppre::DIV4,
205 APBPrescaler::Div8 => Ppre::DIV8,
206 APBPrescaler::Div16 => Ppre::DIV16,
207 }
208 }
209}
210
211impl Into<Hpre> for AHBPrescaler {
212 fn into(self) -> Hpre {
213 match self {
214 AHBPrescaler::NotDivided => Hpre::DIV1,
215 AHBPrescaler::Div2 => Hpre::DIV2,
216 AHBPrescaler::Div4 => Hpre::DIV4,
217 AHBPrescaler::Div8 => Hpre::DIV8,
218 AHBPrescaler::Div16 => Hpre::DIV16,
219 AHBPrescaler::Div64 => Hpre::DIV64,
220 AHBPrescaler::Div128 => Hpre::DIV128,
221 AHBPrescaler::Div256 => Hpre::DIV256,
222 AHBPrescaler::Div512 => Hpre::DIV512,
223 }
224 }
225}
226
227/// Clocks configutation 176/// Clocks configutation
228pub struct Config { 177pub struct Config {
229 pub mux: ClockSrc, 178 pub mux: ClockSrc,
@@ -425,25 +374,14 @@ pub(crate) unsafe fn init(config: Config) {
425 FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); 374 FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
426 } 375 }
427 376
428 let ahb_div = match config.ahb_pre { 377 let ahb_freq = Hertz(sys_clk) / config.ahb_pre;
429 AHBPrescaler::NotDivided => 1,
430 AHBPrescaler::Div2 => 2,
431 AHBPrescaler::Div4 => 4,
432 AHBPrescaler::Div8 => 8,
433 AHBPrescaler::Div16 => 16,
434 AHBPrescaler::Div64 => 64,
435 AHBPrescaler::Div128 => 128,
436 AHBPrescaler::Div256 => 256,
437 AHBPrescaler::Div512 => 512,
438 };
439 let ahb_freq = sys_clk / ahb_div;
440 378
441 let (apb_freq, apb_tim_freq) = match config.apb_pre { 379 let (apb_freq, apb_tim_freq) = match config.apb_pre {
442 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 380 APBPrescaler::NotDivided => (ahb_freq.0, ahb_freq.0),
443 pre => { 381 pre => {
444 let pre: Ppre = pre.into(); 382 let pre: Ppre = pre.into();
445 let pre: u8 = 1 << (pre.to_bits() - 3); 383 let pre: u8 = 1 << (pre.to_bits() - 3);
446 let freq = ahb_freq / pre as u32; 384 let freq = ahb_freq.0 / pre as u32;
447 (freq, freq * 2) 385 (freq, freq * 2)
448 } 386 }
449 }; 387 };
@@ -455,7 +393,7 @@ pub(crate) unsafe fn init(config: Config) {
455 393
456 set_freqs(Clocks { 394 set_freqs(Clocks {
457 sys: Hertz(sys_clk), 395 sys: Hertz(sys_clk),
458 ahb1: Hertz(ahb_freq), 396 ahb1: ahb_freq,
459 apb1: Hertz(apb_freq), 397 apb1: Hertz(apb_freq),
460 apb1_tim: Hertz(apb_tim_freq), 398 apb1_tim: Hertz(apb_tim_freq),
461 }); 399 });
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs
index ff8f97541..dff04023e 100644
--- a/embassy-stm32/src/rcc/g4.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -2,6 +2,7 @@ use stm32_metapac::flash::vals::Latency;
2use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; 2use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw};
3use stm32_metapac::FLASH; 3use stm32_metapac::FLASH;
4 4
5pub use super::common::{AHBPrescaler, APBPrescaler};
5use crate::pac::{PWR, RCC}; 6use crate::pac::{PWR, RCC};
6use crate::rcc::sealed::RccPeripheral; 7use crate::rcc::sealed::RccPeripheral;
7use crate::rcc::{set_freqs, Clocks}; 8use crate::rcc::{set_freqs, Clocks};
@@ -21,30 +22,6 @@ pub enum ClockSrc {
21 PLL, 22 PLL,
22} 23}
23 24
24/// AHB prescaler
25#[derive(Clone, Copy, PartialEq)]
26pub enum AHBPrescaler {
27 NotDivided,
28 Div2,
29 Div4,
30 Div8,
31 Div16,
32 Div64,
33 Div128,
34 Div256,
35 Div512,
36}
37
38/// APB prescaler
39#[derive(Clone, Copy)]
40pub enum APBPrescaler {
41 NotDivided,
42 Div2,
43 Div4,
44 Div8,
45 Div16,
46}
47
48/// PLL clock input source 25/// PLL clock input source
49#[derive(Clone, Copy, Debug)] 26#[derive(Clone, Copy, Debug)]
50pub enum PllSrc { 27pub enum PllSrc {
diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs
index 7e2f75ab7..2e72b1931 100644
--- a/embassy-stm32/src/rcc/h5.rs
+++ b/embassy-stm32/src/rcc/h5.rs
@@ -1,6 +1,6 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use stm32_metapac::rcc::vals::{Hpre, Ppre, Timpre}; 3use stm32_metapac::rcc::vals::Timpre;
4 4
5use crate::pac::pwr::vals::Vos; 5use crate::pac::pwr::vals::Vos;
6use crate::pac::rcc::vals::{Hseext, Hsidiv, Mco1, Mco2, Pllrge, Pllsrc, Pllvcosel, Sw}; 6use crate::pac::rcc::vals::{Hseext, Hsidiv, Mco1, Mco2, Pllrge, Pllsrc, Pllvcosel, Sw};
@@ -26,21 +26,7 @@ const VCO_MAX: u32 = 420_000_000;
26const VCO_WIDE_MIN: u32 = 128_000_000; 26const VCO_WIDE_MIN: u32 = 128_000_000;
27const VCO_WIDE_MAX: u32 = 560_000_000; 27const VCO_WIDE_MAX: u32 = 560_000_000;
28 28
29/// Voltage Scale 29pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale};
30///
31/// Represents the voltage range feeding the CPU core. The maximum core
32/// clock frequency depends on this value.
33#[derive(Copy, Clone, PartialEq)]
34pub enum VoltageScale {
35 /// VOS 0 range VCORE 1.30V - 1.40V
36 Scale0,
37 /// VOS 1 range VCORE 1.15V - 1.26V
38 Scale1,
39 /// VOS 2 range VCORE 1.05V - 1.15V
40 Scale2,
41 /// VOS 3 range VCORE 0.95V - 1.05V
42 Scale3,
43}
44 30
45pub enum HseMode { 31pub enum HseMode {
46 /// crystal/ceramic oscillator (HSEBYP=0) 32 /// crystal/ceramic oscillator (HSEBYP=0)
@@ -105,57 +91,7 @@ pub struct Pll {
105 pub divr: Option<u16>, 91 pub divr: Option<u16>,
106} 92}
107 93
108/// AHB prescaler
109#[derive(Clone, Copy, PartialEq)]
110pub enum AHBPrescaler {
111 NotDivided,
112 Div2,
113 Div4,
114 Div8,
115 Div16,
116 Div64,
117 Div128,
118 Div256,
119 Div512,
120}
121
122impl AHBPrescaler {
123 fn div(&self, clk: Hertz) -> Hertz {
124 match self {
125 Self::NotDivided => clk,
126 Self::Div2 => clk / 2u32,
127 Self::Div4 => clk / 4u32,
128 Self::Div8 => clk / 8u32,
129 Self::Div16 => clk / 16u32,
130 Self::Div64 => clk / 64u32,
131 Self::Div128 => clk / 128u32,
132 Self::Div256 => clk / 256u32,
133 Self::Div512 => clk / 512u32,
134 }
135 }
136}
137
138/// APB prescaler
139#[derive(Clone, Copy)]
140pub enum APBPrescaler {
141 NotDivided,
142 Div2,
143 Div4,
144 Div8,
145 Div16,
146}
147
148impl APBPrescaler { 94impl APBPrescaler {
149 fn div(&self, clk: Hertz) -> Hertz {
150 match self {
151 Self::NotDivided => clk,
152 Self::Div2 => clk / 2u32,
153 Self::Div4 => clk / 4u32,
154 Self::Div8 => clk / 8u32,
155 Self::Div16 => clk / 16u32,
156 }
157 }
158
159 fn div_tim(&self, clk: Hertz, tim: TimerPrescaler) -> Hertz { 95 fn div_tim(&self, clk: Hertz, tim: TimerPrescaler) -> Hertz {
160 match (tim, self) { 96 match (tim, self) {
161 // The timers kernel clock is equal to rcc_hclk1 if PPRE1 or PPRE2 corresponds to a 97 // The timers kernel clock is equal to rcc_hclk1 if PPRE1 or PPRE2 corresponds to a
@@ -193,34 +129,6 @@ impl From<TimerPrescaler> for Timpre {
193 } 129 }
194} 130}
195 131
196impl From<APBPrescaler> for Ppre {
197 fn from(val: APBPrescaler) -> Ppre {
198 match val {
199 APBPrescaler::NotDivided => Ppre::DIV1,
200 APBPrescaler::Div2 => Ppre::DIV2,
201 APBPrescaler::Div4 => Ppre::DIV4,
202 APBPrescaler::Div8 => Ppre::DIV8,
203 APBPrescaler::Div16 => Ppre::DIV16,
204 }
205 }
206}
207
208impl From<AHBPrescaler> for Hpre {
209 fn from(val: AHBPrescaler) -> Hpre {
210 match val {
211 AHBPrescaler::NotDivided => Hpre::DIV1,
212 AHBPrescaler::Div2 => Hpre::DIV2,
213 AHBPrescaler::Div4 => Hpre::DIV4,
214 AHBPrescaler::Div8 => Hpre::DIV8,
215 AHBPrescaler::Div16 => Hpre::DIV16,
216 AHBPrescaler::Div64 => Hpre::DIV64,
217 AHBPrescaler::Div128 => Hpre::DIV128,
218 AHBPrescaler::Div256 => Hpre::DIV256,
219 AHBPrescaler::Div512 => Hpre::DIV512,
220 }
221 }
222}
223
224/// Configuration of the core clocks 132/// Configuration of the core clocks
225#[non_exhaustive] 133#[non_exhaustive]
226pub struct Config { 134pub struct Config {
@@ -406,13 +314,13 @@ pub(crate) unsafe fn init(config: Config) {
406 }; 314 };
407 assert!(sys <= max_clk); 315 assert!(sys <= max_clk);
408 316
409 let hclk = config.ahb_pre.div(sys); 317 let hclk = sys / config.ahb_pre;
410 318
411 let apb1 = config.apb1_pre.div(hclk); 319 let apb1 = hclk / config.apb1_pre;
412 let apb1_tim = config.apb1_pre.div_tim(hclk, config.timer_prescaler); 320 let apb1_tim = config.apb1_pre.div_tim(hclk, config.timer_prescaler);
413 let apb2 = config.apb2_pre.div(hclk); 321 let apb2 = hclk / config.apb2_pre;
414 let apb2_tim = config.apb2_pre.div_tim(hclk, config.timer_prescaler); 322 let apb2_tim = config.apb2_pre.div_tim(hclk, config.timer_prescaler);
415 let apb3 = config.apb3_pre.div(hclk); 323 let apb3 = hclk / config.apb3_pre;
416 324
417 flash_setup(hclk, config.voltage_scale); 325 flash_setup(hclk, config.voltage_scale);
418 326
diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs
index 7e5cd0d1a..0788b0640 100644
--- a/embassy-stm32/src/rcc/h7.rs
+++ b/embassy-stm32/src/rcc/h7.rs
@@ -1,6 +1,6 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_hal_common::into_ref; 3use embassy_hal_internal::into_ref;
4pub use pll::PllConfig; 4pub use pll::PllConfig;
5use stm32_metapac::rcc::vals::{Mco1, Mco2}; 5use stm32_metapac::rcc::vals::{Mco1, Mco2};
6 6
@@ -24,21 +24,7 @@ pub const HSI48_FREQ: Hertz = Hertz(48_000_000);
24/// LSI speed 24/// LSI speed
25pub const LSI_FREQ: Hertz = Hertz(32_000); 25pub const LSI_FREQ: Hertz = Hertz(32_000);
26 26
27/// Voltage Scale 27pub use super::common::VoltageScale;
28///
29/// Represents the voltage range feeding the CPU core. The maximum core
30/// clock frequency depends on this value.
31#[derive(Copy, Clone, PartialEq)]
32pub enum VoltageScale {
33 /// VOS 0 range VCORE 1.26V - 1.40V
34 Scale0,
35 /// VOS 1 range VCORE 1.15V - 1.26V
36 Scale1,
37 /// VOS 2 range VCORE 1.05V - 1.15V
38 Scale2,
39 /// VOS 3 range VCORE 0.95V - 1.05V
40 Scale3,
41}
42 28
43#[derive(Clone, Copy)] 29#[derive(Clone, Copy)]
44pub enum AdcClockSource { 30pub enum AdcClockSource {
diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs
index 46a528e31..46b58ca7c 100644
--- a/embassy-stm32/src/rcc/l0.rs
+++ b/embassy-stm32/src/rcc/l0.rs
@@ -1,3 +1,4 @@
1pub use super::common::{AHBPrescaler, APBPrescaler};
1use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; 2use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
2use crate::pac::RCC; 3use crate::pac::RCC;
3#[cfg(crs)] 4#[cfg(crs)]
@@ -70,30 +71,6 @@ pub enum PLLMul {
70 Mul48, 71 Mul48,
71} 72}
72 73
73/// AHB prescaler
74#[derive(Clone, Copy, PartialEq)]
75pub enum AHBPrescaler {
76 NotDivided,
77 Div2,
78 Div4,
79 Div8,
80 Div16,
81 Div64,
82 Div128,
83 Div256,
84 Div512,
85}
86
87/// APB prescaler
88#[derive(Clone, Copy)]
89pub enum APBPrescaler {
90 NotDivided,
91 Div2,
92 Div4,
93 Div8,
94 Div16,
95}
96
97/// PLL clock input source 74/// PLL clock input source
98#[derive(Clone, Copy)] 75#[derive(Clone, Copy)]
99pub enum PLLSource { 76pub enum PLLSource {
@@ -136,34 +113,6 @@ impl From<PLLSource> for Pllsrc {
136 } 113 }
137} 114}
138 115
139impl From<APBPrescaler> for Ppre {
140 fn from(val: APBPrescaler) -> Ppre {
141 match val {
142 APBPrescaler::NotDivided => Ppre::DIV1,
143 APBPrescaler::Div2 => Ppre::DIV2,
144 APBPrescaler::Div4 => Ppre::DIV4,
145 APBPrescaler::Div8 => Ppre::DIV8,
146 APBPrescaler::Div16 => Ppre::DIV16,
147 }
148 }
149}
150
151impl From<AHBPrescaler> for Hpre {
152 fn from(val: AHBPrescaler) -> Hpre {
153 match val {
154 AHBPrescaler::NotDivided => Hpre::DIV1,
155 AHBPrescaler::Div2 => Hpre::DIV2,
156 AHBPrescaler::Div4 => Hpre::DIV4,
157 AHBPrescaler::Div8 => Hpre::DIV8,
158 AHBPrescaler::Div16 => Hpre::DIV16,
159 AHBPrescaler::Div64 => Hpre::DIV64,
160 AHBPrescaler::Div128 => Hpre::DIV128,
161 AHBPrescaler::Div256 => Hpre::DIV256,
162 AHBPrescaler::Div512 => Hpre::DIV512,
163 }
164 }
165}
166
167impl From<MSIRange> for Msirange { 116impl From<MSIRange> for Msirange {
168 fn from(val: MSIRange) -> Msirange { 117 fn from(val: MSIRange) -> Msirange {
169 match val { 118 match val {
diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs
index 59a6eac8f..bdfc5b87a 100644
--- a/embassy-stm32/src/rcc/l1.rs
+++ b/embassy-stm32/src/rcc/l1.rs
@@ -1,3 +1,4 @@
1pub use super::common::{AHBPrescaler, APBPrescaler};
1use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; 2use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
2use crate::pac::{FLASH, RCC}; 3use crate::pac::{FLASH, RCC};
3use crate::rcc::{set_freqs, Clocks}; 4use crate::rcc::{set_freqs, Clocks};
@@ -68,30 +69,6 @@ pub enum PLLMul {
68 Mul48, 69 Mul48,
69} 70}
70 71
71/// AHB prescaler
72#[derive(Clone, Copy, PartialEq)]
73pub enum AHBPrescaler {
74 NotDivided,
75 Div2,
76 Div4,
77 Div8,
78 Div16,
79 Div64,
80 Div128,
81 Div256,
82 Div512,
83}
84
85/// APB prescaler
86#[derive(Clone, Copy)]
87pub enum APBPrescaler {
88 NotDivided,
89 Div2,
90 Div4,
91 Div8,
92 Div16,
93}
94
95/// PLL clock input source 72/// PLL clock input source
96#[derive(Clone, Copy)] 73#[derive(Clone, Copy)]
97pub enum PLLSource { 74pub enum PLLSource {
@@ -134,34 +111,6 @@ impl From<PLLSource> for Pllsrc {
134 } 111 }
135} 112}
136 113
137impl From<APBPrescaler> for Ppre {
138 fn from(val: APBPrescaler) -> Ppre {
139 match val {
140 APBPrescaler::NotDivided => Ppre::DIV1,
141 APBPrescaler::Div2 => Ppre::DIV2,
142 APBPrescaler::Div4 => Ppre::DIV4,
143 APBPrescaler::Div8 => Ppre::DIV8,
144 APBPrescaler::Div16 => Ppre::DIV16,
145 }
146 }
147}
148
149impl From<AHBPrescaler> for Hpre {
150 fn from(val: AHBPrescaler) -> Hpre {
151 match val {
152 AHBPrescaler::NotDivided => Hpre::DIV1,
153 AHBPrescaler::Div2 => Hpre::DIV2,
154 AHBPrescaler::Div4 => Hpre::DIV4,
155 AHBPrescaler::Div8 => Hpre::DIV8,
156 AHBPrescaler::Div16 => Hpre::DIV16,
157 AHBPrescaler::Div64 => Hpre::DIV64,
158 AHBPrescaler::Div128 => Hpre::DIV128,
159 AHBPrescaler::Div256 => Hpre::DIV256,
160 AHBPrescaler::Div512 => Hpre::DIV512,
161 }
162 }
163}
164
165impl From<MSIRange> for Msirange { 114impl From<MSIRange> for Msirange {
166 fn from(val: MSIRange) -> Msirange { 115 fn from(val: MSIRange) -> Msirange {
167 match val { 116 match val {
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs
index 8a9b4adbf..237b7bc91 100644
--- a/embassy-stm32/src/rcc/l4.rs
+++ b/embassy-stm32/src/rcc/l4.rs
@@ -1,9 +1,10 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_hal_common::into_ref; 3use embassy_hal_internal::into_ref;
4use stm32_metapac::rcc::regs::Cfgr; 4use stm32_metapac::rcc::regs::Cfgr;
5use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel}; 5use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel};
6 6
7pub use super::common::{AHBPrescaler, APBPrescaler};
7use crate::gpio::sealed::AFType; 8use crate::gpio::sealed::AFType;
8use crate::gpio::Speed; 9use crate::gpio::Speed;
9use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; 10use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
@@ -78,30 +79,6 @@ pub enum PLLDiv {
78 Div4, 79 Div4,
79} 80}
80 81
81/// AHB prescaler
82#[derive(Clone, Copy, PartialEq)]
83pub enum AHBPrescaler {
84 NotDivided,
85 Div2,
86 Div4,
87 Div8,
88 Div16,
89 Div64,
90 Div128,
91 Div256,
92 Div512,
93}
94
95/// APB prescaler
96#[derive(Clone, Copy)]
97pub enum APBPrescaler {
98 NotDivided,
99 Div2,
100 Div4,
101 Div8,
102 Div16,
103}
104
105/// PLL clock input source 82/// PLL clock input source
106#[derive(Clone, Copy)] 83#[derive(Clone, Copy)]
107pub enum PLLSource { 84pub enum PLLSource {
@@ -209,34 +186,6 @@ impl From<PLLSource> for Pllsrc {
209 } 186 }
210} 187}
211 188
212impl From<APBPrescaler> for Ppre {
213 fn from(val: APBPrescaler) -> Ppre {
214 match val {
215 APBPrescaler::NotDivided => Ppre::DIV1,
216 APBPrescaler::Div2 => Ppre::DIV2,
217 APBPrescaler::Div4 => Ppre::DIV4,
218 APBPrescaler::Div8 => Ppre::DIV8,
219 APBPrescaler::Div16 => Ppre::DIV16,
220 }
221 }
222}
223
224impl From<AHBPrescaler> for Hpre {
225 fn from(val: AHBPrescaler) -> Hpre {
226 match val {
227 AHBPrescaler::NotDivided => Hpre::DIV1,
228 AHBPrescaler::Div2 => Hpre::DIV2,
229 AHBPrescaler::Div4 => Hpre::DIV4,
230 AHBPrescaler::Div8 => Hpre::DIV8,
231 AHBPrescaler::Div16 => Hpre::DIV16,
232 AHBPrescaler::Div64 => Hpre::DIV64,
233 AHBPrescaler::Div128 => Hpre::DIV128,
234 AHBPrescaler::Div256 => Hpre::DIV256,
235 AHBPrescaler::Div512 => Hpre::DIV512,
236 }
237 }
238}
239
240impl From<MSIRange> for Msirange { 189impl From<MSIRange> for Msirange {
241 fn from(val: MSIRange) -> Msirange { 190 fn from(val: MSIRange) -> Msirange {
242 match val { 191 match val {
diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs
index 16da65d5e..a85e14889 100644
--- a/embassy-stm32/src/rcc/l5.rs
+++ b/embassy-stm32/src/rcc/l5.rs
@@ -1,5 +1,6 @@
1use stm32_metapac::PWR; 1use stm32_metapac::PWR;
2 2
3pub use super::common::{AHBPrescaler, APBPrescaler};
3use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; 4use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
4use crate::pac::{FLASH, RCC}; 5use crate::pac::{FLASH, RCC};
5use crate::rcc::{set_freqs, Clocks}; 6use crate::rcc::{set_freqs, Clocks};
@@ -71,30 +72,6 @@ pub enum PLLDiv {
71 Div4, 72 Div4,
72} 73}
73 74
74/// AHB prescaler
75#[derive(Clone, Copy, PartialEq)]
76pub enum AHBPrescaler {
77 NotDivided,
78 Div2,
79 Div4,
80 Div8,
81 Div16,
82 Div64,
83 Div128,
84 Div256,
85 Div512,
86}
87
88/// APB prescaler
89#[derive(Clone, Copy)]
90pub enum APBPrescaler {
91 NotDivided,
92 Div2,
93 Div4,
94 Div8,
95 Div16,
96}
97
98/// PLL clock input source 75/// PLL clock input source
99#[derive(Clone, Copy)] 76#[derive(Clone, Copy)]
100pub enum PLLSource { 77pub enum PLLSource {
@@ -202,34 +179,6 @@ impl From<PLLSource> for Pllsrc {
202 } 179 }
203} 180}
204 181
205impl From<APBPrescaler> for Ppre {
206 fn from(val: APBPrescaler) -> Ppre {
207 match val {
208 APBPrescaler::NotDivided => Ppre::DIV1,
209 APBPrescaler::Div2 => Ppre::DIV2,
210 APBPrescaler::Div4 => Ppre::DIV4,
211 APBPrescaler::Div8 => Ppre::DIV8,
212 APBPrescaler::Div16 => Ppre::DIV16,
213 }
214 }
215}
216
217impl From<AHBPrescaler> for Hpre {
218 fn from(val: AHBPrescaler) -> Hpre {
219 match val {
220 AHBPrescaler::NotDivided => Hpre::DIV1,
221 AHBPrescaler::Div2 => Hpre::DIV2,
222 AHBPrescaler::Div4 => Hpre::DIV4,
223 AHBPrescaler::Div8 => Hpre::DIV8,
224 AHBPrescaler::Div16 => Hpre::DIV16,
225 AHBPrescaler::Div64 => Hpre::DIV64,
226 AHBPrescaler::Div128 => Hpre::DIV128,
227 AHBPrescaler::Div256 => Hpre::DIV256,
228 AHBPrescaler::Div512 => Hpre::DIV512,
229 }
230 }
231}
232
233impl From<MSIRange> for Msirange { 182impl From<MSIRange> for Msirange {
234 fn from(val: MSIRange) -> Msirange { 183 fn from(val: MSIRange) -> Msirange {
235 match val { 184 match val {
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 4ae65d3e6..5c69037ed 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -1,5 +1,7 @@
1#![macro_use] 1#![macro_use]
2 2
3pub mod common;
4
3use core::mem::MaybeUninit; 5use core::mem::MaybeUninit;
4 6
5use crate::time::Hertz; 7use crate::time::Hertz;
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index cfc07f069..b5feeb0c4 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -1,5 +1,6 @@
1use stm32_metapac::rcc::vals::{Hpre, Msirange, Msirgsel, Pllm, Pllsrc, Ppre, Sw}; 1use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw};
2 2
3pub use super::common::{AHBPrescaler, APBPrescaler};
3use crate::pac::{FLASH, RCC}; 4use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz; 6use crate::time::Hertz;
@@ -10,19 +11,7 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000);
10/// LSI speed 11/// LSI speed
11pub const LSI_FREQ: Hertz = Hertz(32_000); 12pub const LSI_FREQ: Hertz = Hertz(32_000);
12 13
13/// Voltage Scale 14pub use super::common::VoltageScale;
14///
15/// Represents the voltage range feeding the CPU core. The maximum core
16/// clock frequency depends on this value.
17#[derive(Copy, Clone, PartialEq)]
18pub enum VoltageScale {
19 // Highest frequency
20 Range1,
21 Range2,
22 Range3,
23 // Lowest power
24 Range4,
25}
26 15
27#[derive(Copy, Clone)] 16#[derive(Copy, Clone)]
28pub enum ClockSrc { 17pub enum ClockSrc {
@@ -130,36 +119,6 @@ impl Into<Pllm> for PllM {
130 } 119 }
131} 120}
132 121
133/// AHB prescaler
134#[derive(Clone, Copy, PartialEq)]
135pub enum AHBPrescaler {
136 NotDivided,
137 Div2,
138 Div4,
139 Div8,
140 Div16,
141 Div64,
142 Div128,
143 Div256,
144 Div512,
145}
146
147impl Into<Hpre> for AHBPrescaler {
148 fn into(self) -> Hpre {
149 match self {
150 AHBPrescaler::NotDivided => Hpre::NONE,
151 AHBPrescaler::Div2 => Hpre::DIV2,
152 AHBPrescaler::Div4 => Hpre::DIV4,
153 AHBPrescaler::Div8 => Hpre::DIV8,
154 AHBPrescaler::Div16 => Hpre::DIV16,
155 AHBPrescaler::Div64 => Hpre::DIV64,
156 AHBPrescaler::Div128 => Hpre::DIV128,
157 AHBPrescaler::Div256 => Hpre::DIV256,
158 AHBPrescaler::Div512 => Hpre::DIV512,
159 }
160 }
161}
162
163impl Into<u8> for AHBPrescaler { 122impl Into<u8> for AHBPrescaler {
164 fn into(self) -> u8 { 123 fn into(self) -> u8 {
165 match self { 124 match self {
@@ -182,28 +141,6 @@ impl Default for AHBPrescaler {
182 } 141 }
183} 142}
184 143
185/// APB prescaler
186#[derive(Clone, Copy)]
187pub enum APBPrescaler {
188 NotDivided,
189 Div2,
190 Div4,
191 Div8,
192 Div16,
193}
194
195impl Into<Ppre> for APBPrescaler {
196 fn into(self) -> Ppre {
197 match self {
198 APBPrescaler::NotDivided => Ppre::NONE,
199 APBPrescaler::Div2 => Ppre::DIV2,
200 APBPrescaler::Div4 => Ppre::DIV4,
201 APBPrescaler::Div8 => Ppre::DIV8,
202 APBPrescaler::Div16 => Ppre::DIV16,
203 }
204 }
205}
206
207impl Default for APBPrescaler { 144impl Default for APBPrescaler {
208 fn default() -> Self { 145 fn default() -> Self {
209 APBPrescaler::NotDivided 146 APBPrescaler::NotDivided
@@ -389,12 +326,12 @@ pub(crate) unsafe fn init(config: Config) {
389 } 326 }
390 327
391 // TODO make configurable 328 // TODO make configurable
392 let power_vos = VoltageScale::Range4; 329 let power_vos = VoltageScale::Scale3;
393 330
394 // states and programming delay 331 // states and programming delay
395 let wait_states = match power_vos { 332 let wait_states = match power_vos {
396 // VOS 0 range VCORE 1.26V - 1.40V 333 // VOS 0 range VCORE 1.26V - 1.40V
397 VoltageScale::Range1 => { 334 VoltageScale::Scale0 => {
398 if sys_clk < 32_000_000 { 335 if sys_clk < 32_000_000 {
399 0 336 0
400 } else if sys_clk < 64_000_000 { 337 } else if sys_clk < 64_000_000 {
@@ -408,7 +345,7 @@ pub(crate) unsafe fn init(config: Config) {
408 } 345 }
409 } 346 }
410 // VOS 1 range VCORE 1.15V - 1.26V 347 // VOS 1 range VCORE 1.15V - 1.26V
411 VoltageScale::Range2 => { 348 VoltageScale::Scale1 => {
412 if sys_clk < 30_000_000 { 349 if sys_clk < 30_000_000 {
413 0 350 0
414 } else if sys_clk < 60_000_000 { 351 } else if sys_clk < 60_000_000 {
@@ -420,7 +357,7 @@ pub(crate) unsafe fn init(config: Config) {
420 } 357 }
421 } 358 }
422 // VOS 2 range VCORE 1.05V - 1.15V 359 // VOS 2 range VCORE 1.05V - 1.15V
423 VoltageScale::Range3 => { 360 VoltageScale::Scale2 => {
424 if sys_clk < 24_000_000 { 361 if sys_clk < 24_000_000 {
425 0 362 0
426 } else if sys_clk < 48_000_000 { 363 } else if sys_clk < 48_000_000 {
@@ -430,7 +367,7 @@ pub(crate) unsafe fn init(config: Config) {
430 } 367 }
431 } 368 }
432 // VOS 3 range VCORE 0.95V - 1.05V 369 // VOS 3 range VCORE 0.95V - 1.05V
433 VoltageScale::Range4 => { 370 VoltageScale::Scale3 => {
434 if sys_clk < 12_000_000 { 371 if sys_clk < 12_000_000 {
435 0 372 0
436 } else { 373 } else {
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs
index 4322b950a..21aacec58 100644
--- a/embassy-stm32/src/rcc/wb.rs
+++ b/embassy-stm32/src/rcc/wb.rs
@@ -1,3 +1,4 @@
1pub use super::common::{AHBPrescaler, APBPrescaler};
1use crate::rcc::Clocks; 2use crate::rcc::Clocks;
2use crate::time::{khz, mhz, Hertz}; 3use crate::time::{khz, mhz, Hertz};
3 4
@@ -102,68 +103,6 @@ pub struct Pll {
102 pub divr: Option<u16>, 103 pub divr: Option<u16>,
103} 104}
104 105
105/// AHB prescaler
106#[derive(Clone, Copy, PartialEq)]
107pub enum AHBPrescaler {
108 NotDivided,
109 Div2,
110 Div3,
111 Div4,
112 Div5,
113 Div6,
114 Div8,
115 Div10,
116 Div16,
117 Div32,
118 Div64,
119 Div128,
120 Div256,
121 Div512,
122}
123
124/// APB prescaler
125#[derive(Clone, Copy)]
126pub enum APBPrescaler {
127 NotDivided,
128 Div2,
129 Div4,
130 Div8,
131 Div16,
132}
133
134impl Into<u8> for APBPrescaler {
135 fn into(self) -> u8 {
136 match self {
137 APBPrescaler::NotDivided => 1,
138 APBPrescaler::Div2 => 0x04,
139 APBPrescaler::Div4 => 0x05,
140 APBPrescaler::Div8 => 0x06,
141 APBPrescaler::Div16 => 0x07,
142 }
143 }
144}
145
146impl Into<u8> for AHBPrescaler {
147 fn into(self) -> u8 {
148 match self {
149 AHBPrescaler::NotDivided => 0x0,
150 AHBPrescaler::Div2 => 0x08,
151 AHBPrescaler::Div3 => 0x01,
152 AHBPrescaler::Div4 => 0x09,
153 AHBPrescaler::Div5 => 0x02,
154 AHBPrescaler::Div6 => 0x05,
155 AHBPrescaler::Div8 => 0x0a,
156 AHBPrescaler::Div10 => 0x06,
157 AHBPrescaler::Div16 => 0x0b,
158 AHBPrescaler::Div32 => 0x07,
159 AHBPrescaler::Div64 => 0x0c,
160 AHBPrescaler::Div128 => 0x0d,
161 AHBPrescaler::Div256 => 0x0e,
162 AHBPrescaler::Div512 => 0x0f,
163 }
164 }
165}
166
167/// Clocks configutation 106/// Clocks configutation
168pub struct Config { 107pub struct Config {
169 pub hse: Option<Hse>, 108 pub hse: Option<Hse>,
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs
index 6b69bb1cb..ea6e8dde6 100644
--- a/embassy-stm32/src/rcc/wl.rs
+++ b/embassy-stm32/src/rcc/wl.rs
@@ -1,3 +1,4 @@
1pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale};
1use crate::pac::pwr::vals::Dbp; 2use crate::pac::pwr::vals::Dbp;
2use crate::pac::{FLASH, PWR, RCC}; 3use crate::pac::{FLASH, PWR, RCC};
3use crate::rcc::{set_freqs, Clocks}; 4use crate::rcc::{set_freqs, Clocks};
@@ -73,9 +74,9 @@ impl MSIRange {
73 74
74 fn vos(&self) -> VoltageScale { 75 fn vos(&self) -> VoltageScale {
75 if self > &MSIRange::Range8 { 76 if self > &MSIRange::Range8 {
76 VoltageScale::Range1 77 VoltageScale::Scale0
77 } else { 78 } else {
78 VoltageScale::Range2 79 VoltageScale::Scale1
79 } 80 }
80 } 81 }
81} 82}
@@ -105,78 +106,6 @@ impl Into<u8> for MSIRange {
105 } 106 }
106} 107}
107 108
108/// Voltage Scale
109///
110/// Represents the voltage range feeding the CPU core. The maximum core
111/// clock frequency depends on this value.
112#[derive(Copy, Clone, PartialEq)]
113pub enum VoltageScale {
114 Range1,
115 Range2,
116}
117
118/// AHB prescaler
119#[derive(Clone, Copy, PartialEq)]
120pub enum AHBPrescaler {
121 NotDivided,
122 Div2,
123 Div3,
124 Div4,
125 Div5,
126 Div6,
127 Div8,
128 Div10,
129 Div16,
130 Div32,
131 Div64,
132 Div128,
133 Div256,
134 Div512,
135}
136
137/// APB prescaler
138#[derive(Clone, Copy)]
139pub enum APBPrescaler {
140 NotDivided,
141 Div2,
142 Div4,
143 Div8,
144 Div16,
145}
146
147impl Into<u8> for APBPrescaler {
148 fn into(self) -> u8 {
149 match self {
150 APBPrescaler::NotDivided => 1,
151 APBPrescaler::Div2 => 0x04,
152 APBPrescaler::Div4 => 0x05,
153 APBPrescaler::Div8 => 0x06,
154 APBPrescaler::Div16 => 0x07,
155 }
156 }
157}
158
159impl Into<u8> for AHBPrescaler {
160 fn into(self) -> u8 {
161 match self {
162 AHBPrescaler::NotDivided => 0x0,
163 AHBPrescaler::Div2 => 0x08,
164 AHBPrescaler::Div3 => 0x01,
165 AHBPrescaler::Div4 => 0x09,
166 AHBPrescaler::Div5 => 0x02,
167 AHBPrescaler::Div6 => 0x05,
168 AHBPrescaler::Div8 => 0x0a,
169 AHBPrescaler::Div10 => 0x06,
170 AHBPrescaler::Div16 => 0x0b,
171 AHBPrescaler::Div32 => 0x07,
172 AHBPrescaler::Div64 => 0x0c,
173 AHBPrescaler::Div128 => 0x0d,
174 AHBPrescaler::Div256 => 0x0e,
175 AHBPrescaler::Div512 => 0x0f,
176 }
177 }
178}
179
180/// Clocks configutation 109/// Clocks configutation
181pub struct Config { 110pub struct Config {
182 pub mux: ClockSrc, 111 pub mux: ClockSrc,
@@ -220,8 +149,8 @@ pub enum Lsedrv {
220 149
221pub(crate) unsafe fn init(config: Config) { 150pub(crate) unsafe fn init(config: Config) {
222 let (sys_clk, sw, vos) = match config.mux { 151 let (sys_clk, sw, vos) = match config.mux {
223 ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2), 152 ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Scale1),
224 ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::Range1), 153 ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::Scale0),
225 ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()), 154 ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()),
226 }; 155 };
227 156
@@ -266,12 +195,12 @@ pub(crate) unsafe fn init(config: Config) {
266 // Adjust flash latency 195 // Adjust flash latency
267 let flash_clk_src_freq: u32 = shd_ahb_freq; 196 let flash_clk_src_freq: u32 = shd_ahb_freq;
268 let ws = match vos { 197 let ws = match vos {
269 VoltageScale::Range1 => match flash_clk_src_freq { 198 VoltageScale::Scale0 => match flash_clk_src_freq {
270 0..=18_000_000 => 0b000, 199 0..=18_000_000 => 0b000,
271 18_000_001..=36_000_000 => 0b001, 200 18_000_001..=36_000_000 => 0b001,
272 _ => 0b010, 201 _ => 0b010,
273 }, 202 },
274 VoltageScale::Range2 => match flash_clk_src_freq { 203 VoltageScale::Scale1 => match flash_clk_src_freq {
275 0..=6_000_000 => 0b000, 204 0..=6_000_000 => 0b000,
276 6_000_001..=12_000_000 => 0b001, 205 6_000_001..=12_000_000 => 0b001,
277 _ => 0b010, 206 _ => 0b010,
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index b2faec53d..2a4978ec5 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -1,15 +1,17 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::future::poll_fn; 3use core::future::poll_fn;
4use core::marker::PhantomData;
4use core::task::Poll; 5use core::task::Poll;
5 6
6use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
8use rand_core::{CryptoRng, RngCore}; 9use rand_core::{CryptoRng, RngCore};
9 10
10use crate::{pac, peripherals, Peripheral}; 11use crate::interrupt::typelevel::Interrupt;
12use crate::{interrupt, pac, peripherals, Peripheral};
11 13
12pub(crate) static RNG_WAKER: AtomicWaker = AtomicWaker::new(); 14static RNG_WAKER: AtomicWaker = AtomicWaker::new();
13 15
14#[cfg_attr(feature = "defmt", derive(defmt::Format))] 16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub enum Error { 17pub enum Error {
@@ -17,68 +19,145 @@ pub enum Error {
17 ClockError, 19 ClockError,
18} 20}
19 21
22pub struct InterruptHandler<T: Instance> {
23 _phantom: PhantomData<T>,
24}
25
26impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
27 unsafe fn on_interrupt() {
28 let bits = T::regs().sr().read();
29 if bits.drdy() || bits.seis() || bits.ceis() {
30 T::regs().cr().modify(|reg| reg.set_ie(false));
31 RNG_WAKER.wake();
32 }
33 }
34}
35
20pub struct Rng<'d, T: Instance> { 36pub struct Rng<'d, T: Instance> {
21 _inner: PeripheralRef<'d, T>, 37 _inner: PeripheralRef<'d, T>,
22} 38}
23 39
24impl<'d, T: Instance> Rng<'d, T> { 40impl<'d, T: Instance> Rng<'d, T> {
25 pub fn new(inner: impl Peripheral<P = T> + 'd) -> Self { 41 pub fn new(
42 inner: impl Peripheral<P = T> + 'd,
43 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
44 ) -> Self {
26 T::enable(); 45 T::enable();
27 T::reset(); 46 T::reset();
28 into_ref!(inner); 47 into_ref!(inner);
29 let mut random = Self { _inner: inner }; 48 let mut random = Self { _inner: inner };
30 random.reset(); 49 random.reset();
50
51 T::Interrupt::unpend();
52 unsafe { T::Interrupt::enable() };
53
31 random 54 random
32 } 55 }
33 56
57 #[cfg(rng_v1)]
34 pub fn reset(&mut self) { 58 pub fn reset(&mut self) {
35 // rng_v2 locks up on seed error, needs reset 59 T::regs().cr().write(|reg| {
36 #[cfg(rng_v2)] 60 reg.set_rngen(false);
37 if T::regs().sr().read().seis() {
38 T::reset();
39 }
40 T::regs().cr().modify(|reg| {
41 reg.set_rngen(true);
42 reg.set_ie(true);
43 }); 61 });
44 T::regs().sr().modify(|reg| { 62 T::regs().sr().modify(|reg| {
45 reg.set_seis(false); 63 reg.set_seis(false);
46 reg.set_ceis(false); 64 reg.set_ceis(false);
47 }); 65 });
66 T::regs().cr().modify(|reg| {
67 reg.set_rngen(true);
68 });
48 // Reference manual says to discard the first. 69 // Reference manual says to discard the first.
49 let _ = self.next_u32(); 70 let _ = self.next_u32();
50 } 71 }
51 72
52 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 73 #[cfg(not(rng_v1))]
74 pub fn reset(&mut self) {
75 T::regs().cr().write(|reg| {
76 reg.set_rngen(false);
77 reg.set_condrst(true);
78 // set RNG config "A" according to reference manual
79 // this has to be written within the same write access as setting the CONDRST bit
80 reg.set_nistc(pac::rng::vals::Nistc::DEFAULT);
81 reg.set_rng_config1(pac::rng::vals::RngConfig1::CONFIGA);
82 reg.set_rng_config2(pac::rng::vals::RngConfig2::CONFIGA_B);
83 reg.set_rng_config3(pac::rng::vals::RngConfig3::CONFIGA);
84 reg.set_clkdiv(pac::rng::vals::Clkdiv::NODIV);
85 });
86 // wait for CONDRST to be set
87 while !T::regs().cr().read().condrst() {}
88 // magic number must be written immediately before every read or write access to HTCR
89 T::regs().htcr().write(|w| w.set_htcfg(pac::rng::vals::Htcfg::MAGIC));
90 // write recommended value according to reference manual
91 // note: HTCR can only be written during conditioning
92 T::regs()
93 .htcr()
94 .write(|w| w.set_htcfg(pac::rng::vals::Htcfg::RECOMMENDED));
95 // finish conditioning
53 T::regs().cr().modify(|reg| { 96 T::regs().cr().modify(|reg| {
54 reg.set_rngen(true); 97 reg.set_rngen(true);
98 reg.set_condrst(false);
55 }); 99 });
100 // wait for CONDRST to be reset
101 while T::regs().cr().read().condrst() {}
102 }
103
104 pub fn recover_seed_error(&mut self) -> () {
105 self.reset();
106 // reset should also clear the SEIS flag
107 if T::regs().sr().read().seis() {
108 warn!("recovering from seed error failed");
109 return;
110 }
111 // wait for SECS to be cleared by RNG
112 while T::regs().sr().read().secs() {}
113 }
56 114
115 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
57 for chunk in dest.chunks_mut(4) { 116 for chunk in dest.chunks_mut(4) {
58 poll_fn(|cx| { 117 let bits = T::regs().sr().read();
59 RNG_WAKER.register(cx.waker()); 118 if bits.seis() {
60 T::regs().cr().modify(|reg| { 119 // in case of noise-source or seed error we try to recover here
61 reg.set_ie(true); 120 // but we must not use the data in DR and we return an error
62 }); 121 // to leave retry-logic to the application
63 122 self.recover_seed_error();
64 let bits = T::regs().sr().read(); 123 return Err(Error::SeedError);
65 124 } else if bits.ceis() {
66 if bits.drdy() { 125 // clock error detected, DR could still be used but keep it safe,
67 Poll::Ready(Ok(())) 126 // clear the error and abort
68 } else if bits.seis() { 127 T::regs().sr().modify(|sr| sr.set_ceis(false));
69 self.reset(); 128 return Err(Error::ClockError);
70 Poll::Ready(Err(Error::SeedError)) 129 } else if bits.drdy() {
71 } else if bits.ceis() { 130 // DR can be read up to four times until the output buffer is empty
72 self.reset(); 131 // DRDY is cleared automatically when that happens
73 Poll::Ready(Err(Error::ClockError)) 132 let random_word = T::regs().dr().read();
74 } else { 133 // reference manual: always check if DR is zero
75 Poll::Pending 134 if random_word == 0 {
135 return Err(Error::SeedError);
136 }
137 // write bytes to chunk
138 for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) {
139 *dest = *src
76 } 140 }
77 }) 141 } else {
78 .await?; 142 // wait for interrupt
79 let random_bytes = T::regs().dr().read().to_be_bytes(); 143 poll_fn(|cx| {
80 for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) { 144 // quick check to avoid registration if already done.
81 *dest = *src 145 let bits = T::regs().sr().read();
146 if bits.drdy() || bits.seis() || bits.ceis() {
147 return Poll::Ready(());
148 }
149 RNG_WAKER.register(cx.waker());
150 T::regs().cr().modify(|reg| reg.set_ie(true));
151 // Need to check condition **after** `register` to avoid a race
152 // condition that would result in lost notifications.
153 let bits = T::regs().sr().read();
154 if bits.drdy() || bits.seis() || bits.ceis() {
155 Poll::Ready(())
156 } else {
157 Poll::Pending
158 }
159 })
160 .await;
82 } 161 }
83 } 162 }
84 163
@@ -129,57 +208,20 @@ pub(crate) mod sealed {
129 } 208 }
130} 209}
131 210
132pub trait Instance: sealed::Instance + crate::rcc::RccPeripheral {} 211pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
212 type Interrupt: interrupt::typelevel::Interrupt;
213}
133 214
134foreach_peripheral!( 215foreach_interrupt!(
135 (rng, $inst:ident) => { 216 ($inst:ident, rng, RNG, GLOBAL, $irq:ident) => {
136 impl Instance for peripherals::$inst {} 217 impl Instance for peripherals::$inst {
218 type Interrupt = crate::interrupt::typelevel::$irq;
219 }
137 220
138 impl sealed::Instance for peripherals::$inst { 221 impl sealed::Instance for peripherals::$inst {
139 fn regs() -> crate::pac::rng::Rng { 222 fn regs() -> crate::pac::rng::Rng {
140 crate::pac::RNG 223 crate::pac::$inst
141 }
142 }
143 };
144);
145
146#[cfg(feature = "rt")]
147macro_rules! irq {
148 ($irq:ident) => {
149 mod rng_irq {
150 use crate::interrupt;
151
152 #[interrupt]
153 unsafe fn $irq() {
154 let bits = $crate::pac::RNG.sr().read();
155 if bits.drdy() || bits.seis() || bits.ceis() {
156 $crate::pac::RNG.cr().write(|reg| reg.set_ie(false));
157 $crate::rng::RNG_WAKER.wake();
158 }
159 } 224 }
160 } 225 }
161 }; 226 };
162}
163
164#[cfg(feature = "rt")]
165foreach_interrupt!(
166 (RNG) => {
167 irq!(RNG);
168 };
169
170 (RNG_LPUART1) => {
171 irq!(RNG_LPUART1);
172 };
173
174 (AES_RNG_LPUART1) => {
175 irq!(AES_RNG_LPUART1);
176 };
177
178 (AES_RNG) => {
179 irq!(AES_RNG);
180 };
181
182 (HASH_RNG) => {
183 irq!(HASH_RNG);
184 };
185); 227);
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 12a2ac795..323be3187 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -15,7 +15,7 @@ pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
15#[cfg_attr(any(rtc_v3, rtc_v3u5), path = "v3.rs")] 15#[cfg_attr(any(rtc_v3, rtc_v3u5), path = "v3.rs")]
16mod _version; 16mod _version;
17pub use _version::*; 17pub use _version::*;
18use embassy_hal_common::Peripheral; 18use embassy_hal_internal::Peripheral;
19 19
20/// Errors that can occur on methods on [RtcClock] 20/// Errors that can occur on methods on [RtcClock]
21#[derive(Clone, Debug, PartialEq, Eq)] 21#[derive(Clone, Debug, PartialEq, Eq)]
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index a2eace6d3..e3b9dfb8b 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -39,9 +39,8 @@ impl<'d, T: Instance> super::Rtc<'d, T> {
39 let rtcsel = reg.rtcsel().to_bits(); 39 let rtcsel = reg.rtcsel().to_bits();
40 40
41 if !reg.rtcen() || rtcsel != clock_config { 41 if !reg.rtcen() || rtcsel != clock_config {
42 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 42 #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))]
43 crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); 43 crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true));
44
45 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 44 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
46 let cr = crate::pac::RCC.bdcr(); 45 let cr = crate::pac::RCC.bdcr();
47 #[cfg(any(rtc_v2l0, rtc_v2l1))] 46 #[cfg(any(rtc_v2l0, rtc_v2l1))]
@@ -201,6 +200,11 @@ impl sealed::Instance for crate::peripherals::RTC {
201 // read to allow the pwr clock to enable 200 // read to allow the pwr clock to enable
202 crate::pac::PWR.cr1().read(); 201 crate::pac::PWR.cr1().read();
203 } 202 }
203 #[cfg(any(rtc_v2f2))]
204 {
205 crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true));
206 crate::pac::PWR.cr().read();
207 }
204 } 208 }
205 209
206 fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> { 210 fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> {
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 434c56a48..6b532363c 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -6,8 +6,8 @@ use core::marker::PhantomData;
6use core::ops::{Deref, DerefMut}; 6use core::ops::{Deref, DerefMut};
7use core::task::Poll; 7use core::task::Poll;
8 8
9use embassy_hal_common::drop::OnDrop; 9use embassy_hal_internal::drop::OnDrop;
10use embassy_hal_common::{into_ref, PeripheralRef}; 10use embassy_hal_internal::{into_ref, PeripheralRef};
11use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
12use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; 12use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
13 13
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index d5f63f84e..bbc7c3b91 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -4,7 +4,7 @@ use core::ptr;
4 4
5use embassy_embedded_hal::SetConfig; 5use embassy_embedded_hal::SetConfig;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 8pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
9 9
10use crate::dma::{slice_ptr_parts, word, Transfer}; 10use crate::dma::{slice_ptr_parts, word, Transfer};
@@ -36,6 +36,7 @@ pub enum BitOrder {
36pub struct Config { 36pub struct Config {
37 pub mode: Mode, 37 pub mode: Mode,
38 pub bit_order: BitOrder, 38 pub bit_order: BitOrder,
39 pub frequency: Hertz,
39} 40}
40 41
41impl Default for Config { 42impl Default for Config {
@@ -43,6 +44,7 @@ impl Default for Config {
43 Self { 44 Self {
44 mode: MODE_0, 45 mode: MODE_0,
45 bit_order: BitOrder::MsbFirst, 46 bit_order: BitOrder::MsbFirst,
47 frequency: Hertz(1_000_000),
46 } 48 }
47 } 49 }
48} 50}
@@ -88,7 +90,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
88 miso: impl Peripheral<P = impl MisoPin<T>> + 'd, 90 miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
89 txdma: impl Peripheral<P = Tx> + 'd, 91 txdma: impl Peripheral<P = Tx> + 'd,
90 rxdma: impl Peripheral<P = Rx> + 'd, 92 rxdma: impl Peripheral<P = Rx> + 'd,
91 freq: Hertz,
92 config: Config, 93 config: Config,
93 ) -> Self { 94 ) -> Self {
94 into_ref!(peri, sck, mosi, miso); 95 into_ref!(peri, sck, mosi, miso);
@@ -112,7 +113,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
112 Some(miso.map_into()), 113 Some(miso.map_into()),
113 txdma, 114 txdma,
114 rxdma, 115 rxdma,
115 freq,
116 config, 116 config,
117 ) 117 )
118 } 118 }
@@ -123,7 +123,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
123 miso: impl Peripheral<P = impl MisoPin<T>> + 'd, 123 miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
124 txdma: impl Peripheral<P = Tx> + 'd, // TODO remove 124 txdma: impl Peripheral<P = Tx> + 'd, // TODO remove
125 rxdma: impl Peripheral<P = Rx> + 'd, 125 rxdma: impl Peripheral<P = Rx> + 'd,
126 freq: Hertz,
127 config: Config, 126 config: Config,
128 ) -> Self { 127 ) -> Self {
129 into_ref!(sck, miso); 128 into_ref!(sck, miso);
@@ -139,7 +138,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
139 Some(miso.map_into()), 138 Some(miso.map_into()),
140 txdma, 139 txdma,
141 rxdma, 140 rxdma,
142 freq,
143 config, 141 config,
144 ) 142 )
145 } 143 }
@@ -150,7 +148,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
150 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd, 148 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
151 txdma: impl Peripheral<P = Tx> + 'd, 149 txdma: impl Peripheral<P = Tx> + 'd,
152 rxdma: impl Peripheral<P = Rx> + 'd, // TODO remove 150 rxdma: impl Peripheral<P = Rx> + 'd, // TODO remove
153 freq: Hertz,
154 config: Config, 151 config: Config,
155 ) -> Self { 152 ) -> Self {
156 into_ref!(sck, mosi); 153 into_ref!(sck, mosi);
@@ -166,7 +163,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
166 None, 163 None,
167 txdma, 164 txdma,
168 rxdma, 165 rxdma,
169 freq,
170 config, 166 config,
171 ) 167 )
172 } 168 }
@@ -176,14 +172,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
176 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd, 172 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
177 txdma: impl Peripheral<P = Tx> + 'd, 173 txdma: impl Peripheral<P = Tx> + 'd,
178 rxdma: impl Peripheral<P = Rx> + 'd, // TODO: remove 174 rxdma: impl Peripheral<P = Rx> + 'd, // TODO: remove
179 freq: Hertz,
180 config: Config, 175 config: Config,
181 ) -> Self { 176 ) -> Self {
182 into_ref!(mosi); 177 into_ref!(mosi);
183 mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); 178 mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down);
184 mosi.set_speed(crate::gpio::Speed::Medium); 179 mosi.set_speed(crate::gpio::Speed::Medium);
185 180
186 Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config) 181 Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, config)
187 } 182 }
188 183
189 #[cfg(stm32wl)] 184 #[cfg(stm32wl)]
@@ -201,7 +196,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
201 let mut config = Config::default(); 196 let mut config = Config::default();
202 config.mode = MODE_0; 197 config.mode = MODE_0;
203 config.bit_order = BitOrder::MsbFirst; 198 config.bit_order = BitOrder::MsbFirst;
204 Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config) 199 config.frequency = freq;
200 Self::new_inner(peri, None, None, None, txdma, rxdma, config)
205 } 201 }
206 202
207 #[allow(dead_code)] 203 #[allow(dead_code)]
@@ -209,10 +205,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
209 peri: impl Peripheral<P = T> + 'd, 205 peri: impl Peripheral<P = T> + 'd,
210 txdma: impl Peripheral<P = Tx> + 'd, 206 txdma: impl Peripheral<P = Tx> + 'd,
211 rxdma: impl Peripheral<P = Rx> + 'd, 207 rxdma: impl Peripheral<P = Rx> + 'd,
212 freq: Hertz,
213 config: Config, 208 config: Config,
214 ) -> Self { 209 ) -> Self {
215 Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config) 210 Self::new_inner(peri, None, None, None, txdma, rxdma, config)
216 } 211 }
217 212
218 fn new_inner( 213 fn new_inner(
@@ -222,12 +217,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
222 miso: Option<PeripheralRef<'d, AnyPin>>, 217 miso: Option<PeripheralRef<'d, AnyPin>>,
223 txdma: impl Peripheral<P = Tx> + 'd, 218 txdma: impl Peripheral<P = Tx> + 'd,
224 rxdma: impl Peripheral<P = Rx> + 'd, 219 rxdma: impl Peripheral<P = Rx> + 'd,
225 freq: Hertz,
226 config: Config, 220 config: Config,
227 ) -> Self { 221 ) -> Self {
228 into_ref!(peri, txdma, rxdma); 222 into_ref!(peri, txdma, rxdma);
229 223
230 let pclk = T::frequency(); 224 let pclk = T::frequency();
225 let freq = config.frequency;
231 let br = compute_baud_rate(pclk, freq.into()); 226 let br = compute_baud_rate(pclk, freq.into());
232 227
233 let cpha = config.raw_phase(); 228 let cpha = config.raw_phase();
@@ -334,19 +329,29 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
334 329
335 let lsbfirst = config.raw_byte_order(); 330 let lsbfirst = config.raw_byte_order();
336 331
332 let pclk = T::frequency();
333 let freq = config.frequency;
334 let br = compute_baud_rate(pclk, freq.into());
335
337 #[cfg(any(spi_v1, spi_f1, spi_v2))] 336 #[cfg(any(spi_v1, spi_f1, spi_v2))]
338 T::REGS.cr1().modify(|w| { 337 T::REGS.cr1().modify(|w| {
339 w.set_cpha(cpha); 338 w.set_cpha(cpha);
340 w.set_cpol(cpol); 339 w.set_cpol(cpol);
340 w.set_br(br);
341 w.set_lsbfirst(lsbfirst); 341 w.set_lsbfirst(lsbfirst);
342 }); 342 });
343 343
344 #[cfg(any(spi_v3, spi_v4, spi_v5))] 344 #[cfg(any(spi_v3, spi_v4, spi_v5))]
345 T::REGS.cfg2().modify(|w| { 345 {
346 w.set_cpha(cpha); 346 T::REGS.cfg2().modify(|w| {
347 w.set_cpol(cpol); 347 w.set_cpha(cpha);
348 w.set_lsbfirst(lsbfirst); 348 w.set_cpol(cpol);
349 }); 349 w.set_lsbfirst(lsbfirst);
350 });
351 T::REGS.cfg1().modify(|w| {
352 w.set_mbr(br);
353 });
354 }
350 } 355 }
351 356
352 pub fn get_current_config(&self) -> Config { 357 pub fn get_current_config(&self) -> Config {
@@ -354,6 +359,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
354 let cfg = T::REGS.cr1().read(); 359 let cfg = T::REGS.cr1().read();
355 #[cfg(any(spi_v3, spi_v4, spi_v5))] 360 #[cfg(any(spi_v3, spi_v4, spi_v5))]
356 let cfg = T::REGS.cfg2().read(); 361 let cfg = T::REGS.cfg2().read();
362 #[cfg(any(spi_v3, spi_v4, spi_v5))]
363 let cfg1 = T::REGS.cfg1().read();
364
357 let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { 365 let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
358 Polarity::IdleLow 366 Polarity::IdleLow
359 } else { 367 } else {
@@ -371,9 +379,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
371 BitOrder::MsbFirst 379 BitOrder::MsbFirst
372 }; 380 };
373 381
382 #[cfg(any(spi_v1, spi_f1, spi_v2))]
383 let br = cfg.br();
384 #[cfg(any(spi_v3, spi_v4, spi_v5))]
385 let br = cfg1.mbr();
386
387 let pclk = T::frequency();
388 let frequency = compute_frequency(pclk, br);
389
374 Config { 390 Config {
375 mode: Mode { polarity, phase }, 391 mode: Mode { polarity, phase },
376 bit_order, 392 bit_order,
393 frequency,
377 } 394 }
378 } 395 }
379 396
@@ -653,6 +670,21 @@ fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
653 Br::from_bits(val) 670 Br::from_bits(val)
654} 671}
655 672
673fn compute_frequency(clocks: Hertz, br: Br) -> Hertz {
674 let div: u16 = match br {
675 Br::DIV2 => 2,
676 Br::DIV4 => 4,
677 Br::DIV8 => 8,
678 Br::DIV16 => 16,
679 Br::DIV32 => 32,
680 Br::DIV64 => 64,
681 Br::DIV128 => 128,
682 Br::DIV256 => 256,
683 };
684
685 clocks / div
686}
687
656trait RegsExt { 688trait RegsExt {
657 fn tx_ptr<W>(&self) -> *mut W; 689 fn tx_ptr<W>(&self) -> *mut W;
658 fn rx_ptr<W>(&self) -> *mut W; 690 fn rx_ptr<W>(&self) -> *mut W;
diff --git a/embassy-stm32/src/pwm/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 4d64d005c..48cb610f1 100644
--- a/embassy-stm32/src/pwm/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -1,13 +1,13 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_internal::{into_ref, PeripheralRef};
4use stm32_metapac::timer::vals::Ckd; 4use stm32_metapac::timer::vals::Ckd;
5 5
6use super::simple_pwm::*; 6use super::simple_pwm::*;
7use super::*; 7use super::*;
8#[allow(unused_imports)] 8#[allow(unused_imports)]
9use crate::gpio::sealed::{AFType, Pin}; 9use crate::gpio::sealed::{AFType, Pin};
10use crate::gpio::AnyPin; 10use crate::gpio::{AnyPin, OutputType};
11use crate::time::Hertz; 11use crate::time::Hertz;
12use crate::Peripheral; 12use crate::Peripheral;
13 13
@@ -17,13 +17,13 @@ pub struct ComplementaryPwmPin<'d, Perip, Channel> {
17} 17}
18 18
19macro_rules! complementary_channel_impl { 19macro_rules! complementary_channel_impl {
20 ($new_chx:ident, $channel:ident, $pin_trait:ident, $complementary_pin_trait:ident) => { 20 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
21 impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { 21 impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> {
22 pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { 22 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self {
23 into_ref!(pin); 23 into_ref!(pin);
24 critical_section::with(|_| { 24 critical_section::with(|_| {
25 pin.set_low(); 25 pin.set_low();
26 pin.set_as_af(pin.af_num(), AFType::OutputPushPull); 26 pin.set_as_af(pin.af_num(), output_type.into());
27 #[cfg(gpio_v2)] 27 #[cfg(gpio_v2)]
28 pin.set_speed(crate::gpio::Speed::VeryHigh); 28 pin.set_speed(crate::gpio::Speed::VeryHigh);
29 }); 29 });
@@ -36,10 +36,10 @@ macro_rules! complementary_channel_impl {
36 }; 36 };
37} 37}
38 38
39complementary_channel_impl!(new_ch1, Ch1, Channel1Pin, Channel1ComplementaryPin); 39complementary_channel_impl!(new_ch1, Ch1, Channel1ComplementaryPin);
40complementary_channel_impl!(new_ch2, Ch2, Channel2Pin, Channel2ComplementaryPin); 40complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin);
41complementary_channel_impl!(new_ch3, Ch3, Channel3Pin, Channel3ComplementaryPin); 41complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
42complementary_channel_impl!(new_ch4, Ch4, Channel4Pin, Channel4ComplementaryPin); 42complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
43 43
44pub struct ComplementaryPwm<'d, T> { 44pub struct ComplementaryPwm<'d, T> {
45 inner: PeripheralRef<'d, T>, 45 inner: PeripheralRef<'d, T>,
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 09b7a3776..6c2d6d827 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,3 +1,6 @@
1pub mod complementary_pwm;
2pub mod simple_pwm;
3
1use stm32_metapac::timer::vals; 4use stm32_metapac::timer::vals;
2 5
3use crate::interrupt; 6use crate::interrupt;
@@ -43,15 +46,123 @@ pub(crate) mod sealed {
43 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { 46 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
44 fn regs_advanced() -> crate::pac::timer::TimAdv; 47 fn regs_advanced() -> crate::pac::timer::TimAdv;
45 } 48 }
49
50 pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
51 /// Global output enable. Does not do anything on non-advanced timers.
52 fn enable_outputs(&mut self, enable: bool);
53
54 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
55
56 fn enable_channel(&mut self, channel: Channel, enable: bool);
57
58 fn set_compare_value(&mut self, channel: Channel, value: u16);
59
60 fn get_max_compare_value(&self) -> u16;
61 }
62
63 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance {
64 fn set_dead_time_clock_division(&mut self, value: vals::Ckd);
65
66 fn set_dead_time_value(&mut self, value: u8);
67
68 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool);
69 }
70
71 pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance {
72 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
73
74 fn enable_channel(&mut self, channel: Channel, enable: bool);
75
76 fn set_compare_value(&mut self, channel: Channel, value: u32);
77
78 fn get_max_compare_value(&self) -> u32;
79 }
80}
81
82#[derive(Clone, Copy)]
83pub enum Channel {
84 Ch1,
85 Ch2,
86 Ch3,
87 Ch4,
46} 88}
47 89
90impl Channel {
91 pub fn raw(&self) -> usize {
92 match self {
93 Channel::Ch1 => 0,
94 Channel::Ch2 => 1,
95 Channel::Ch3 => 2,
96 Channel::Ch4 => 3,
97 }
98 }
99}
100
101#[derive(Clone, Copy)]
102pub enum OutputCompareMode {
103 Frozen,
104 ActiveOnMatch,
105 InactiveOnMatch,
106 Toggle,
107 ForceInactive,
108 ForceActive,
109 PwmMode1,
110 PwmMode2,
111}
112
113impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
114 fn from(mode: OutputCompareMode) -> Self {
115 match mode {
116 OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN,
117 OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH,
118 OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH,
119 OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE,
120 OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE,
121 OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE,
122 OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1,
123 OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2,
124 }
125 }
126}
127
128pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
129
48pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {} 130pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {}
49 131
50pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {} 132pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {}
51 133
52pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {} 134pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {}
53 135
54pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {} 136pub trait CaptureCompare16bitInstance:
137 sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static
138{
139}
140
141pub trait ComplementaryCaptureCompare16bitInstance:
142 sealed::ComplementaryCaptureCompare16bitInstance + AdvancedControlInstance + 'static
143{
144}
145
146pub trait CaptureCompare32bitInstance:
147 sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static
148{
149}
150
151pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
152pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance);
153pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
154pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance);
155pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
156pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance);
157pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
158pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance);
159pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
160pin_trait!(BreakInputPin, CaptureCompare16bitInstance);
161pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance);
162pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance);
163pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance);
164pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance);
165pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance);
55 166
56#[allow(unused)] 167#[allow(unused)]
57macro_rules! impl_basic_16bit_timer { 168macro_rules! impl_basic_16bit_timer {
@@ -140,33 +251,94 @@ macro_rules! impl_32bit_timer {
140 }; 251 };
141} 252}
142 253
254#[allow(unused)]
255macro_rules! impl_compare_capable_16bit {
256 ($inst:ident) => {
257 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
258 fn enable_outputs(&mut self, _enable: bool) {}
259
260 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
261 use sealed::GeneralPurpose16bitInstance;
262 let r = Self::regs_gp16();
263 let raw_channel: usize = channel.raw();
264 r.ccmr_output(raw_channel / 2)
265 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
266 }
267
268 fn enable_channel(&mut self, channel: Channel, enable: bool) {
269 use sealed::GeneralPurpose16bitInstance;
270 Self::regs_gp16()
271 .ccer()
272 .modify(|w| w.set_cce(channel.raw(), enable));
273 }
274
275 fn set_compare_value(&mut self, channel: Channel, value: u16) {
276 use sealed::GeneralPurpose16bitInstance;
277 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
278 }
279
280 fn get_max_compare_value(&self) -> u16 {
281 use sealed::GeneralPurpose16bitInstance;
282 Self::regs_gp16().arr().read().arr()
283 }
284 }
285 };
286}
287
143foreach_interrupt! { 288foreach_interrupt! {
144 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { 289 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
145 impl_basic_16bit_timer!($inst, $irq); 290 impl_basic_16bit_timer!($inst, $irq);
146 291 impl Basic16bitInstance for crate::peripherals::$inst {}
147 impl Basic16bitInstance for crate::peripherals::$inst {
148 }
149 }; 292 };
150 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { 293 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
151 impl_basic_16bit_timer!($inst, $irq); 294 impl_basic_16bit_timer!($inst, $irq);
152 295 impl_compare_capable_16bit!($inst);
153 impl Basic16bitInstance for crate::peripherals::$inst { 296 impl Basic16bitInstance for crate::peripherals::$inst {}
154 } 297 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
298 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
155 299
156 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 300 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
157 fn regs_gp16() -> crate::pac::timer::TimGp16 { 301 fn regs_gp16() -> crate::pac::timer::TimGp16 {
158 crate::pac::$inst 302 crate::pac::$inst
159 } 303 }
160 } 304 }
161
162 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
163 }
164 }; 305 };
165 306
166 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { 307 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
167 impl_basic_16bit_timer!($inst, $irq); 308 impl_basic_16bit_timer!($inst, $irq);
309 impl_32bit_timer!($inst);
310 impl_compare_capable_16bit!($inst);
311 impl Basic16bitInstance for crate::peripherals::$inst {}
312 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
313 impl CaptureCompare32bitInstance for crate::peripherals::$inst {}
314 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
315 impl GeneralPurpose32bitInstance for crate::peripherals::$inst {}
316
317 impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {
318 fn set_output_compare_mode(
319 &mut self,
320 channel: Channel,
321 mode: OutputCompareMode,
322 ) {
323 use crate::timer::sealed::GeneralPurpose32bitInstance;
324 let raw_channel = channel.raw();
325 Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
326 }
327
328 fn enable_channel(&mut self, channel: Channel, enable: bool) {
329 use crate::timer::sealed::GeneralPurpose32bitInstance;
330 Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable));
331 }
168 332
169 impl Basic16bitInstance for crate::peripherals::$inst { 333 fn set_compare_value(&mut self, channel: Channel, value: u32) {
334 use crate::timer::sealed::GeneralPurpose32bitInstance;
335 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
336 }
337
338 fn get_max_compare_value(&self) -> u32 {
339 use crate::timer::sealed::GeneralPurpose32bitInstance;
340 Self::regs_gp32().arr().read().arr() as u32
341 }
170 } 342 }
171 343
172 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 344 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
@@ -174,21 +346,16 @@ foreach_interrupt! {
174 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } 346 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
175 } 347 }
176 } 348 }
177
178 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
179 }
180
181 impl_32bit_timer!($inst);
182
183 impl GeneralPurpose32bitInstance for crate::peripherals::$inst {
184 }
185 }; 349 };
186 350
187 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { 351 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
188 impl_basic_16bit_timer!($inst, $irq); 352 impl_basic_16bit_timer!($inst, $irq);
189 353
190 impl Basic16bitInstance for crate::peripherals::$inst { 354 impl Basic16bitInstance for crate::peripherals::$inst {}
191 } 355 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
356 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
357 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
358 impl AdvancedControlInstance for crate::peripherals::$inst {}
192 359
193 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 360 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
194 fn regs_gp16() -> crate::pac::timer::TimGp16 { 361 fn regs_gp16() -> crate::pac::timer::TimGp16 {
@@ -196,16 +363,70 @@ foreach_interrupt! {
196 } 363 }
197 } 364 }
198 365
199 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {
200 }
201
202 impl sealed::AdvancedControlInstance for crate::peripherals::$inst { 366 impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
203 fn regs_advanced() -> crate::pac::timer::TimAdv { 367 fn regs_advanced() -> crate::pac::timer::TimAdv {
204 crate::pac::$inst 368 crate::pac::$inst
205 } 369 }
206 } 370 }
207 371
208 impl AdvancedControlInstance for crate::peripherals::$inst { 372 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
373 fn enable_outputs(&mut self, enable: bool) {
374 use crate::timer::sealed::AdvancedControlInstance;
375 let r = Self::regs_advanced();
376 r.bdtr().modify(|w| w.set_moe(enable));
377 }
378
379 fn set_output_compare_mode(
380 &mut self,
381 channel: Channel,
382 mode: OutputCompareMode,
383 ) {
384 use crate::timer::sealed::AdvancedControlInstance;
385 let r = Self::regs_advanced();
386 let raw_channel: usize = channel.raw();
387 r.ccmr_output(raw_channel / 2)
388 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
389 }
390
391 fn enable_channel(&mut self, channel: Channel, enable: bool) {
392 use crate::timer::sealed::AdvancedControlInstance;
393 Self::regs_advanced()
394 .ccer()
395 .modify(|w| w.set_cce(channel.raw(), enable));
396 }
397
398 fn set_compare_value(&mut self, channel: Channel, value: u16) {
399 use crate::timer::sealed::AdvancedControlInstance;
400 Self::regs_advanced()
401 .ccr(channel.raw())
402 .modify(|w| w.set_ccr(value));
403 }
404
405 fn get_max_compare_value(&self) -> u16 {
406 use crate::timer::sealed::AdvancedControlInstance;
407 Self::regs_advanced().arr().read().arr()
408 }
409 }
410
411 impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
412 fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
413 use crate::timer::sealed::AdvancedControlInstance;
414 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
415 }
416
417 fn set_dead_time_value(&mut self, value: u8) {
418 use crate::timer::sealed::AdvancedControlInstance;
419 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
420 }
421
422 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
423 use crate::timer::sealed::AdvancedControlInstance;
424 Self::regs_advanced()
425 .ccer()
426 .modify(|w| w.set_ccne(channel.raw(), enable));
427 }
209 } 428 }
429
430
210 }; 431 };
211} 432}
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 995f59c23..e0a817929 100644
--- a/embassy-stm32/src/pwm/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -1,11 +1,11 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_internal::{into_ref, PeripheralRef};
4 4
5use super::*; 5use super::*;
6#[allow(unused_imports)] 6#[allow(unused_imports)]
7use crate::gpio::sealed::{AFType, Pin}; 7use crate::gpio::sealed::{AFType, Pin};
8use crate::gpio::AnyPin; 8use crate::gpio::{AnyPin, OutputType};
9use crate::time::Hertz; 9use crate::time::Hertz;
10use crate::Peripheral; 10use crate::Peripheral;
11 11
@@ -22,11 +22,11 @@ pub struct PwmPin<'d, Perip, Channel> {
22macro_rules! channel_impl { 22macro_rules! channel_impl {
23 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 23 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
24 impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { 24 impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> {
25 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self { 25 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self {
26 into_ref!(pin); 26 into_ref!(pin);
27 critical_section::with(|_| { 27 critical_section::with(|_| {
28 pin.set_low(); 28 pin.set_low();
29 pin.set_as_af(pin.af_num(), AFType::OutputPushPull); 29 pin.set_as_af(pin.af_num(), output_type.into());
30 #[cfg(gpio_v2)] 30 #[cfg(gpio_v2)]
31 pin.set_speed(crate::gpio::Speed::VeryHigh); 31 pin.set_speed(crate::gpio::Speed::VeryHigh);
32 }); 32 });
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 433ad299c..ca117da82 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -2,7 +2,7 @@ use core::future::poll_fn;
2use core::slice; 2use core::slice;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_common::atomic_ring_buffer::RingBuffer; 5use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
6use embassy_sync::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
7 7
8use super::*; 8use super::*;
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index ea8e525ea..d99034bca 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -5,8 +5,8 @@ use core::marker::PhantomData;
5use core::sync::atomic::{compiler_fence, Ordering}; 5use core::sync::atomic::{compiler_fence, Ordering};
6use core::task::Poll; 6use core::task::Poll;
7 7
8use embassy_hal_common::drop::OnDrop; 8use embassy_hal_internal::drop::OnDrop;
9use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10use futures::future::{select, Either}; 10use futures::future::{select, Either};
11 11
12use crate::dma::{NoDma, Transfer}; 12use crate::dma::{NoDma, Transfer};
@@ -857,7 +857,7 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
857 "Using {} oversampling, desired baudrate: {}, actual baudrate: {}", 857 "Using {} oversampling, desired baudrate: {}, actual baudrate: {}",
858 oversampling, 858 oversampling,
859 config.baudrate, 859 config.baudrate,
860 pclk_freq.0 / div 860 (pclk_freq.0 * mul as u32) / div
861 ); 861 );
862 862
863 r.cr2().write(|w| { 863 r.cr2().write(|w| {
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index c74d7e092..80261d048 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -2,7 +2,7 @@ use core::future::poll_fn;
2use core::sync::atomic::{compiler_fence, Ordering}; 2use core::sync::atomic::{compiler_fence, Ordering};
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_common::PeripheralRef; 5use embassy_hal_internal::PeripheralRef;
6use futures::future::{select, Either}; 6use futures::future::{select, Either};
7 7
8use super::{clear_interrupt_flags, rdr, sr, BasicInstance, Error, UartRx}; 8use super::{clear_interrupt_flags, rdr, sr, BasicInstance, Error, UartRx};
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index ecdd1d0b8..cef196355 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -5,7 +5,7 @@ use core::marker::PhantomData;
5use core::sync::atomic::{AtomicBool, Ordering}; 5use core::sync::atomic::{AtomicBool, Ordering};
6use core::task::Poll; 6use core::task::Poll;
7 7
8use embassy_hal_common::into_ref; 8use embassy_hal_internal::into_ref;
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10use embassy_usb_driver as driver; 10use embassy_usb_driver as driver;
11use embassy_usb_driver::{ 11use embassy_usb_driver::{
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index fd0e22adf..348f0f79d 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
3use core::sync::atomic::{AtomicBool, AtomicU16, Ordering}; 3use core::sync::atomic::{AtomicBool, AtomicU16, Ordering};
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_hal_common::{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 self, Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo,
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index b03e81d6e..eafd03364 100644
--- a/embassy-stm32/src/wdg/mod.rs
+++ b/embassy-stm32/src/wdg/mod.rs
@@ -1,6 +1,6 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_hal_common::{into_ref, Peripheral}; 3use embassy_hal_internal::{into_ref, Peripheral};
4use stm32_metapac::iwdg::vals::{Key, Pr}; 4use stm32_metapac::iwdg::vals::{Key, Pr};
5 5
6use crate::rcc::LSI_FREQ; 6use crate::rcc::LSI_FREQ;
diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs
index c8497494c..b5e1950cc 100644
--- a/examples/boot/application/rp/src/bin/a.rs
+++ b/examples/boot/application/rp/src/bin/a.rs
@@ -7,7 +7,7 @@ use core::cell::RefCell;
7use defmt_rtt as _; 7use defmt_rtt as _;
8use embassy_boot_rp::*; 8use embassy_boot_rp::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_rp::flash::Flash; 10use embassy_rp::flash::{self, Flash};
11use embassy_rp::gpio::{Level, Output}; 11use embassy_rp::gpio::{Level, Output};
12use embassy_rp::watchdog::Watchdog; 12use embassy_rp::watchdog::Watchdog;
13use embassy_sync::blocking_mutex::Mutex; 13use embassy_sync::blocking_mutex::Mutex;
@@ -34,7 +34,7 @@ async fn main(_s: Spawner) {
34 let mut watchdog = Watchdog::new(p.WATCHDOG); 34 let mut watchdog = Watchdog::new(p.WATCHDOG);
35 watchdog.start(Duration::from_secs(8)); 35 watchdog.start(Duration::from_secs(8));
36 36
37 let flash: Flash<_, FLASH_SIZE> = Flash::new(p.FLASH); 37 let flash = Flash::<_, flash::Blocking, FLASH_SIZE>::new(p.FLASH);
38 let flash = Mutex::new(RefCell::new(flash)); 38 let flash = Mutex::new(RefCell::new(flash));
39 39
40 let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); 40 let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash);
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml
index 30b67b7b2..068474e7a 100644
--- a/examples/nrf-rtos-trace/Cargo.toml
+++ b/examples/nrf-rtos-trace/Cargo.toml
@@ -34,3 +34,6 @@ log = { version = "0.4.17", optional = true }
34[[bin]] 34[[bin]]
35name = "rtos_trace" 35name = "rtos_trace"
36required-features = ["nightly"] 36required-features = ["nightly"]
37
38[profile.release]
39debug = 2
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml
index ded3b7db8..715f1ecfe 100644
--- a/examples/nrf52840-rtic/Cargo.toml
+++ b/examples/nrf52840-rtic/Cargo.toml
@@ -19,3 +19,6 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
19cortex-m-rt = "0.7.0" 19cortex-m-rt = "0.7.0"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 20panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22
23[profile.release]
24debug = 2
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index 9b41ec5ab..780aaeac2 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -57,5 +57,5 @@ embedded-hal-async = { version = "0.2.0-alpha.2", optional = true }
57num-integer = { version = "0.1.45", default-features = false } 57num-integer = { version = "0.1.45", default-features = false }
58microfft = "0.5.0" 58microfft = "0.5.0"
59 59
60[patch.crates-io] 60[profile.release]
61lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } 61debug = 2
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml
index f1d45f336..b0e51dcf4 100644
--- a/examples/nrf5340/Cargo.toml
+++ b/examples/nrf5340/Cargo.toml
@@ -53,3 +53,6 @@ rand = { version = "0.8.4", default-features = false }
53embedded-storage = "0.3.0" 53embedded-storage = "0.3.0"
54usbd-hid = "0.6.0" 54usbd-hid = "0.6.0"
55serde = { version = "1.0.136", default-features = false } 55serde = { version = "1.0.136", default-features = false }
56
57[profile.release]
58debug = 2
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index c812cb3ee..8c61dc5e1 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -53,7 +53,4 @@ pio = "0.2.1"
53rand = { version = "0.8.5", default-features = false } 53rand = { version = "0.8.5", default-features = false }
54 54
55[profile.release] 55[profile.release]
56debug = true 56debug = 2
57
58[patch.crates-io]
59lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" }
diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs
index 4c4982acc..88bb931d2 100644
--- a/examples/rp/src/bin/flash.rs
+++ b/examples/rp/src/bin/flash.rs
@@ -6,7 +6,7 @@
6 6
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE}; 9use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE};
10use embassy_rp::peripherals::FLASH; 10use embassy_rp::peripherals::FLASH;
11use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) {
25 // https://github.com/knurling-rs/defmt/pull/683 25 // https://github.com/knurling-rs/defmt/pull/683
26 Timer::after(Duration::from_millis(10)).await; 26 Timer::after(Duration::from_millis(10)).await;
27 27
28 let mut flash = embassy_rp::flash::Flash::<_, FLASH_SIZE>::new(p.FLASH); 28 let mut flash = embassy_rp::flash::Flash::<_, Async, FLASH_SIZE>::new(p.FLASH, p.DMA_CH0);
29 29
30 // Get JEDEC id 30 // Get JEDEC id
31 let jedec = flash.jedec_id().unwrap(); 31 let jedec = flash.jedec_id().unwrap();
@@ -40,10 +40,12 @@ async fn main(_spawner: Spawner) {
40 40
41 multiwrite_bytes(&mut flash, ERASE_SIZE as u32); 41 multiwrite_bytes(&mut flash, ERASE_SIZE as u32);
42 42
43 background_read(&mut flash, (ERASE_SIZE * 2) as u32).await;
44
43 loop {} 45 loop {}
44} 46}
45 47
46fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) { 48fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) {
47 info!(">>>> [multiwrite_bytes]"); 49 info!(">>>> [multiwrite_bytes]");
48 let mut read_buf = [0u8; ERASE_SIZE]; 50 let mut read_buf = [0u8; ERASE_SIZE];
49 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf)); 51 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf));
@@ -71,7 +73,7 @@ fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>,
71 } 73 }
72} 74}
73 75
74fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) { 76fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) {
75 info!(">>>> [erase_write_sector]"); 77 info!(">>>> [erase_write_sector]");
76 let mut buf = [0u8; ERASE_SIZE]; 78 let mut buf = [0u8; ERASE_SIZE];
77 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf)); 79 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf));
@@ -99,3 +101,35 @@ fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE
99 defmt::panic!("unexpected"); 101 defmt::panic!("unexpected");
100 } 102 }
101} 103}
104
105async fn background_read(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) {
106 info!(">>>> [background_read]");
107
108 let mut buf = [0u32; 8];
109 defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await;
110
111 info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32);
112 info!("Contents start with {=u32:x}", buf[0]);
113
114 defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32));
115
116 defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await;
117 info!("Contents after erase starts with {=u32:x}", buf[0]);
118 if buf.iter().any(|x| *x != 0xFFFFFFFF) {
119 defmt::panic!("unexpected");
120 }
121
122 for b in buf.iter_mut() {
123 *b = 0xDABA1234;
124 }
125
126 defmt::unwrap!(flash.write(ADDR_OFFSET + offset, unsafe {
127 core::slice::from_raw_parts(buf.as_ptr() as *const u8, buf.len() * 4)
128 }));
129
130 defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await;
131 info!("Contents after write starts with {=u32:x}", buf[0]);
132 if buf.iter().any(|x| *x != 0xDABA1234) {
133 defmt::panic!("unexpected");
134 }
135}
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index c001d6440..a6d6144be 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -8,7 +8,6 @@ use embassy_executor::Spawner;
8use embassy_rp::bind_interrupts; 8use embassy_rp::bind_interrupts;
9use embassy_rp::peripherals::PIO0; 9use embassy_rp::peripherals::PIO0;
10use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; 10use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine};
11use embassy_rp::relocate::RelocatedProgram;
12use fixed::traits::ToFixed; 11use fixed::traits::ToFixed;
13use fixed_macro::types::U56F8; 12use fixed_macro::types::U56F8;
14use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -29,9 +28,8 @@ fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a,
29 ".wrap", 28 ".wrap",
30 ); 29 );
31 30
32 let relocated = RelocatedProgram::new(&prg.program);
33 let mut cfg = Config::default(); 31 let mut cfg = Config::default();
34 cfg.use_program(&pio.load_program(&relocated), &[]); 32 cfg.use_program(&pio.load_program(&prg.program), &[]);
35 let out_pin = pio.make_pio_pin(pin); 33 let out_pin = pio.make_pio_pin(pin);
36 cfg.set_out_pins(&[&out_pin]); 34 cfg.set_out_pins(&[&out_pin]);
37 cfg.set_set_pins(&[&out_pin]); 35 cfg.set_set_pins(&[&out_pin]);
@@ -65,9 +63,8 @@ fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a,
65 ".wrap", 63 ".wrap",
66 ); 64 );
67 65
68 let relocated = RelocatedProgram::new(&prg.program);
69 let mut cfg = Config::default(); 66 let mut cfg = Config::default();
70 cfg.use_program(&pio.load_program(&relocated), &[]); 67 cfg.use_program(&pio.load_program(&prg.program), &[]);
71 cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); 68 cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed();
72 cfg.shift_in.auto_fill = true; 69 cfg.shift_in.auto_fill = true;
73 cfg.shift_in.direction = ShiftDirection::Right; 70 cfg.shift_in.direction = ShiftDirection::Right;
@@ -96,9 +93,8 @@ fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a,
96 "irq 3 [15]", 93 "irq 3 [15]",
97 ".wrap", 94 ".wrap",
98 ); 95 );
99 let relocated = RelocatedProgram::new(&prg.program);
100 let mut cfg = Config::default(); 96 let mut cfg = Config::default();
101 cfg.use_program(&pio.load_program(&relocated), &[]); 97 cfg.use_program(&pio.load_program(&prg.program), &[]);
102 cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); 98 cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed();
103 sm.set_config(&cfg); 99 sm.set_config(&cfg);
104} 100}
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index 9ab72e1f3..86e5017ac 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -8,7 +8,6 @@ use embassy_executor::Spawner;
8use embassy_futures::join::join; 8use embassy_futures::join::join;
9use embassy_rp::peripherals::PIO0; 9use embassy_rp::peripherals::PIO0;
10use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; 10use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection};
11use embassy_rp::relocate::RelocatedProgram;
12use embassy_rp::{bind_interrupts, Peripheral}; 11use embassy_rp::{bind_interrupts, Peripheral};
13use fixed::traits::ToFixed; 12use fixed::traits::ToFixed;
14use fixed_macro::types::U56F8; 13use fixed_macro::types::U56F8;
@@ -46,9 +45,8 @@ async fn main(_spawner: Spawner) {
46 ".wrap", 45 ".wrap",
47 ); 46 );
48 47
49 let relocated = RelocatedProgram::new(&prg.program);
50 let mut cfg = Config::default(); 48 let mut cfg = Config::default();
51 cfg.use_program(&common.load_program(&relocated), &[]); 49 cfg.use_program(&common.load_program(&prg.program), &[]);
52 cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed(); 50 cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed();
53 cfg.shift_in = ShiftConfig { 51 cfg.shift_in = ShiftConfig {
54 auto_fill: true, 52 auto_fill: true,
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
index 8aedd24b6..d80c5c24b 100644
--- a/examples/rp/src/bin/pio_hd44780.rs
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -14,7 +14,6 @@ use embassy_rp::pio::{
14 Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, 14 Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine,
15}; 15};
16use embassy_rp::pwm::{self, Pwm}; 16use embassy_rp::pwm::{self, Pwm};
17use embassy_rp::relocate::RelocatedProgram;
18use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef}; 17use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef};
19use embassy_time::{Duration, Instant, Timer}; 18use embassy_time::{Duration, Instant, Timer};
20use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
@@ -127,9 +126,8 @@ impl<'l> HD44780<'l> {
127 126
128 sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]); 127 sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]);
129 128
130 let relocated = RelocatedProgram::new(&prg.program);
131 let mut cfg = Config::default(); 129 let mut cfg = Config::default();
132 cfg.use_program(&common.load_program(&relocated), &[&e]); 130 cfg.use_program(&common.load_program(&prg.program), &[&e]);
133 cfg.clock_divider = 125u8.into(); 131 cfg.clock_divider = 125u8.into();
134 cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); 132 cfg.set_out_pins(&[&db4, &db5, &db6, &db7]);
135 cfg.shift_out = ShiftConfig { 133 cfg.shift_out = ShiftConfig {
@@ -201,9 +199,8 @@ impl<'l> HD44780<'l> {
201 "# 199 "#
202 ); 200 );
203 201
204 let relocated = RelocatedProgram::new(&prg.program);
205 let mut cfg = Config::default(); 202 let mut cfg = Config::default();
206 cfg.use_program(&common.load_program(&relocated), &[&e]); 203 cfg.use_program(&common.load_program(&prg.program), &[&e]);
207 cfg.clock_divider = 8u8.into(); // ~64ns/insn 204 cfg.clock_divider = 8u8.into(); // ~64ns/insn
208 cfg.set_jmp_pin(&db7); 205 cfg.set_jmp_pin(&db7);
209 cfg.set_set_pins(&[&rs, &rw]); 206 cfg.set_set_pins(&[&rs, &rw]);
diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs
new file mode 100644
index 000000000..4c382c2ee
--- /dev/null
+++ b/examples/rp/src/bin/pio_uart.rs
@@ -0,0 +1,394 @@
1//! This example shows how to use the PIO module in the RP2040 chip to implement a duplex UART.
2//! The PIO module is a very powerful peripheral that can be used to implement many different
3//! protocols. It is a very flexible state machine that can be programmed to do almost anything.
4//!
5//! This example opens up a USB device that implements a CDC ACM serial port. It then uses the
6//! PIO module to implement a UART that is connected to the USB serial port. This allows you to
7//! communicate with a device connected to the RP2040 over USB serial.
8
9#![no_std]
10#![no_main]
11#![feature(type_alias_impl_trait)]
12#![feature(async_fn_in_trait)]
13
14use defmt::{info, panic, trace};
15use embassy_executor::Spawner;
16use embassy_futures::join::{join, join3};
17use embassy_rp::bind_interrupts;
18use embassy_rp::peripherals::{PIO0, USB};
19use embassy_rp::pio::InterruptHandler as PioInterruptHandler;
20use embassy_rp::usb::{Driver, Instance, InterruptHandler};
21use embassy_sync::blocking_mutex::raw::NoopRawMutex;
22use embassy_sync::pipe::Pipe;
23use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State};
24use embassy_usb::driver::EndpointError;
25use embassy_usb::{Builder, Config};
26use embedded_io::asynch::{Read, Write};
27use {defmt_rtt as _, panic_probe as _};
28
29use crate::uart::PioUart;
30use crate::uart_rx::PioUartRx;
31use crate::uart_tx::PioUartTx;
32
33bind_interrupts!(struct Irqs {
34 USBCTRL_IRQ => InterruptHandler<USB>;
35 PIO0_IRQ_0 => PioInterruptHandler<PIO0>;
36});
37
38#[embassy_executor::main]
39async fn main(_spawner: Spawner) {
40 info!("Hello there!");
41
42 let p = embassy_rp::init(Default::default());
43
44 // Create the driver, from the HAL.
45 let driver = Driver::new(p.USB, Irqs);
46
47 // Create embassy-usb Config
48 let mut config = Config::new(0xc0de, 0xcafe);
49 config.manufacturer = Some("Embassy");
50 config.product = Some("PIO UART example");
51 config.serial_number = Some("12345678");
52 config.max_power = 100;
53 config.max_packet_size_0 = 64;
54
55 // Required for windows compatibility.
56 // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
57 config.device_class = 0xEF;
58 config.device_sub_class = 0x02;
59 config.device_protocol = 0x01;
60 config.composite_with_iads = true;
61
62 // Create embassy-usb DeviceBuilder using the driver and config.
63 // It needs some buffers for building the descriptors.
64 let mut device_descriptor = [0; 256];
65 let mut config_descriptor = [0; 256];
66 let mut bos_descriptor = [0; 256];
67 let mut control_buf = [0; 64];
68
69 let mut state = State::new();
70
71 let mut builder = Builder::new(
72 driver,
73 config,
74 &mut device_descriptor,
75 &mut config_descriptor,
76 &mut bos_descriptor,
77 &mut control_buf,
78 );
79
80 // Create classes on the builder.
81 let class = CdcAcmClass::new(&mut builder, &mut state, 64);
82
83 // Build the builder.
84 let mut usb = builder.build();
85
86 // Run the USB device.
87 let usb_fut = usb.run();
88
89 // PIO UART setup
90 let uart = PioUart::new(9600, p.PIO0, p.PIN_4, p.PIN_5);
91 let (mut uart_tx, mut uart_rx) = uart.split();
92
93 // Pipe setup
94 let usb_pipe: Pipe<NoopRawMutex, 20> = Pipe::new();
95 let mut usb_pipe_writer = usb_pipe.writer();
96 let mut usb_pipe_reader = usb_pipe.reader();
97
98 let uart_pipe: Pipe<NoopRawMutex, 20> = Pipe::new();
99 let mut uart_pipe_writer = uart_pipe.writer();
100 let mut uart_pipe_reader = uart_pipe.reader();
101
102 let (mut usb_tx, mut usb_rx) = class.split();
103
104 // Read + write from USB
105 let usb_future = async {
106 loop {
107 info!("Wait for USB connection");
108 usb_rx.wait_connection().await;
109 info!("Connected");
110 let _ = join(
111 usb_read(&mut usb_rx, &mut uart_pipe_writer),
112 usb_write(&mut usb_tx, &mut usb_pipe_reader),
113 )
114 .await;
115 info!("Disconnected");
116 }
117 };
118
119 // Read + write from UART
120 let uart_future = join(
121 uart_read(&mut uart_rx, &mut usb_pipe_writer),
122 uart_write(&mut uart_tx, &mut uart_pipe_reader),
123 );
124
125 // Run everything concurrently.
126 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
127 join3(usb_fut, usb_future, uart_future).await;
128}
129
130struct Disconnected {}
131
132impl From<EndpointError> for Disconnected {
133 fn from(val: EndpointError) -> Self {
134 match val {
135 EndpointError::BufferOverflow => panic!("Buffer overflow"),
136 EndpointError::Disabled => Disconnected {},
137 }
138 }
139}
140
141/// Read from the USB and write it to the UART TX pipe
142async fn usb_read<'d, T: Instance + 'd>(
143 usb_rx: &mut Receiver<'d, Driver<'d, T>>,
144 uart_pipe_writer: &mut embassy_sync::pipe::Writer<'_, NoopRawMutex, 20>,
145) -> Result<(), Disconnected> {
146 let mut buf = [0; 64];
147 loop {
148 let n = usb_rx.read_packet(&mut buf).await?;
149 let data = &buf[..n];
150 trace!("USB IN: {:x}", data);
151 uart_pipe_writer.write(data).await;
152 }
153}
154
155/// Read from the USB TX pipe and write it to the USB
156async fn usb_write<'d, T: Instance + 'd>(
157 usb_tx: &mut Sender<'d, Driver<'d, T>>,
158 usb_pipe_reader: &mut embassy_sync::pipe::Reader<'_, NoopRawMutex, 20>,
159) -> Result<(), Disconnected> {
160 let mut buf = [0; 64];
161 loop {
162 let n = usb_pipe_reader.read(&mut buf).await;
163 let data = &buf[..n];
164 trace!("USB OUT: {:x}", data);
165 usb_tx.write_packet(&data).await?;
166 }
167}
168
169/// Read from the UART and write it to the USB TX pipe
170async fn uart_read(
171 uart_rx: &mut PioUartRx<'_>,
172 usb_pipe_writer: &mut embassy_sync::pipe::Writer<'_, NoopRawMutex, 20>,
173) -> ! {
174 let mut buf = [0; 64];
175 loop {
176 let n = uart_rx.read(&mut buf).await.expect("UART read error");
177 if n == 0 {
178 continue;
179 }
180 let data = &buf[..n];
181 trace!("UART IN: {:x}", buf);
182 usb_pipe_writer.write(data).await;
183 }
184}
185
186/// Read from the UART TX pipe and write it to the UART
187async fn uart_write(
188 uart_tx: &mut PioUartTx<'_>,
189 uart_pipe_reader: &mut embassy_sync::pipe::Reader<'_, NoopRawMutex, 20>,
190) -> ! {
191 let mut buf = [0; 64];
192 loop {
193 let n = uart_pipe_reader.read(&mut buf).await;
194 let data = &buf[..n];
195 trace!("UART OUT: {:x}", data);
196 let _ = uart_tx.write(&data).await;
197 }
198}
199
200mod uart {
201 use embassy_rp::peripherals::PIO0;
202 use embassy_rp::pio::{Pio, PioPin};
203 use embassy_rp::Peripheral;
204
205 use crate::uart_rx::PioUartRx;
206 use crate::uart_tx::PioUartTx;
207 use crate::Irqs;
208
209 pub struct PioUart<'a> {
210 tx: PioUartTx<'a>,
211 rx: PioUartRx<'a>,
212 }
213
214 impl<'a> PioUart<'a> {
215 pub fn new(
216 baud: u64,
217 pio: impl Peripheral<P = PIO0> + 'a,
218 tx_pin: impl PioPin,
219 rx_pin: impl PioPin,
220 ) -> PioUart<'a> {
221 let Pio {
222 mut common, sm0, sm1, ..
223 } = Pio::new(pio, Irqs);
224
225 let tx = PioUartTx::new(&mut common, sm0, tx_pin, baud);
226 let rx = PioUartRx::new(&mut common, sm1, rx_pin, baud);
227
228 PioUart { tx, rx }
229 }
230
231 pub fn split(self) -> (PioUartTx<'a>, PioUartRx<'a>) {
232 (self.tx, self.rx)
233 }
234 }
235}
236
237mod uart_tx {
238 use core::convert::Infallible;
239
240 use embassy_rp::gpio::Level;
241 use embassy_rp::peripherals::PIO0;
242 use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine};
243 use embedded_io::asynch::Write;
244 use embedded_io::Io;
245 use fixed::traits::ToFixed;
246 use fixed_macro::types::U56F8;
247
248 pub struct PioUartTx<'a> {
249 sm_tx: StateMachine<'a, PIO0, 0>,
250 }
251
252 impl<'a> PioUartTx<'a> {
253 pub fn new(
254 common: &mut Common<'a, PIO0>,
255 mut sm_tx: StateMachine<'a, PIO0, 0>,
256 tx_pin: impl PioPin,
257 baud: u64,
258 ) -> Self {
259 let prg = pio_proc::pio_asm!(
260 r#"
261 .side_set 1 opt
262
263 ; An 8n1 UART transmit program.
264 ; OUT pin 0 and side-set pin 0 are both mapped to UART TX pin.
265
266 pull side 1 [7] ; Assert stop bit, or stall with line in idle state
267 set x, 7 side 0 [7] ; Preload bit counter, assert start bit for 8 clocks
268 bitloop: ; This loop will run 8 times (8n1 UART)
269 out pins, 1 ; Shift 1 bit from OSR to the first OUT pin
270 jmp x-- bitloop [6] ; Each loop iteration is 8 cycles.
271 "#
272 );
273 let tx_pin = common.make_pio_pin(tx_pin);
274 sm_tx.set_pins(Level::High, &[&tx_pin]);
275 sm_tx.set_pin_dirs(Direction::Out, &[&tx_pin]);
276
277 let mut cfg = Config::default();
278
279 cfg.set_out_pins(&[&tx_pin]);
280 cfg.use_program(&common.load_program(&prg.program), &[&tx_pin]);
281 cfg.shift_out.auto_fill = false;
282 cfg.shift_out.direction = ShiftDirection::Right;
283 cfg.fifo_join = FifoJoin::TxOnly;
284 cfg.clock_divider = (U56F8!(125_000_000) / (8 * baud)).to_fixed();
285 sm_tx.set_config(&cfg);
286 sm_tx.set_enable(true);
287
288 Self { sm_tx }
289 }
290
291 pub async fn write_u8(&mut self, data: u8) {
292 self.sm_tx.tx().wait_push(data as u32).await;
293 }
294 }
295
296 impl Io for PioUartTx<'_> {
297 type Error = Infallible;
298 }
299
300 impl Write for PioUartTx<'_> {
301 async fn write(&mut self, buf: &[u8]) -> Result<usize, Infallible> {
302 for byte in buf {
303 self.write_u8(*byte).await;
304 }
305 Ok(buf.len())
306 }
307 }
308}
309
310mod uart_rx {
311 use core::convert::Infallible;
312
313 use embassy_rp::gpio::Level;
314 use embassy_rp::peripherals::PIO0;
315 use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine};
316 use embedded_io::asynch::Read;
317 use embedded_io::Io;
318 use fixed::traits::ToFixed;
319 use fixed_macro::types::U56F8;
320
321 pub struct PioUartRx<'a> {
322 sm_rx: StateMachine<'a, PIO0, 1>,
323 }
324
325 impl<'a> PioUartRx<'a> {
326 pub fn new(
327 common: &mut Common<'a, PIO0>,
328 mut sm_rx: StateMachine<'a, PIO0, 1>,
329 rx_pin: impl PioPin,
330 baud: u64,
331 ) -> Self {
332 let prg = pio_proc::pio_asm!(
333 r#"
334 ; Slightly more fleshed-out 8n1 UART receiver which handles framing errors and
335 ; break conditions more gracefully.
336 ; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX.
337
338 start:
339 wait 0 pin 0 ; Stall until start bit is asserted
340 set x, 7 [10] ; Preload bit counter, then delay until halfway through
341 rx_bitloop: ; the first data bit (12 cycles incl wait, set).
342 in pins, 1 ; Shift data bit into ISR
343 jmp x-- rx_bitloop [6] ; Loop 8 times, each loop iteration is 8 cycles
344 jmp pin good_rx_stop ; Check stop bit (should be high)
345
346 irq 4 rel ; Either a framing error or a break. Set a sticky flag,
347 wait 1 pin 0 ; and wait for line to return to idle state.
348 jmp start ; Don't push data if we didn't see good framing.
349
350 good_rx_stop: ; No delay before returning to start; a little slack is
351 in null 24
352 push ; important in case the TX clock is slightly too fast.
353 "#
354 );
355 let mut cfg = Config::default();
356 cfg.use_program(&common.load_program(&prg.program), &[]);
357
358 let rx_pin = common.make_pio_pin(rx_pin);
359 sm_rx.set_pins(Level::High, &[&rx_pin]);
360 cfg.set_in_pins(&[&rx_pin]);
361 cfg.set_jmp_pin(&rx_pin);
362 sm_rx.set_pin_dirs(Direction::In, &[&rx_pin]);
363
364 cfg.clock_divider = (U56F8!(125_000_000) / (8 * baud)).to_fixed();
365 cfg.shift_in.auto_fill = false;
366 cfg.shift_in.direction = ShiftDirection::Right;
367 cfg.shift_in.threshold = 32;
368 cfg.fifo_join = FifoJoin::RxOnly;
369 sm_rx.set_config(&cfg);
370 sm_rx.set_enable(true);
371
372 Self { sm_rx }
373 }
374
375 pub async fn read_u8(&mut self) -> u8 {
376 self.sm_rx.rx().wait_pull().await as u8
377 }
378 }
379
380 impl Io for PioUartRx<'_> {
381 type Error = Infallible;
382 }
383
384 impl Read for PioUartRx<'_> {
385 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Infallible> {
386 let mut i = 0;
387 while i < buf.len() {
388 buf[i] = self.read_u8().await;
389 i += 1;
390 }
391 Ok(i)
392 }
393 }
394}
diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs
index 3de2bd48d..bc87016ec 100644
--- a/examples/rp/src/bin/pio_ws2812.rs
+++ b/examples/rp/src/bin/pio_ws2812.rs
@@ -12,7 +12,6 @@ use embassy_rp::peripherals::PIO0;
12use embassy_rp::pio::{ 12use embassy_rp::pio::{
13 Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, 13 Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine,
14}; 14};
15use embassy_rp::relocate::RelocatedProgram;
16use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; 15use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef};
17use embassy_time::{Duration, Timer}; 16use embassy_time::{Duration, Timer};
18use fixed::types::U24F8; 17use fixed::types::U24F8;
@@ -73,8 +72,7 @@ impl<'d, P: Instance, const S: usize, const N: usize> Ws2812<'d, P, S, N> {
73 cfg.set_out_pins(&[&out_pin]); 72 cfg.set_out_pins(&[&out_pin]);
74 cfg.set_set_pins(&[&out_pin]); 73 cfg.set_set_pins(&[&out_pin]);
75 74
76 let relocated = RelocatedProgram::new(&prg); 75 cfg.use_program(&pio.load_program(&prg), &[&out_pin]);
77 cfg.use_program(&pio.load_program(&relocated), &[&out_pin]);
78 76
79 // Clock config, measured in kHz to avoid overflows 77 // Clock config, measured in kHz to avoid overflows
80 // TODO CLOCK_FREQ should come from embassy_rp 78 // TODO CLOCK_FREQ should come from embassy_rp
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index 92933ab50..42adede10 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -23,3 +23,6 @@ clap = { version = "3.0.0-beta.5", features = ["derive"] }
23rand_core = { version = "0.6.3", features = ["std"] } 23rand_core = { version = "0.6.3", features = ["std"] }
24heapless = { version = "0.7.5", default-features = false } 24heapless = { version = "0.7.5", default-features = false }
25static_cell = { version = "1.1", features = ["nightly"]} 25static_cell = { version = "1.1", features = ["nightly"]}
26
27[profile.release]
28debug = 2
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml
index e74c5357b..8534921ab 100644
--- a/examples/stm32c0/Cargo.toml
+++ b/examples/stm32c0/Cargo.toml
@@ -20,3 +20,6 @@ embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 20panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.7.5", default-features = false } 22heapless = { version = "0.7.5", default-features = false }
23
24[profile.release]
25debug = 2
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml
index 620a139ae..46b6db45c 100644
--- a/examples/stm32f0/Cargo.toml
+++ b/examples/stm32f0/Cargo.toml
@@ -18,3 +18,6 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de
18embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 18embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
19embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 19embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
20static_cell = { version = "1.1", features = ["nightly"]} 20static_cell = { version = "1.1", features = ["nightly"]}
21
22[profile.release]
23debug = 2
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index 8450c541f..5d32992cd 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -26,3 +26,6 @@ nb = "1.0.0"
26 26
27[profile.dev] 27[profile.dev]
28opt-level = "s" 28opt-level = "s"
29
30[profile.release]
31debug = 2
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml
index 147e2ecbf..9857fb631 100644
--- a/examples/stm32f2/Cargo.toml
+++ b/examples/stm32f2/Cargo.toml
@@ -21,3 +21,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.7.5", default-features = false } 22heapless = { version = "0.7.5", default-features = false }
23nb = "1.0.0" 23nb = "1.0.0"
24
25[profile.release]
26debug = 2
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index 6ac5d57e9..bd594d16a 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -25,3 +25,6 @@ heapless = { version = "0.7.5", default-features = false }
25nb = "1.0.0" 25nb = "1.0.0"
26embedded-storage = "0.3.0" 26embedded-storage = "0.3.0"
27static_cell = { version = "1.1", features = ["nightly"]} 27static_cell = { version = "1.1", features = ["nightly"]}
28
29[profile.release]
30debug = 2
diff --git a/examples/stm32f3/src/bin/spi_dma.rs b/examples/stm32f3/src/bin/spi_dma.rs
index 95b2b6865..a27c1d547 100644
--- a/examples/stm32f3/src/bin/spi_dma.rs
+++ b/examples/stm32f3/src/bin/spi_dma.rs
@@ -17,16 +17,10 @@ async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
18 info!("Hello World!"); 18 info!("Hello World!");
19 19
20 let mut spi = Spi::new( 20 let mut spi_config = Config::default();
21 p.SPI1, 21 spi_config.frequency = Hertz(1_000_000);
22 p.PB3, 22
23 p.PB5, 23 let mut spi = Spi::new(p.SPI1, p.PB3, p.PB5, p.PB4, p.DMA1_CH3, p.DMA1_CH2, spi_config);
24 p.PB4,
25 p.DMA1_CH3,
26 p.DMA1_CH2,
27 Hertz(1_000_000),
28 Config::default(),
29 );
30 24
31 for n in 0u32.. { 25 for n in 0u32.. {
32 let mut write: String<128> = String::new(); 26 let mut write: String<128> = String::new();
diff --git a/examples/stm32f334/.cargo/config.toml b/examples/stm32f334/.cargo/config.toml
new file mode 100644
index 000000000..caf947be6
--- /dev/null
+++ b/examples/stm32f334/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace STM32F429ZITx with your chip as listed in `probe-rs-cli chip list`
3runner = "probe-run --chip STM32F334R8"
4
5[build]
6target = "thumbv7em-none-eabihf"
7
8[env]
9DEFMT_LOG = "trace"
diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml
new file mode 100644
index 000000000..6410891a1
--- /dev/null
+++ b/examples/stm32f334/Cargo.toml
@@ -0,0 +1,26 @@
1[package]
2edition = "2021"
3name = "embassy-stm32f3-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
12embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
14
15defmt = "0.3"
16defmt-rtt = "0.4"
17
18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
19cortex-m-rt = "0.7.0"
20embedded-hal = "0.2.6"
21panic-probe = { version = "0.3", features = ["print-defmt"] }
22futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
23heapless = { version = "0.7.5", default-features = false }
24nb = "1.0.0"
25embedded-storage = "0.3.0"
26static_cell = { version = "1.1", features = ["nightly"]}
diff --git a/examples/stm32f334/build.rs b/examples/stm32f334/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32f334/build.rs
@@ -0,0 +1,5 @@
1fn main() {
2 println!("cargo:rustc-link-arg-bins=--nmagic");
3 println!("cargo:rustc-link-arg-bins=-Tlink.x");
4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
5}
diff --git a/examples/stm32f334/src/bin/button.rs b/examples/stm32f334/src/bin/button.rs
new file mode 100644
index 000000000..599c0f27d
--- /dev/null
+++ b/examples/stm32f334/src/bin/button.rs
@@ -0,0 +1,27 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer};
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 info!("Hello World!");
14
15 let p = embassy_stm32::init(Default::default());
16
17 let mut out1 = Output::new(p.PA8, Level::Low, Speed::High);
18
19 out1.set_high();
20 Timer::after(Duration::from_millis(500)).await;
21 out1.set_low();
22
23 Timer::after(Duration::from_millis(500)).await;
24 info!("end program");
25
26 cortex_m::asm::bkpt();
27}
diff --git a/examples/stm32f334/src/bin/hello.rs b/examples/stm32f334/src/bin/hello.rs
new file mode 100644
index 000000000..65773210d
--- /dev/null
+++ b/examples/stm32f334/src/bin/hello.rs
@@ -0,0 +1,23 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::info;
6use embassy_executor::Spawner;
7use embassy_stm32::time::Hertz;
8use embassy_stm32::Config;
9use embassy_time::{Duration, Timer};
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! {
14 let mut config = Config::default();
15 config.rcc.hse = Some(Hertz(8_000_000));
16 config.rcc.sysclk = Some(Hertz(16_000_000));
17 let _p = embassy_stm32::init(config);
18
19 loop {
20 info!("Hello World!");
21 Timer::after(Duration::from_secs(1)).await;
22 }
23}
diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs
new file mode 100644
index 000000000..2660b10c5
--- /dev/null
+++ b/examples/stm32f334/src/bin/pwm.rs
@@ -0,0 +1,71 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::hrtim::*;
8use embassy_stm32::time::{khz, mhz};
9use embassy_stm32::Config;
10use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let mut config: Config = Default::default();
16 config.rcc.sysclk = Some(mhz(64));
17 config.rcc.hclk = Some(mhz(64));
18 config.rcc.pclk1 = Some(mhz(32));
19 config.rcc.pclk2 = Some(mhz(64));
20
21 let p = embassy_stm32::init(config);
22 info!("Hello World!");
23
24 let ch1 = PwmPin::new_cha(p.PA8);
25 let ch1n = ComplementaryPwmPin::new_cha(p.PA9);
26 let pwm = AdvancedPwm::new(
27 p.HRTIM1,
28 Some(ch1),
29 Some(ch1n),
30 None,
31 None,
32 None,
33 None,
34 None,
35 None,
36 None,
37 None,
38 );
39
40 info!("pwm constructed");
41
42 let mut buck_converter = BridgeConverter::new(pwm.ch_a, khz(5));
43
44 // embassy_stm32::pac::HRTIM1
45 // .tim(0)
46 // .setr(0)
47 // .modify(|w| w.set_sst(Activeeffect::SETACTIVE));
48 //
49 // Timer::after(Duration::from_millis(500)).await;
50 //
51 // embassy_stm32::pac::HRTIM1
52 // .tim(0)
53 // .rstr(0)
54 // .modify(|w| w.set_srt(Inactiveeffect::SETINACTIVE));
55
56 let max_duty = buck_converter.get_max_compare_value();
57
58 info!("max compare value: {}", max_duty);
59
60 buck_converter.set_dead_time(max_duty / 20);
61 buck_converter.set_primary_duty(max_duty / 2);
62 buck_converter.set_secondary_duty(3 * max_duty / 4);
63
64 buck_converter.start();
65
66 Timer::after(Duration::from_millis(500)).await;
67
68 info!("end program");
69
70 cortex_m::asm::bkpt();
71}
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs
index d0b164393..496016687 100644
--- a/examples/stm32f4/src/bin/eth.rs
+++ b/examples/stm32f4/src/bin/eth.rs
@@ -11,13 +11,15 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{bind_interrupts, eth, Config}; 14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
17use static_cell::make_static; 17use static_cell::make_static;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19
19bind_interrupts!(struct Irqs { 20bind_interrupts!(struct Irqs {
20 ETH => eth::InterruptHandler; 21 ETH => eth::InterruptHandler;
22 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
21}); 23});
22 24
23type Device = Ethernet<'static, ETH, GenericSMI>; 25type Device = Ethernet<'static, ETH, GenericSMI>;
@@ -36,7 +38,7 @@ async fn main(spawner: Spawner) -> ! {
36 info!("Hello World!"); 38 info!("Hello World!");
37 39
38 // Generate random seed. 40 // Generate random seed.
39 let mut rng = Rng::new(p.RNG); 41 let mut rng = Rng::new(p.RNG, Irqs);
40 let mut seed = [0; 8]; 42 let mut seed = [0; 8];
41 let _ = rng.async_fill_bytes(&mut seed).await; 43 let _ = rng.async_fill_bytes(&mut seed).await;
42 let seed = u64::from_le_bytes(seed); 44 let seed = u64::from_le_bytes(seed);
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
index 7c5902052..1013a844e 100644
--- a/examples/stm32f4/src/bin/pwm.rs
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -4,9 +4,10 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm}; 7use embassy_stm32::gpio::OutputType;
8use embassy_stm32::pwm::Channel;
9use embassy_stm32::time::khz; 8use embassy_stm32::time::khz;
9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
10use embassy_stm32::timer::Channel;
10use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
12 13
@@ -15,7 +16,7 @@ async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
16 info!("Hello World!"); 17 info!("Hello World!");
17 18
18 let ch1 = PwmPin::new_ch1(p.PE9); 19 let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull);
19 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10)); 20 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10));
20 let max = pwm.get_max_duty(); 21 let max = pwm.get_max_duty();
21 pwm.enable(Channel::Ch1); 22 pwm.enable(Channel::Ch1);
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs
index a8a68ed6e..83a3c7537 100644
--- a/examples/stm32f4/src/bin/pwm_complementary.rs
+++ b/examples/stm32f4/src/bin/pwm_complementary.rs
@@ -4,10 +4,11 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::pwm::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; 7use embassy_stm32::gpio::OutputType;
8use embassy_stm32::pwm::simple_pwm::PwmPin;
9use embassy_stm32::pwm::Channel;
10use embassy_stm32::time::khz; 8use embassy_stm32::time::khz;
9use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
10use embassy_stm32::timer::simple_pwm::PwmPin;
11use embassy_stm32::timer::Channel;
11use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
13 14
@@ -16,8 +17,8 @@ async fn main(_spawner: Spawner) {
16 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
17 info!("Hello World!"); 18 info!("Hello World!");
18 19
19 let ch1 = PwmPin::new_ch1(p.PE9); 20 let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull);
20 let ch1n = ComplementaryPwmPin::new_ch1(p.PA7); 21 let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull);
21 let mut pwm = ComplementaryPwm::new( 22 let mut pwm = ComplementaryPwm::new(
22 p.TIM1, 23 p.TIM1,
23 Some(ch1), 24 Some(ch1),
diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs
index 05b48f478..0919e9874 100644
--- a/examples/stm32f4/src/bin/spi.rs
+++ b/examples/stm32f4/src/bin/spi.rs
@@ -16,16 +16,10 @@ fn main() -> ! {
16 16
17 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
18 18
19 let mut spi = Spi::new( 19 let mut spi_config = Config::default();
20 p.SPI3, 20 spi_config.frequency = Hertz(1_000_000);
21 p.PC10, 21
22 p.PC12, 22 let mut spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config);
23 p.PC11,
24 NoDma,
25 NoDma,
26 Hertz(1_000_000),
27 Config::default(),
28 );
29 23
30 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh); 24 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh);
31 25
diff --git a/examples/stm32f4/src/bin/spi_dma.rs b/examples/stm32f4/src/bin/spi_dma.rs
index 3d2a1a1ae..f291f7dba 100644
--- a/examples/stm32f4/src/bin/spi_dma.rs
+++ b/examples/stm32f4/src/bin/spi_dma.rs
@@ -17,16 +17,10 @@ async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
18 info!("Hello World!"); 18 info!("Hello World!");
19 19
20 let mut spi = Spi::new( 20 let mut spi_config = Config::default();
21 p.SPI1, 21 spi_config.frequency = Hertz(1_000_000);
22 p.PB3, 22
23 p.PB5, 23 let mut spi = Spi::new(p.SPI1, p.PB3, p.PB5, p.PB4, p.DMA2_CH3, p.DMA2_CH2, spi_config);
24 p.PB4,
25 p.DMA2_CH3,
26 p.DMA2_CH2,
27 Hertz(1_000_000),
28 Config::default(),
29 );
30 24
31 for n in 0u32.. { 25 for n in 0u32.. {
32 let mut write: String<128> = String::new(); 26 let mut write: String<128> = String::new();
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs
index b1f01417c..740d3018e 100644
--- a/examples/stm32f4/src/bin/usb_ethernet.rs
+++ b/examples/stm32f4/src/bin/usb_ethernet.rs
@@ -6,7 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_net::tcp::TcpSocket; 7use embassy_net::tcp::TcpSocket;
8use embassy_net::{Stack, StackResources}; 8use embassy_net::{Stack, StackResources};
9use embassy_stm32::rng::Rng; 9use embassy_stm32::rng::{self, Rng};
10use embassy_stm32::time::mhz; 10use embassy_stm32::time::mhz;
11use embassy_stm32::usb_otg::Driver; 11use embassy_stm32::usb_otg::Driver;
12use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 12use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
@@ -38,6 +38,7 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
38 38
39bind_interrupts!(struct Irqs { 39bind_interrupts!(struct Irqs {
40 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>; 40 OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
41 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
41}); 42});
42 43
43#[embassy_executor::main] 44#[embassy_executor::main]
@@ -104,7 +105,7 @@ async fn main(spawner: Spawner) {
104 //}); 105 //});
105 106
106 // Generate random seed 107 // Generate random seed
107 let mut rng = Rng::new(p.RNG); 108 let mut rng = Rng::new(p.RNG, Irqs);
108 let mut seed = [0; 8]; 109 let mut seed = [0; 8];
109 unwrap!(rng.async_fill_bytes(&mut seed).await); 110 unwrap!(rng.async_fill_bytes(&mut seed).await);
110 let seed = u64::from_le_bytes(seed); 111 let seed = u64::from_le_bytes(seed);
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index bbc99fee0..a379cbbe3 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8# Change stm32f767zi to your chip name, if necessary. 8# Change stm32f767zi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] }
10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
@@ -28,3 +28,6 @@ rand_core = "0.6.3"
28critical-section = "1.1" 28critical-section = "1.1"
29embedded-storage = "0.3.0" 29embedded-storage = "0.3.0"
30static_cell = { version = "1.1", features = ["nightly"]} 30static_cell = { version = "1.1", features = ["nightly"]}
31
32[profile.release]
33debug = 2
diff --git a/examples/stm32f7/build.rs b/examples/stm32f7/build.rs
index 2b5d412a9..8cd32d7ed 100644
--- a/examples/stm32f7/build.rs
+++ b/examples/stm32f7/build.rs
@@ -1,43 +1,5 @@
1//! adapted from https://github.com/stm32-rs/stm32f7xx-hal/blob/master/build.rs 1fn main() {
2use std::fs::File;
3use std::io::prelude::*;
4use std::path::PathBuf;
5use std::{env, io};
6
7#[derive(Debug)]
8enum Error {
9 Env(env::VarError),
10 Io(io::Error),
11}
12
13impl From<env::VarError> for Error {
14 fn from(error: env::VarError) -> Self {
15 Self::Env(error)
16 }
17}
18
19impl From<io::Error> for Error {
20 fn from(error: io::Error) -> Self {
21 Self::Io(error)
22 }
23}
24
25fn main() -> Result<(), Error> {
26 println!("cargo:rerun-if-changed=build.rs");
27 println!("cargo:rerun-if-changed=memory.x");
28
29 let out_dir = env::var("OUT_DIR")?;
30 let out_dir = PathBuf::from(out_dir);
31
32 let memory_x = include_bytes!("memory.x").as_ref();
33 File::create(out_dir.join("memory.x"))?.write_all(memory_x)?;
34
35 // Tell Cargo where to find the file.
36 println!("cargo:rustc-link-search={}", out_dir.display());
37
38 println!("cargo:rustc-link-arg-bins=--nmagic"); 2 println!("cargo:rustc-link-arg-bins=--nmagic");
39 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 3 println!("cargo:rustc-link-arg-bins=-Tlink.x");
40 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
41
42 Ok(())
43} 5}
diff --git a/examples/stm32f7/memory.x b/examples/stm32f7/memory.x
deleted file mode 100644
index 899f7a4b8..000000000
--- a/examples/stm32f7/memory.x
+++ /dev/null
@@ -1,12 +0,0 @@
1/* For STM32F765,767,768,769,777,778,779 devices */
2MEMORY
3{
4 /* NOTE K = KiBi = 1024 bytes */
5 FLASH : ORIGIN = 0x08000000, LENGTH = 2M
6 RAM : ORIGIN = 0x20000000, LENGTH = 368K + 16K
7}
8
9/* This is where the call stack will be allocated. */
10/* The stack is of the full descending type. */
11/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
12_stack_start = ORIGIN(RAM) + LENGTH(RAM);
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs
index c6b2ba45c..e5abf52bc 100644
--- a/examples/stm32f7/src/bin/eth.rs
+++ b/examples/stm32f7/src/bin/eth.rs
@@ -11,14 +11,16 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{bind_interrupts, eth, Config}; 14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
17use rand_core::RngCore; 17use rand_core::RngCore;
18use static_cell::make_static; 18use static_cell::make_static;
19use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
20
20bind_interrupts!(struct Irqs { 21bind_interrupts!(struct Irqs {
21 ETH => eth::InterruptHandler; 22 ETH => eth::InterruptHandler;
23 RNG => rng::InterruptHandler<peripherals::RNG>;
22}); 24});
23 25
24type Device = Ethernet<'static, ETH, GenericSMI>; 26type Device = Ethernet<'static, ETH, GenericSMI>;
@@ -37,7 +39,7 @@ async fn main(spawner: Spawner) -> ! {
37 info!("Hello World!"); 39 info!("Hello World!");
38 40
39 // Generate random seed. 41 // Generate random seed.
40 let mut rng = Rng::new(p.RNG); 42 let mut rng = Rng::new(p.RNG, Irqs);
41 let mut seed = [0; 8]; 43 let mut seed = [0; 8];
42 rng.fill_bytes(&mut seed); 44 rng.fill_bytes(&mut seed);
43 let seed = u64::from_le_bytes(seed); 45 let seed = u64::from_le_bytes(seed);
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index 4a14568ac..b4dfe3c6b 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -20,3 +20,6 @@ embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 20panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.7.5", default-features = false } 22heapless = { version = "0.7.5", default-features = false }
23
24[profile.release]
25debug = 2
diff --git a/examples/stm32g0/src/bin/spi_neopixel.rs b/examples/stm32g0/src/bin/spi_neopixel.rs
index 81fdd15cb..ee7aaf33f 100644
--- a/examples/stm32g0/src/bin/spi_neopixel.rs
+++ b/examples/stm32g0/src/bin/spi_neopixel.rs
@@ -76,7 +76,9 @@ async fn main(_spawner: Spawner) {
76 let p = embassy_stm32::init(Default::default()); 76 let p = embassy_stm32::init(Default::default());
77 info!("Start test using spi as neopixel driver"); 77 info!("Start test using spi as neopixel driver");
78 78
79 let mut spi = Spi::new_txonly_nosck(p.SPI1, p.PB5, p.DMA1_CH3, NoDma, Hertz(4_000_000), Config::default()); 79 let mut config = Config::default();
80 config.frequency = Hertz(4_000_000);
81 let mut spi = Spi::new_txonly_nosck(p.SPI1, p.PB5, p.DMA1_CH3, NoDma, config);
80 82
81 let mut neopixels = Ws2812::new(); 83 let mut neopixels = Ws2812::new();
82 84
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index 935997a74..cf3e2ce9b 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -10,7 +10,6 @@ embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["
10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
15 14
16defmt = "0.3" 15defmt = "0.3"
@@ -22,3 +21,6 @@ embedded-hal = "0.2.6"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "0.3", features = ["print-defmt"] }
23futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 22futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
24heapless = { version = "0.7.5", default-features = false } 23heapless = { version = "0.7.5", default-features = false }
24
25[profile.release]
26debug = 2
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index 8f7842ed7..01e9cb476 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -4,9 +4,10 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm}; 7use embassy_stm32::gpio::OutputType;
8use embassy_stm32::pwm::Channel;
9use embassy_stm32::time::khz; 8use embassy_stm32::time::khz;
9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
10use embassy_stm32::timer::Channel;
10use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
12 13
@@ -15,7 +16,7 @@ async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
16 info!("Hello World!"); 17 info!("Hello World!");
17 18
18 let ch1 = PwmPin::new_ch1(p.PC0); 19 let ch1 = PwmPin::new_ch1(p.PC0, OutputType::PushPull);
19 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10)); 20 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10));
20 let max = pwm.get_max_duty(); 21 let max = pwm.get_max_duty();
21 pwm.enable(Channel::Ch1); 22 pwm.enable(Channel::Ch1);
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index aebc795c1..51d3bad1f 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8# Change stm32h563zi to your chip name, if necessary. 8# Change stm32h563zi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
diff --git a/examples/stm32h5/memory.x b/examples/stm32h5/memory.x
deleted file mode 100644
index 456061509..000000000
--- a/examples/stm32h5/memory.x
+++ /dev/null
@@ -1,5 +0,0 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x08000000, LENGTH = 0x200000
4 RAM : ORIGIN = 0x20000000, LENGTH = 0x50000
5}
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs
index 0bff85ed8..2aa2ab62b 100644
--- a/examples/stm32h5/src/bin/eth.rs
+++ b/examples/stm32h5/src/bin/eth.rs
@@ -12,14 +12,16 @@ use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; 12use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale};
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
14use embassy_stm32::time::Hertz; 14use embassy_stm32::time::Hertz;
15use embassy_stm32::{bind_interrupts, eth, Config}; 15use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
16use embassy_time::{Duration, Timer}; 16use embassy_time::{Duration, Timer};
17use embedded_io::asynch::Write; 17use embedded_io::asynch::Write;
18use rand_core::RngCore; 18use rand_core::RngCore;
19use static_cell::make_static; 19use static_cell::make_static;
20use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
21
21bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
22 ETH => eth::InterruptHandler; 23 ETH => eth::InterruptHandler;
24 RNG => rng::InterruptHandler<peripherals::RNG>;
23}); 25});
24 26
25type Device = Ethernet<'static, ETH, GenericSMI>; 27type Device = Ethernet<'static, ETH, GenericSMI>;
@@ -56,7 +58,7 @@ async fn main(spawner: Spawner) -> ! {
56 info!("Hello World!"); 58 info!("Hello World!");
57 59
58 // Generate random seed. 60 // Generate random seed.
59 let mut rng = Rng::new(p.RNG); 61 let mut rng = Rng::new(p.RNG, Irqs);
60 let mut seed = [0; 8]; 62 let mut seed = [0; 8];
61 rng.fill_bytes(&mut seed); 63 rng.fill_bytes(&mut seed);
62 let seed = u64::from_le_bytes(seed); 64 let seed = u64::from_le_bytes(seed);
diff --git a/examples/stm32h5/src/bin/rng.rs b/examples/stm32h5/src/bin/rng.rs
index af9be0b62..7c8c50eca 100644
--- a/examples/stm32h5/src/bin/rng.rs
+++ b/examples/stm32h5/src/bin/rng.rs
@@ -5,14 +5,19 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rng::Rng; 7use embassy_stm32::rng::Rng;
8use embassy_stm32::{bind_interrupts, peripherals, rng};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(struct Irqs {
12 RNG => rng::InterruptHandler<peripherals::RNG>;
13});
14
10#[embassy_executor::main] 15#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 18 info!("Hello World!");
14 19
15 let mut rng = Rng::new(p.RNG); 20 let mut rng = Rng::new(p.RNG, Irqs);
16 21
17 let mut buf = [0u8; 16]; 22 let mut buf = [0u8; 16];
18 unwrap!(rng.async_fill_bytes(&mut buf).await); 23 unwrap!(rng.async_fill_bytes(&mut buf).await);
diff --git a/examples/stm32h7/.cargo/config.toml b/examples/stm32h7/.cargo/config.toml
index 5f680dbce..4160bf855 100644
--- a/examples/stm32h7/.cargo/config.toml
+++ b/examples/stm32h7/.cargo/config.toml
@@ -1,5 +1,5 @@
1[target.thumbv7em-none-eabihf] 1[target.thumbv7em-none-eabihf]
2runner = 'probe-rs run --chip STM32H743ZITx' 2runner = 'probe-rs run --chip STM32H7A3ZITxQ'
3 3
4[build] 4[build]
5target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 5target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index 2d82c0d0d..3c1232e67 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8# Change stm32h743bi to your chip name, if necessary. 8# Change stm32h743bi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "unstable-traits"] }
10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
diff --git a/examples/stm32h7/memory.x b/examples/stm32h7/memory.x
deleted file mode 100644
index 026b14b9b..000000000
--- a/examples/stm32h7/memory.x
+++ /dev/null
@@ -1,5 +0,0 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x8000000, LENGTH = 1024K
4 RAM : ORIGIN = 0x24000000, LENGTH = 384K
5}
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
new file mode 100644
index 000000000..a9cb5d1ed
--- /dev/null
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -0,0 +1,140 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::dac::{DacChannel, ValueArray};
8use embassy_stm32::pac::timer::vals::{Mms, Opm};
9use embassy_stm32::peripherals::{TIM6, TIM7};
10use embassy_stm32::rcc::low_level::RccPeripheral;
11use embassy_stm32::time::{mhz, Hertz};
12use embassy_stm32::timer::low_level::Basic16bitInstance;
13use micromath::F32Ext;
14use {defmt_rtt as _, panic_probe as _};
15
16pub type Dac1Type =
17 embassy_stm32::dac::DacCh1<'static, embassy_stm32::peripherals::DAC1, embassy_stm32::peripherals::DMA1_CH3>;
18
19pub type Dac2Type =
20 embassy_stm32::dac::DacCh2<'static, embassy_stm32::peripherals::DAC1, embassy_stm32::peripherals::DMA1_CH4>;
21
22#[embassy_executor::main]
23async fn main(spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default();
25 config.rcc.sys_ck = Some(mhz(400));
26 config.rcc.hclk = Some(mhz(100));
27 config.rcc.pll1.q_ck = Some(mhz(100));
28
29 // Initialize the board and obtain a Peripherals instance
30 let p: embassy_stm32::Peripherals = embassy_stm32::init(config);
31
32 // Obtain two independent channels (p.DAC1 can only be consumed once, though!)
33 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split();
34
35 spawner.spawn(dac_task1(dac_ch1)).ok();
36 spawner.spawn(dac_task2(dac_ch2)).ok();
37}
38
39#[embassy_executor::task]
40async fn dac_task1(mut dac: Dac1Type) {
41 let data: &[u8; 256] = &calculate_array::<256>();
42
43 info!("TIM6 frequency is {}", TIM6::frequency());
44 const FREQUENCY: Hertz = Hertz::hz(200);
45
46 // Compute the reload value such that we obtain the FREQUENCY for the sine
47 let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32;
48
49 // Depends on your clock and on the specific chip used, you may need higher or lower values here
50 if reload < 10 {
51 error!("Reload value {} below threshold!", reload);
52 }
53
54 dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap();
55 dac.enable_channel().unwrap();
56
57 TIM6::enable();
58 TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
59 TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
60 TIM6::regs().cr1().modify(|w| {
61 w.set_opm(Opm::DISABLED);
62 w.set_cen(true);
63 });
64
65 debug!(
66 "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
67 TIM6::frequency(),
68 FREQUENCY,
69 reload,
70 reload as u16,
71 data.len()
72 );
73
74 // Loop technically not necessary if DMA circular mode is enabled
75 loop {
76 info!("Loop DAC1");
77 if let Err(e) = dac.write(ValueArray::Bit8(data), true).await {
78 error!("Could not write to dac: {}", e);
79 }
80 }
81}
82
83#[embassy_executor::task]
84async fn dac_task2(mut dac: Dac2Type) {
85 let data: &[u8; 256] = &calculate_array::<256>();
86
87 info!("TIM7 frequency is {}", TIM7::frequency());
88
89 const FREQUENCY: Hertz = Hertz::hz(600);
90 let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32;
91
92 if reload < 10 {
93 error!("Reload value {} below threshold!", reload);
94 }
95
96 TIM7::enable();
97 TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
98 TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
99 TIM7::regs().cr1().modify(|w| {
100 w.set_opm(Opm::DISABLED);
101 w.set_cen(true);
102 });
103
104 dac.select_trigger(embassy_stm32::dac::Ch2Trigger::Tim7).unwrap();
105
106 debug!(
107 "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
108 TIM7::frequency(),
109 FREQUENCY,
110 reload,
111 reload as u16,
112 data.len()
113 );
114
115 if let Err(e) = dac.write(ValueArray::Bit8(data), true).await {
116 error!("Could not write to dac: {}", e);
117 }
118}
119
120fn to_sine_wave(v: u8) -> u8 {
121 if v >= 128 {
122 // top half
123 let r = 3.14 * ((v - 128) as f32 / 128.0);
124 (r.sin() * 128.0 + 127.0) as u8
125 } else {
126 // bottom half
127 let r = 3.14 + 3.14 * (v as f32 / 128.0);
128 (r.sin() * 128.0 + 127.0) as u8
129 }
130}
131
132fn calculate_array<const N: usize>() -> [u8; N] {
133 let mut res = [0; N];
134 let mut i = 0;
135 while i < N {
136 res[i] = to_sine_wave(i as u8);
137 i += 1;
138 }
139 res
140}
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index cfafcaed1..c93be9f00 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -11,14 +11,16 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{bind_interrupts, eth, Config}; 14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
17use rand_core::RngCore; 17use rand_core::RngCore;
18use static_cell::make_static; 18use static_cell::make_static;
19use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
20
20bind_interrupts!(struct Irqs { 21bind_interrupts!(struct Irqs {
21 ETH => eth::InterruptHandler; 22 ETH => eth::InterruptHandler;
23 RNG => rng::InterruptHandler<peripherals::RNG>;
22}); 24});
23 25
24type Device = Ethernet<'static, ETH, GenericSMI>; 26type Device = Ethernet<'static, ETH, GenericSMI>;
@@ -38,7 +40,7 @@ async fn main(spawner: Spawner) -> ! {
38 info!("Hello World!"); 40 info!("Hello World!");
39 41
40 // Generate random seed. 42 // Generate random seed.
41 let mut rng = Rng::new(p.RNG); 43 let mut rng = Rng::new(p.RNG, Irqs);
42 let mut seed = [0; 8]; 44 let mut seed = [0; 8];
43 rng.fill_bytes(&mut seed); 45 rng.fill_bytes(&mut seed);
44 let seed = u64::from_le_bytes(seed); 46 let seed = u64::from_le_bytes(seed);
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index 4ed737578..78005e91f 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -11,15 +11,17 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{bind_interrupts, eth, Config}; 14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
17use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; 17use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect};
18use rand_core::RngCore; 18use rand_core::RngCore;
19use static_cell::make_static; 19use static_cell::make_static;
20use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
21
21bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
22 ETH => eth::InterruptHandler; 23 ETH => eth::InterruptHandler;
24 RNG => rng::InterruptHandler<peripherals::RNG>;
23}); 25});
24 26
25type Device = Ethernet<'static, ETH, GenericSMI>; 27type Device = Ethernet<'static, ETH, GenericSMI>;
@@ -39,7 +41,7 @@ async fn main(spawner: Spawner) -> ! {
39 info!("Hello World!"); 41 info!("Hello World!");
40 42
41 // Generate random seed. 43 // Generate random seed.
42 let mut rng = Rng::new(p.RNG); 44 let mut rng = Rng::new(p.RNG, Irqs);
43 let mut seed = [0; 8]; 45 let mut seed = [0; 8];
44 rng.fill_bytes(&mut seed); 46 rng.fill_bytes(&mut seed);
45 let seed = u64::from_le_bytes(seed); 47 let seed = u64::from_le_bytes(seed);
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index d360df085..45b0872b5 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -6,8 +6,8 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::low_level::AFType; 7use embassy_stm32::gpio::low_level::AFType;
8use embassy_stm32::gpio::Speed; 8use embassy_stm32::gpio::Speed;
9use embassy_stm32::pwm::*;
10use embassy_stm32::time::{khz, mhz, Hertz}; 9use embassy_stm32::time::{khz, mhz, Hertz};
10use embassy_stm32::timer::*;
11use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef}; 11use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef};
12use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index c5c0dd290..aa5ec1bcf 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -4,9 +4,10 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm}; 7use embassy_stm32::gpio::OutputType;
8use embassy_stm32::pwm::Channel;
9use embassy_stm32::time::{khz, mhz}; 8use embassy_stm32::time::{khz, mhz};
9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
10use embassy_stm32::timer::Channel;
10use embassy_stm32::Config; 11use embassy_stm32::Config;
11use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -24,7 +25,7 @@ async fn main(_spawner: Spawner) {
24 let p = embassy_stm32::init(config); 25 let p = embassy_stm32::init(config);
25 info!("Hello World!"); 26 info!("Hello World!");
26 27
27 let ch1 = PwmPin::new_ch1(p.PA6); 28 let ch1 = PwmPin::new_ch1(p.PA6, OutputType::PushPull);
28 let mut pwm = SimplePwm::new(p.TIM3, Some(ch1), None, None, None, khz(10)); 29 let mut pwm = SimplePwm::new(p.TIM3, Some(ch1), None, None, None, khz(10));
29 let max = pwm.get_max_duty(); 30 let max = pwm.get_max_duty();
30 pwm.enable(Channel::Ch1); 31 pwm.enable(Channel::Ch1);
diff --git a/examples/stm32h7/src/bin/rng.rs b/examples/stm32h7/src/bin/rng.rs
index af9be0b62..7c8c50eca 100644
--- a/examples/stm32h7/src/bin/rng.rs
+++ b/examples/stm32h7/src/bin/rng.rs
@@ -5,14 +5,19 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rng::Rng; 7use embassy_stm32::rng::Rng;
8use embassy_stm32::{bind_interrupts, peripherals, rng};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(struct Irqs {
12 RNG => rng::InterruptHandler<peripherals::RNG>;
13});
14
10#[embassy_executor::main] 15#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 18 info!("Hello World!");
14 19
15 let mut rng = Rng::new(p.RNG); 20 let mut rng = Rng::new(p.RNG, Irqs);
16 21
17 let mut buf = [0u8; 16]; 22 let mut buf = [0u8; 16];
18 unwrap!(rng.async_fill_bytes(&mut buf).await); 23 unwrap!(rng.async_fill_bytes(&mut buf).await);
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index 1f407f002..28bba2b8d 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -43,16 +43,10 @@ fn main() -> ! {
43 config.rcc.pll1.q_ck = Some(mhz(100)); 43 config.rcc.pll1.q_ck = Some(mhz(100));
44 let p = embassy_stm32::init(config); 44 let p = embassy_stm32::init(config);
45 45
46 let spi = spi::Spi::new( 46 let mut spi_config = spi::Config::default();
47 p.SPI3, 47 spi_config.frequency = mhz(1);
48 p.PB3, 48
49 p.PB5, 49 let spi = spi::Spi::new(p.SPI3, p.PB3, p.PB5, p.PB4, NoDma, NoDma, spi_config);
50 p.PB4,
51 NoDma,
52 NoDma,
53 mhz(1),
54 spi::Config::default(),
55 );
56 50
57 let executor = EXECUTOR.init(Executor::new()); 51 let executor = EXECUTOR.init(Executor::new());
58 52
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 53004fc9b..f6e30cfa5 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -39,16 +39,10 @@ fn main() -> ! {
39 config.rcc.pll1.q_ck = Some(mhz(100)); 39 config.rcc.pll1.q_ck = Some(mhz(100));
40 let p = embassy_stm32::init(config); 40 let p = embassy_stm32::init(config);
41 41
42 let spi = spi::Spi::new( 42 let mut spi_config = spi::Config::default();
43 p.SPI3, 43 spi_config.frequency = mhz(1);
44 p.PB3, 44
45 p.PB5, 45 let spi = spi::Spi::new(p.SPI3, p.PB3, p.PB5, p.PB4, p.DMA1_CH3, p.DMA1_CH4, spi_config);
46 p.PB4,
47 p.DMA1_CH3,
48 p.DMA1_CH4,
49 mhz(1),
50 spi::Config::default(),
51 );
52 46
53 let executor = EXECUTOR.init(Executor::new()); 47 let executor = EXECUTOR.init(Executor::new());
54 48
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index e6a5a4c14..c325751c6 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -34,5 +34,5 @@ heapless = { version = "0.7.5", default-features = false }
34embedded-hal = "0.2.6" 34embedded-hal = "0.2.6"
35static_cell = "1.1" 35static_cell = "1.1"
36 36
37[patch.crates-io] 37[profile.release]
38lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } 38debug = 2
diff --git a/examples/stm32l0/src/bin/lora_cad.rs b/examples/stm32l0/src/bin/lora_cad.rs
index 588cea1e5..7729b4163 100644
--- a/examples/stm32l0/src/bin/lora_cad.rs
+++ b/examples/stm32l0/src/bin/lora_cad.rs
@@ -27,17 +27,11 @@ async fn main(_spawner: Spawner) {
27 config.rcc.enable_hsi48 = true; 27 config.rcc.enable_hsi48 = true;
28 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
29 29
30 let mut spi_config = spi::Config::default();
31 spi_config.frequency = khz(200);
32
30 // SPI for sx1276 33 // SPI for sx1276
31 let spi = spi::Spi::new( 34 let spi = spi::Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, p.DMA1_CH3, p.DMA1_CH2, spi_config);
32 p.SPI1,
33 p.PB3,
34 p.PA7,
35 p.PA6,
36 p.DMA1_CH3,
37 p.DMA1_CH2,
38 khz(200),
39 spi::Config::default(),
40 );
41 35
42 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low); 36 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low);
43 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low); 37 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low);
diff --git a/examples/stm32l0/src/bin/lora_lorawan.rs b/examples/stm32l0/src/bin/lora_lorawan.rs
index c397edd58..10608aebf 100644
--- a/examples/stm32l0/src/bin/lora_lorawan.rs
+++ b/examples/stm32l0/src/bin/lora_lorawan.rs
@@ -12,8 +12,8 @@ use embassy_lora::LoraTimer;
12use embassy_stm32::exti::{Channel, ExtiInput}; 12use embassy_stm32::exti::{Channel, ExtiInput};
13use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed}; 13use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed};
14use embassy_stm32::rng::Rng; 14use embassy_stm32::rng::Rng;
15use embassy_stm32::spi;
16use embassy_stm32::time::khz; 15use embassy_stm32::time::khz;
16use embassy_stm32::{bind_interrupts, peripherals, rng, spi};
17use embassy_time::Delay; 17use embassy_time::Delay;
18use lora_phy::mod_params::*; 18use lora_phy::mod_params::*;
19use lora_phy::sx1276_7_8_9::SX1276_7_8_9; 19use lora_phy::sx1276_7_8_9::SX1276_7_8_9;
@@ -23,6 +23,10 @@ use lorawan_device::async_device::lora_radio::LoRaRadio;
23use lorawan_device::async_device::{region, Device, JoinMode}; 23use lorawan_device::async_device::{region, Device, JoinMode};
24use {defmt_rtt as _, panic_probe as _}; 24use {defmt_rtt as _, panic_probe as _};
25 25
26bind_interrupts!(struct Irqs {
27 RNG_LPUART1 => rng::InterruptHandler<peripherals::RNG>;
28});
29
26const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region 30const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region
27 31
28#[embassy_executor::main] 32#[embassy_executor::main]
@@ -32,17 +36,11 @@ async fn main(_spawner: Spawner) {
32 config.rcc.enable_hsi48 = true; 36 config.rcc.enable_hsi48 = true;
33 let p = embassy_stm32::init(config); 37 let p = embassy_stm32::init(config);
34 38
39 let mut spi_config = spi::Config::default();
40 spi_config.frequency = khz(200);
41
35 // SPI for sx1276 42 // SPI for sx1276
36 let spi = spi::Spi::new( 43 let spi = spi::Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, p.DMA1_CH3, p.DMA1_CH2, spi_config);
37 p.SPI1,
38 p.PB3,
39 p.PA7,
40 p.PA6,
41 p.DMA1_CH3,
42 p.DMA1_CH2,
43 khz(200),
44 spi::Config::default(),
45 );
46 44
47 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low); 45 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low);
48 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low); 46 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low);
@@ -66,7 +64,7 @@ async fn main(_spawner: Spawner) {
66 64
67 let radio = LoRaRadio::new(lora); 65 let radio = LoRaRadio::new(lora);
68 let region: region::Configuration = region::Configuration::new(LORAWAN_REGION); 66 let region: region::Configuration = region::Configuration::new(LORAWAN_REGION);
69 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG)); 67 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG, Irqs));
70 68
71 defmt::info!("Joining LoRaWAN network"); 69 defmt::info!("Joining LoRaWAN network");
72 70
diff --git a/examples/stm32l0/src/bin/lora_p2p_receive.rs b/examples/stm32l0/src/bin/lora_p2p_receive.rs
index bb7509509..0f9f60952 100644
--- a/examples/stm32l0/src/bin/lora_p2p_receive.rs
+++ b/examples/stm32l0/src/bin/lora_p2p_receive.rs
@@ -27,17 +27,11 @@ async fn main(_spawner: Spawner) {
27 config.rcc.enable_hsi48 = true; 27 config.rcc.enable_hsi48 = true;
28 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
29 29
30 let mut spi_config = spi::Config::default();
31 spi_config.frequency = khz(200);
32
30 // SPI for sx1276 33 // SPI for sx1276
31 let spi = spi::Spi::new( 34 let spi = spi::Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, p.DMA1_CH3, p.DMA1_CH2, spi_config);
32 p.SPI1,
33 p.PB3,
34 p.PA7,
35 p.PA6,
36 p.DMA1_CH3,
37 p.DMA1_CH2,
38 khz(200),
39 spi::Config::default(),
40 );
41 35
42 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low); 36 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low);
43 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low); 37 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low);
diff --git a/examples/stm32l0/src/bin/lora_p2p_send.rs b/examples/stm32l0/src/bin/lora_p2p_send.rs
index e6fadc01d..c85c3c2b6 100644
--- a/examples/stm32l0/src/bin/lora_p2p_send.rs
+++ b/examples/stm32l0/src/bin/lora_p2p_send.rs
@@ -27,17 +27,11 @@ async fn main(_spawner: Spawner) {
27 config.rcc.enable_hsi48 = true; 27 config.rcc.enable_hsi48 = true;
28 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
29 29
30 let mut spi_config = spi::Config::default();
31 spi_config.frequency = khz(200);
32
30 // SPI for sx1276 33 // SPI for sx1276
31 let spi = spi::Spi::new( 34 let spi = spi::Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, p.DMA1_CH3, p.DMA1_CH2, spi_config);
32 p.SPI1,
33 p.PB3,
34 p.PA7,
35 p.PA6,
36 p.DMA1_CH3,
37 p.DMA1_CH2,
38 khz(200),
39 spi::Config::default(),
40 );
41 35
42 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low); 36 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low);
43 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low); 37 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low);
diff --git a/examples/stm32l0/src/bin/spi.rs b/examples/stm32l0/src/bin/spi.rs
index 9b5b3e27d..583e3d127 100644
--- a/examples/stm32l0/src/bin/spi.rs
+++ b/examples/stm32l0/src/bin/spi.rs
@@ -15,16 +15,10 @@ async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 15 let p = embassy_stm32::init(Default::default());
16 info!("Hello World, folks!"); 16 info!("Hello World, folks!");
17 17
18 let mut spi = Spi::new( 18 let mut spi_config = Config::default();
19 p.SPI1, 19 spi_config.frequency = Hertz(1_000_000);
20 p.PB3, 20
21 p.PA7, 21 let mut spi = Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, NoDma, NoDma, spi_config);
22 p.PA6,
23 NoDma,
24 NoDma,
25 Hertz(1_000_000),
26 Config::default(),
27 );
28 22
29 let mut cs = Output::new(p.PA15, Level::High, Speed::VeryHigh); 23 let mut cs = Output::new(p.PA15, Level::High, Speed::VeryHigh);
30 24
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml
index dcca1cc3d..329d44cac 100644
--- a/examples/stm32l1/Cargo.toml
+++ b/examples/stm32l1/Cargo.toml
@@ -20,3 +20,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
20futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 20futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
21heapless = { version = "0.7.5", default-features = false } 21heapless = { version = "0.7.5", default-features = false }
22embedded-storage = "0.3.0" 22embedded-storage = "0.3.0"
23
24[profile.release]
25debug = 2
diff --git a/examples/stm32l1/src/bin/spi.rs b/examples/stm32l1/src/bin/spi.rs
index 0a532e8e3..905b4d75c 100644
--- a/examples/stm32l1/src/bin/spi.rs
+++ b/examples/stm32l1/src/bin/spi.rs
@@ -15,16 +15,10 @@ async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 15 let p = embassy_stm32::init(Default::default());
16 info!("Hello World, folks!"); 16 info!("Hello World, folks!");
17 17
18 let mut spi = Spi::new( 18 let mut spi_config = Config::default();
19 p.SPI1, 19 spi_config.frequency = Hertz(1_000_000);
20 p.PA5, 20
21 p.PA7, 21 let mut spi = Spi::new(p.SPI1, p.PA5, p.PA7, p.PA6, NoDma, NoDma, spi_config);
22 p.PA6,
23 NoDma,
24 NoDma,
25 Hertz(1_000_000),
26 Config::default(),
27 );
28 22
29 let mut cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); 23 let mut cs = Output::new(p.PA4, Level::High, Speed::VeryHigh);
30 24
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 41c9869bf..3b27d8e81 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8# Change stm32l4s5vi to your chip name, if necessary. 8# Change stm32l4s5vi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits", "chrono"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] }
10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
@@ -27,3 +27,6 @@ heapless = { version = "0.7.5", default-features = false }
27chrono = { version = "^0.4", default-features = false } 27chrono = { version = "^0.4", default-features = false }
28 28
29micromath = "2.0.0" 29micromath = "2.0.0"
30
31[profile.release]
32debug = 2
diff --git a/examples/stm32l4/build.rs b/examples/stm32l4/build.rs
index 30691aa97..8cd32d7ed 100644
--- a/examples/stm32l4/build.rs
+++ b/examples/stm32l4/build.rs
@@ -1,34 +1,4 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() { 1fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 2 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 3 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
diff --git a/examples/stm32l4/memory.x b/examples/stm32l4/memory.x
deleted file mode 100644
index eb87d1b54..000000000
--- a/examples/stm32l4/memory.x
+++ /dev/null
@@ -1,7 +0,0 @@
1MEMORY
2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 /* These values correspond to the STM32L4S5 */
5 FLASH : ORIGIN = 0x08000000, LENGTH = 1024K
6 RAM : ORIGIN = 0x20000000, LENGTH = 128K
7}
diff --git a/examples/stm32l4/src/bin/rng.rs b/examples/stm32l4/src/bin/rng.rs
index c9302bb99..806e49f59 100644
--- a/examples/stm32l4/src/bin/rng.rs
+++ b/examples/stm32l4/src/bin/rng.rs
@@ -6,9 +6,13 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; 7use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv};
8use embassy_stm32::rng::Rng; 8use embassy_stm32::rng::Rng;
9use embassy_stm32::Config; 9use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 RNG => rng::InterruptHandler<peripherals::RNG>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let mut config = Config::default(); 18 let mut config = Config::default();
@@ -24,7 +28,7 @@ async fn main(_spawner: Spawner) {
24 28
25 info!("Hello World!"); 29 info!("Hello World!");
26 30
27 let mut rng = Rng::new(p.RNG); 31 let mut rng = Rng::new(p.RNG, Irqs);
28 32
29 let mut buf = [0u8; 16]; 33 let mut buf = [0u8; 16];
30 unwrap!(rng.async_fill_bytes(&mut buf).await); 34 unwrap!(rng.async_fill_bytes(&mut buf).await);
diff --git a/examples/stm32l4/src/bin/spi.rs b/examples/stm32l4/src/bin/spi.rs
index 76e316a25..54cf68f7b 100644
--- a/examples/stm32l4/src/bin/spi.rs
+++ b/examples/stm32l4/src/bin/spi.rs
@@ -15,16 +15,10 @@ fn main() -> ! {
15 15
16 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
17 17
18 let mut spi = Spi::new( 18 let mut spi_config = Config::default();
19 p.SPI3, 19 spi_config.frequency = Hertz(1_000_000);
20 p.PC10, 20
21 p.PC12, 21 let mut spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config);
22 p.PC11,
23 NoDma,
24 NoDma,
25 Hertz(1_000_000),
26 Config::default(),
27 );
28 22
29 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh); 23 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh);
30 24
diff --git a/examples/stm32l4/src/bin/spi_blocking_async.rs b/examples/stm32l4/src/bin/spi_blocking_async.rs
index 62ef0130e..f1b80087c 100644
--- a/examples/stm32l4/src/bin/spi_blocking_async.rs
+++ b/examples/stm32l4/src/bin/spi_blocking_async.rs
@@ -17,16 +17,10 @@ async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
18 info!("Hello World!"); 18 info!("Hello World!");
19 19
20 let spi = Spi::new( 20 let mut spi_config = Config::default();
21 p.SPI3, 21 spi_config.frequency = Hertz(1_000_000);
22 p.PC10, 22
23 p.PC12, 23 let spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config);
24 p.PC11,
25 NoDma,
26 NoDma,
27 Hertz(1_000_000),
28 Config::default(),
29 );
30 24
31 let mut spi = BlockingAsync::new(spi); 25 let mut spi = BlockingAsync::new(spi);
32 26
diff --git a/examples/stm32l4/src/bin/spi_dma.rs b/examples/stm32l4/src/bin/spi_dma.rs
index 89471db5a..ff9b5b43b 100644
--- a/examples/stm32l4/src/bin/spi_dma.rs
+++ b/examples/stm32l4/src/bin/spi_dma.rs
@@ -14,16 +14,10 @@ async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
15 info!("Hello World!"); 15 info!("Hello World!");
16 16
17 let mut spi = Spi::new( 17 let mut spi_config = Config::default();
18 p.SPI3, 18 spi_config.frequency = Hertz(1_000_000);
19 p.PC10, 19
20 p.PC12, 20 let mut spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, p.DMA1_CH1, p.DMA1_CH2, spi_config);
21 p.PC11,
22 p.DMA1_CH1,
23 p.DMA1_CH2,
24 Hertz(1_000_000),
25 Config::default(),
26 );
27 21
28 // These are the pins for the Inventek eS-Wifi SPI Wifi Adapter. 22 // These are the pins for the Inventek eS-Wifi SPI Wifi Adapter.
29 23
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 5d66c59c3..1afd00398 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -27,3 +27,6 @@ heapless = { version = "0.7.5", default-features = false }
27rand_core = { version = "0.6.3", default-features = false } 27rand_core = { version = "0.6.3", default-features = false }
28embedded-io = { version = "0.4.0", features = ["async"] } 28embedded-io = { version = "0.4.0", features = ["async"] }
29static_cell = { version = "1.1", features = ["nightly"]} 29static_cell = { version = "1.1", features = ["nightly"]}
30
31[profile.release]
32debug = 2
diff --git a/examples/stm32l5/src/bin/rng.rs b/examples/stm32l5/src/bin/rng.rs
index d359847e8..9549d64d8 100644
--- a/examples/stm32l5/src/bin/rng.rs
+++ b/examples/stm32l5/src/bin/rng.rs
@@ -6,9 +6,13 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; 7use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv};
8use embassy_stm32::rng::Rng; 8use embassy_stm32::rng::Rng;
9use embassy_stm32::Config; 9use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 RNG => rng::InterruptHandler<peripherals::RNG>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let mut config = Config::default(); 18 let mut config = Config::default();
@@ -23,7 +27,7 @@ async fn main(_spawner: Spawner) {
23 27
24 info!("Hello World!"); 28 info!("Hello World!");
25 29
26 let mut rng = Rng::new(p.RNG); 30 let mut rng = Rng::new(p.RNG, Irqs);
27 31
28 let mut buf = [0u8; 16]; 32 let mut buf = [0u8; 16];
29 unwrap!(rng.async_fill_bytes(&mut buf).await); 33 unwrap!(rng.async_fill_bytes(&mut buf).await);
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index 32eba4277..5e75b21c9 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -9,7 +9,7 @@ use embassy_net::{Stack, StackResources};
9use embassy_stm32::rcc::*; 9use embassy_stm32::rcc::*;
10use embassy_stm32::rng::Rng; 10use embassy_stm32::rng::Rng;
11use embassy_stm32::usb::Driver; 11use embassy_stm32::usb::Driver;
12use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 12use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config};
13use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 13use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
14use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 14use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
15use embassy_usb::{Builder, UsbDevice}; 15use embassy_usb::{Builder, UsbDevice};
@@ -24,6 +24,7 @@ const MTU: usize = 1514;
24 24
25bind_interrupts!(struct Irqs { 25bind_interrupts!(struct Irqs {
26 USB_FS => usb::InterruptHandler<peripherals::USB>; 26 USB_FS => usb::InterruptHandler<peripherals::USB>;
27 RNG => rng::InterruptHandler<peripherals::RNG>;
27}); 28});
28 29
29#[embassy_executor::task] 30#[embassy_executor::task]
@@ -99,7 +100,7 @@ async fn main(spawner: Spawner) {
99 //}); 100 //});
100 101
101 // Generate random seed 102 // Generate random seed
102 let mut rng = Rng::new(p.RNG); 103 let mut rng = Rng::new(p.RNG, Irqs);
103 let seed = rng.next_u64(); 104 let seed = rng.next_u64();
104 105
105 // Init network stack 106 // Init network stack
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml
index a43a55909..db251eafe 100644
--- a/examples/stm32u5/Cargo.toml
+++ b/examples/stm32u5/Cargo.toml
@@ -23,3 +23,6 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
23heapless = { version = "0.7.5", default-features = false } 23heapless = { version = "0.7.5", default-features = false }
24 24
25micromath = "2.0.0" 25micromath = "2.0.0"
26
27[profile.release]
28debug = 2
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 48e340264..1a5aff352 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -52,3 +52,6 @@ required-features = ["ble"]
52[[bin]] 52[[bin]]
53name = "gatt_server" 53name = "gatt_server"
54required-features = ["ble"] 54required-features = ["ble"]
55
56[profile.release]
57debug = 2
diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs
index 451bd7d29..ea150c67e 100644
--- a/examples/stm32wb/src/bin/eddystone_beacon.rs
+++ b/examples/stm32wb/src/bin/eddystone_beacon.rs
@@ -8,6 +8,7 @@ use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::bind_interrupts; 9use embassy_stm32::bind_interrupts;
10use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 10use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
11use embassy_stm32::rcc::WPAN_DEFAULT;
11use embassy_stm32_wpan::hci::host::uart::UartHci; 12use embassy_stm32_wpan::hci::host::uart::UartHci;
12use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; 13use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType};
13use embassy_stm32_wpan::hci::types::AdvertisingType; 14use embassy_stm32_wpan::hci::types::AdvertisingType;
@@ -54,7 +55,9 @@ async fn main(_spawner: Spawner) {
54 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. 55 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
55 */ 56 */
56 57
57 let p = embassy_stm32::init(Default::default()); 58 let mut config = embassy_stm32::Config::default();
59 config.rcc = WPAN_DEFAULT;
60 let p = embassy_stm32::init(config);
58 info!("Hello World!"); 61 info!("Hello World!");
59 62
60 let config = Config::default(); 63 let config = Config::default();
diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs
index 0f6419d45..dd67249c7 100644
--- a/examples/stm32wb/src/bin/gatt_server.rs
+++ b/examples/stm32wb/src/bin/gatt_server.rs
@@ -8,6 +8,7 @@ use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::bind_interrupts; 9use embassy_stm32::bind_interrupts;
10use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 10use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
11use embassy_stm32::rcc::WPAN_DEFAULT;
11use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters}; 12use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters};
12use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci}; 13use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci};
13use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; 14use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType};
@@ -62,7 +63,9 @@ async fn main(_spawner: Spawner) {
62 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. 63 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
63 */ 64 */
64 65
65 let p = embassy_stm32::init(Default::default()); 66 let mut config = embassy_stm32::Config::default();
67 config.rcc = WPAN_DEFAULT;
68 let p = embassy_stm32::init(config);
66 info!("Hello World!"); 69 info!("Hello World!");
67 70
68 let config = Config::default(); 71 let config = Config::default();
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs
index 1379ac6ba..881dc488d 100644
--- a/examples/stm32wb/src/bin/mac_ffd.rs
+++ b/examples/stm32wb/src/bin/mac_ffd.rs
@@ -6,6 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; 10use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest};
10use embassy_stm32_wpan::mac::event::MacEvent; 11use embassy_stm32_wpan::mac::event::MacEvent;
11use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; 12use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel};
@@ -30,7 +31,7 @@ async fn main(spawner: Spawner) {
30 31
31 - Obtain a NUCLEO-STM32WB55 from your preferred supplier. 32 - Obtain a NUCLEO-STM32WB55 from your preferred supplier.
32 - Download and Install STM32CubeProgrammer. 33 - Download and Install STM32CubeProgrammer.
33 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from 34 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Mac_802_15_4_fw.bin, and Release_Notes.html from
34 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x 35 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
35 - Open STM32CubeProgrammer 36 - Open STM32CubeProgrammer
36 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. 37 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware.
@@ -39,7 +40,7 @@ async fn main(spawner: Spawner) {
39 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file 40 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file
40 - Select that file, the memory address, "verify download", and then "Firmware Upgrade". 41 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
41 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the 42 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the
42 stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. 43 stm32wb5x_BLE_Mac_802_15_4_fw.bin file. It should not be the same memory address.
43 - Select that file, the memory address, "verify download", and then "Firmware Upgrade". 44 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
44 - Select "Start Wireless Stack". 45 - Select "Start Wireless Stack".
45 - Disconnect from the device. 46 - Disconnect from the device.
@@ -49,7 +50,9 @@ async fn main(spawner: Spawner) {
49 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. 50 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
50 */ 51 */
51 52
52 let p = embassy_stm32::init(Default::default()); 53 let mut config = embassy_stm32::Config::default();
54 config.rcc = WPAN_DEFAULT;
55 let p = embassy_stm32::init(config);
53 info!("Hello World!"); 56 info!("Hello World!");
54 57
55 let config = Config::default(); 58 let config = Config::default();
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs
index bbcd0a70f..f8c76b5a4 100644
--- a/examples/stm32wb/src/bin/mac_ffd_net.rs
+++ b/examples/stm32wb/src/bin/mac_ffd_net.rs
@@ -6,6 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest}; 10use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest};
10use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId}; 11use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId};
11use embassy_stm32_wpan::mac::{self, Runner}; 12use embassy_stm32_wpan::mac::{self, Runner};
@@ -36,7 +37,7 @@ async fn main(spawner: Spawner) {
36 37
37 - Obtain a NUCLEO-STM32WB55 from your preferred supplier. 38 - Obtain a NUCLEO-STM32WB55 from your preferred supplier.
38 - Download and Install STM32CubeProgrammer. 39 - Download and Install STM32CubeProgrammer.
39 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from 40 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Mac_802_15_4_fw.bin, and Release_Notes.html from
40 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x 41 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
41 - Open STM32CubeProgrammer 42 - Open STM32CubeProgrammer
42 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. 43 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware.
@@ -45,7 +46,7 @@ async fn main(spawner: Spawner) {
45 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file 46 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file
46 - Select that file, the memory address, "verify download", and then "Firmware Upgrade". 47 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
47 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the 48 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the
48 stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. 49 stm32wb5x_BLE_Mac_802_15_4_fw.bin file. It should not be the same memory address.
49 - Select that file, the memory address, "verify download", and then "Firmware Upgrade". 50 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
50 - Select "Start Wireless Stack". 51 - Select "Start Wireless Stack".
51 - Disconnect from the device. 52 - Disconnect from the device.
@@ -55,7 +56,9 @@ async fn main(spawner: Spawner) {
55 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. 56 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
56 */ 57 */
57 58
58 let p = embassy_stm32::init(Default::default()); 59 let mut config = embassy_stm32::Config::default();
60 config.rcc = WPAN_DEFAULT;
61 let p = embassy_stm32::init(config);
59 info!("Hello World!"); 62 info!("Hello World!");
60 63
61 let config = Config::default(); 64 let config = Config::default();
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs
index 4d8b6601a..000355de6 100644
--- a/examples/stm32wb/src/bin/mac_rfd.rs
+++ b/examples/stm32wb/src/bin/mac_rfd.rs
@@ -6,6 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; 10use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest};
10use embassy_stm32_wpan::mac::event::MacEvent; 11use embassy_stm32_wpan::mac::event::MacEvent;
11use embassy_stm32_wpan::mac::typedefs::{ 12use embassy_stm32_wpan::mac::typedefs::{
@@ -32,7 +33,7 @@ async fn main(spawner: Spawner) {
32 33
33 - Obtain a NUCLEO-STM32WB55 from your preferred supplier. 34 - Obtain a NUCLEO-STM32WB55 from your preferred supplier.
34 - Download and Install STM32CubeProgrammer. 35 - Download and Install STM32CubeProgrammer.
35 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from 36 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Mac_802_15_4_fw.bin, and Release_Notes.html from
36 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x 37 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
37 - Open STM32CubeProgrammer 38 - Open STM32CubeProgrammer
38 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. 39 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware.
@@ -41,7 +42,7 @@ async fn main(spawner: Spawner) {
41 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file 42 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file
42 - Select that file, the memory address, "verify download", and then "Firmware Upgrade". 43 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
43 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the 44 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the
44 stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. 45 stm32wb5x_BLE_Mac_802_15_4_fw.bin file. It should not be the same memory address.
45 - Select that file, the memory address, "verify download", and then "Firmware Upgrade". 46 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
46 - Select "Start Wireless Stack". 47 - Select "Start Wireless Stack".
47 - Disconnect from the device. 48 - Disconnect from the device.
@@ -51,7 +52,9 @@ async fn main(spawner: Spawner) {
51 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. 52 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
52 */ 53 */
53 54
54 let p = embassy_stm32::init(Default::default()); 55 let mut config = embassy_stm32::Config::default();
56 config.rcc = WPAN_DEFAULT;
57 let p = embassy_stm32::init(config);
55 info!("Hello World!"); 58 info!("Hello World!");
56 59
57 let config = Config::default(); 60 let config = Config::default();
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs
index 9fc4b8aac..fc49c3c4a 100644
--- a/examples/stm32wb/src/bin/tl_mbox.rs
+++ b/examples/stm32wb/src/bin/tl_mbox.rs
@@ -6,6 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::TlMbox; 10use embassy_stm32_wpan::TlMbox;
10use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -41,7 +42,9 @@ async fn main(_spawner: Spawner) {
41 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. 42 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
42 */ 43 */
43 44
44 let p = embassy_stm32::init(Default::default()); 45 let mut config = embassy_stm32::Config::default();
46 config.rcc = WPAN_DEFAULT;
47 let p = embassy_stm32::init(config);
45 info!("Hello World!"); 48 info!("Hello World!");
46 49
47 let config = Config::default(); 50 let config = Config::default();
diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs
index 90349422e..5745ebd02 100644
--- a/examples/stm32wb/src/bin/tl_mbox_ble.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs
@@ -6,6 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::TlMbox; 10use embassy_stm32_wpan::TlMbox;
10use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
11 12
@@ -40,7 +41,9 @@ async fn main(_spawner: Spawner) {
40 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. 41 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
41 */ 42 */
42 43
43 let p = embassy_stm32::init(Default::default()); 44 let mut config = embassy_stm32::Config::default();
45 config.rcc = WPAN_DEFAULT;
46 let p = embassy_stm32::init(config);
44 info!("Hello World!"); 47 info!("Hello World!");
45 48
46 let config = Config::default(); 49 let config = Config::default();
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs
index 5931c392b..f32e07d96 100644
--- a/examples/stm32wb/src/bin/tl_mbox_mac.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs
@@ -6,6 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::sub::mm; 10use embassy_stm32_wpan::sub::mm;
10use embassy_stm32_wpan::TlMbox; 11use embassy_stm32_wpan::TlMbox;
11use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -27,7 +28,7 @@ async fn main(spawner: Spawner) {
27 28
28 - Obtain a NUCLEO-STM32WB55 from your preferred supplier. 29 - Obtain a NUCLEO-STM32WB55 from your preferred supplier.
29 - Download and Install STM32CubeProgrammer. 30 - Download and Install STM32CubeProgrammer.
30 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from 31 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Mac_802_15_4_fw.bin, and Release_Notes.html from
31 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x 32 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
32 - Open STM32CubeProgrammer 33 - Open STM32CubeProgrammer
33 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. 34 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware.
@@ -36,7 +37,7 @@ async fn main(spawner: Spawner) {
36 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file 37 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file
37 - Select that file, the memory address, "verify download", and then "Firmware Upgrade". 38 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
38 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the 39 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the
39 stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. 40 stm32wb5x_BLE_Mac_802_15_4_fw.bin file. It should not be the same memory address.
40 - Select that file, the memory address, "verify download", and then "Firmware Upgrade". 41 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
41 - Select "Start Wireless Stack". 42 - Select "Start Wireless Stack".
42 - Disconnect from the device. 43 - Disconnect from the device.
@@ -46,7 +47,9 @@ async fn main(spawner: Spawner) {
46 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. 47 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
47 */ 48 */
48 49
49 let p = embassy_stm32::init(Default::default()); 50 let mut config = embassy_stm32::Config::default();
51 config.rcc = WPAN_DEFAULT;
52 let p = embassy_stm32::init(config);
50 info!("Hello World!"); 53 info!("Hello World!");
51 54
52 let config = Config::default(); 55 let config = Config::default();
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index 6e6f269aa..48b69c8d0 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -28,5 +28,5 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
28heapless = { version = "0.7.5", default-features = false } 28heapless = { version = "0.7.5", default-features = false }
29chrono = { version = "^0.4", default-features = false } 29chrono = { version = "^0.4", default-features = false }
30 30
31[patch.crates-io] 31[profile.release]
32lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } 32debug = 2
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
index 805d21418..2c9c98861 100644
--- a/examples/stm32wl/src/bin/lora_lorawan.rs
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -10,9 +10,9 @@ use embassy_executor::Spawner;
10use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant}; 10use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
11use embassy_lora::LoraTimer; 11use embassy_lora::LoraTimer;
12use embassy_stm32::gpio::{Level, Output, Pin, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pin, Speed};
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::{self, Rng};
14use embassy_stm32::spi::Spi; 14use embassy_stm32::spi::Spi;
15use embassy_stm32::{bind_interrupts, pac}; 15use embassy_stm32::{bind_interrupts, pac, peripherals};
16use embassy_time::Delay; 16use embassy_time::Delay;
17use lora_phy::mod_params::*; 17use lora_phy::mod_params::*;
18use lora_phy::sx1261_2::SX1261_2; 18use lora_phy::sx1261_2::SX1261_2;
@@ -26,6 +26,7 @@ const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set th
26 26
27bind_interrupts!(struct Irqs{ 27bind_interrupts!(struct Irqs{
28 SUBGHZ_RADIO => InterruptHandler; 28 SUBGHZ_RADIO => InterruptHandler;
29 RNG => rng::InterruptHandler<peripherals::RNG>;
29}); 30});
30 31
31#[embassy_executor::main] 32#[embassy_executor::main]
@@ -58,7 +59,7 @@ async fn main(_spawner: Spawner) {
58 }; 59 };
59 let radio = LoRaRadio::new(lora); 60 let radio = LoRaRadio::new(lora);
60 let region: region::Configuration = region::Configuration::new(LORAWAN_REGION); 61 let region: region::Configuration = region::Configuration::new(LORAWAN_REGION);
61 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG)); 62 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG, Irqs));
62 63
63 defmt::info!("Joining LoRaWAN network"); 64 defmt::info!("Joining LoRaWAN network");
64 65
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs
index d8562fca5..592e65f40 100644
--- a/examples/stm32wl/src/bin/random.rs
+++ b/examples/stm32wl/src/bin/random.rs
@@ -4,10 +4,14 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::pac; 7use embassy_stm32::rng::{self, Rng};
8use embassy_stm32::rng::Rng; 8use embassy_stm32::{bind_interrupts, pac, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs{
12 RNG => rng::InterruptHandler<peripherals::RNG>;
13});
14
11#[embassy_executor::main] 15#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
13 let mut config = embassy_stm32::Config::default(); 17 let mut config = embassy_stm32::Config::default();
@@ -21,7 +25,7 @@ async fn main(_spawner: Spawner) {
21 25
22 info!("Hello World!"); 26 info!("Hello World!");
23 27
24 let mut rng = Rng::new(p.RNG); 28 let mut rng = Rng::new(p.RNG, Irqs);
25 29
26 let mut buf = [0u8; 16]; 30 let mut buf = [0u8; 16];
27 unwrap!(rng.async_fill_bytes(&mut buf).await); 31 unwrap!(rng.async_fill_bytes(&mut buf).await);
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml
index 3679e3857..2791cc341 100644
--- a/examples/wasm/Cargo.toml
+++ b/examples/wasm/Cargo.toml
@@ -17,3 +17,6 @@ wasm-bindgen = "0.2"
17web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] } 17web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] }
18log = "0.4.11" 18log = "0.4.11"
19critical-section = { version = "1.1", features = ["std"] } 19critical-section = { version = "1.1", features = ["std"] }
20
21[profile.release]
22debug = 2
diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
index 398ab9d27..e2adfe0be 100644
--- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
+++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
@@ -118,9 +118,9 @@ const WIFI_NETWORK: &str = "EmbassyTest";
118const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; 118const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud";
119 119
120const TEST_DURATION: usize = 10; 120const TEST_DURATION: usize = 10;
121const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 150; 121const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 50;
122const TEST_EXPECTED_UPLOAD_KBPS: usize = 150; 122const TEST_EXPECTED_UPLOAD_KBPS: usize = 50;
123const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 150; 123const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 50;
124const RX_BUFFER_SIZE: usize = 4096; 124const RX_BUFFER_SIZE: usize = 4096;
125const TX_BUFFER_SIZE: usize = 4096; 125const TX_BUFFER_SIZE: usize = 4096;
126const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2); 126const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2);
diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs
index bc127e2e5..fffdabc9b 100644
--- a/tests/rp/src/bin/cyw43-perf.rs
+++ b/tests/rp/src/bin/cyw43-perf.rs
@@ -48,9 +48,9 @@ async fn main(spawner: Spawner) {
48 } 48 }
49 49
50 // cyw43 firmware needs to be flashed manually: 50 // cyw43 firmware needs to be flashed manually:
51 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x101c0000 51 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x101b0000
52 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x101f8000 52 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x101f8000
53 let fw = unsafe { core::slice::from_raw_parts(0x101c0000 as *const u8, 224190) }; 53 let fw = unsafe { core::slice::from_raw_parts(0x101b0000 as *const u8, 230321) };
54 let clm = unsafe { core::slice::from_raw_parts(0x101f8000 as *const u8, 4752) }; 54 let clm = unsafe { core::slice::from_raw_parts(0x101f8000 as *const u8, 4752) };
55 55
56 let pwr = Output::new(p.PIN_23, Level::Low); 56 let pwr = Output::new(p.PIN_23, Level::Low);
diff --git a/tests/rp/src/bin/flash.rs b/tests/rp/src/bin/flash.rs
index cf9b86df5..c31d6decf 100644
--- a/tests/rp/src/bin/flash.rs
+++ b/tests/rp/src/bin/flash.rs
@@ -6,11 +6,11 @@ mod common;
6 6
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE}; 9use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE};
10use embassy_time::{Duration, Timer}; 10use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13const ADDR_OFFSET: u32 = 0x4000; 13const ADDR_OFFSET: u32 = 0x8000;
14 14
15#[embassy_executor::main] 15#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 // https://github.com/knurling-rs/defmt/pull/683 23 // https://github.com/knurling-rs/defmt/pull/683
24 Timer::after(Duration::from_millis(10)).await; 24 Timer::after(Duration::from_millis(10)).await;
25 25
26 let mut flash = embassy_rp::flash::Flash::<_, { 2 * 1024 * 1024 }>::new(p.FLASH); 26 let mut flash = embassy_rp::flash::Flash::<_, Async, { 2 * 1024 * 1024 }>::new(p.FLASH, p.DMA_CH0);
27 27
28 // Get JEDEC id 28 // Get JEDEC id
29 let jedec = defmt::unwrap!(flash.jedec_id()); 29 let jedec = defmt::unwrap!(flash.jedec_id());
@@ -60,6 +60,14 @@ async fn main(_spawner: Spawner) {
60 defmt::panic!("unexpected"); 60 defmt::panic!("unexpected");
61 } 61 }
62 62
63 let mut buf = [0u32; ERASE_SIZE / 4];
64
65 defmt::unwrap!(flash.background_read(ADDR_OFFSET, &mut buf)).await;
66 info!("Contents after write starts with {=u32:x}", buf[0]);
67 if buf.iter().any(|x| *x != 0xDADADADA) {
68 defmt::panic!("unexpected");
69 }
70
63 info!("Test OK"); 71 info!("Test OK");
64 cortex_m::asm::bkpt(); 72 cortex_m::asm::bkpt();
65} 73}
diff --git a/tests/rp/src/bin/pio_irq.rs b/tests/rp/src/bin/pio_irq.rs
index 45004424a..bdea63eaa 100644
--- a/tests/rp/src/bin/pio_irq.rs
+++ b/tests/rp/src/bin/pio_irq.rs
@@ -9,7 +9,6 @@ use embassy_executor::Spawner;
9use embassy_rp::bind_interrupts; 9use embassy_rp::bind_interrupts;
10use embassy_rp::peripherals::PIO0; 10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::{Config, InterruptHandler, Pio}; 11use embassy_rp::pio::{Config, InterruptHandler, Pio};
12use embassy_rp::relocate::RelocatedProgram;
13use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
14 13
15bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
@@ -35,9 +34,8 @@ async fn main(_spawner: Spawner) {
35 "irq wait 1", 34 "irq wait 1",
36 ); 35 );
37 36
38 let relocated = RelocatedProgram::new(&prg.program);
39 let mut cfg = Config::default(); 37 let mut cfg = Config::default();
40 cfg.use_program(&common.load_program(&relocated), &[]); 38 cfg.use_program(&common.load_program(&prg.program), &[]);
41 sm.set_config(&cfg); 39 sm.set_config(&cfg);
42 sm.set_enable(true); 40 sm.set_enable(true);
43 41
diff --git a/tests/rp/src/bin/pio_multi_load.rs b/tests/rp/src/bin/pio_multi_load.rs
new file mode 100644
index 000000000..356f16795
--- /dev/null
+++ b/tests/rp/src/bin/pio_multi_load.rs
@@ -0,0 +1,126 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4#[path = "../common.rs"]
5mod common;
6
7use defmt::info;
8use embassy_executor::Spawner;
9use embassy_rp::bind_interrupts;
10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::{Config, InterruptHandler, LoadError, Pio};
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 PIO0_IRQ_0 => InterruptHandler<PIO0>;
16});
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 let p = embassy_rp::init(Default::default());
21 let pio = p.PIO0;
22 let Pio {
23 mut common,
24 mut sm0,
25 mut sm1,
26 mut sm2,
27 irq_flags,
28 ..
29 } = Pio::new(pio, Irqs);
30
31 // load with explicit origin works
32 let prg1 = pio_proc::pio_asm!(
33 ".origin 4"
34 "nop",
35 "nop",
36 "nop",
37 "nop",
38 "nop",
39 "nop",
40 "nop",
41 "irq 0",
42 "nop",
43 "nop",
44 );
45 let loaded1 = common.load_program(&prg1.program);
46 assert_eq!(loaded1.origin, 4);
47 assert_eq!(loaded1.wrap.source, 13);
48 assert_eq!(loaded1.wrap.target, 4);
49
50 // load without origin chooses a free space
51 let prg2 = pio_proc::pio_asm!("nop", "nop", "nop", "nop", "nop", "nop", "nop", "irq 1", "nop", "nop",);
52 let loaded2 = common.load_program(&prg2.program);
53 assert_eq!(loaded2.origin, 14);
54 assert_eq!(loaded2.wrap.source, 23);
55 assert_eq!(loaded2.wrap.target, 14);
56
57 // wrapping around the end of program space automatically works
58 let prg3 =
59 pio_proc::pio_asm!("nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "irq 2",);
60 let loaded3 = common.load_program(&prg3.program);
61 assert_eq!(loaded3.origin, 24);
62 assert_eq!(loaded3.wrap.source, 3);
63 assert_eq!(loaded3.wrap.target, 24);
64
65 // check that the programs actually work
66 {
67 let mut cfg = Config::default();
68 cfg.use_program(&loaded1, &[]);
69 sm0.set_config(&cfg);
70 sm0.set_enable(true);
71 while !irq_flags.check(0) {}
72 sm0.set_enable(false);
73 }
74 {
75 let mut cfg = Config::default();
76 cfg.use_program(&loaded2, &[]);
77 sm1.set_config(&cfg);
78 sm1.set_enable(true);
79 while !irq_flags.check(1) {}
80 sm1.set_enable(false);
81 }
82 {
83 let mut cfg = Config::default();
84 cfg.use_program(&loaded3, &[]);
85 sm2.set_config(&cfg);
86 sm2.set_enable(true);
87 while !irq_flags.check(2) {}
88 sm2.set_enable(false);
89 }
90
91 // instruction memory is full now. all loads should fail.
92 {
93 let prg = pio_proc::pio_asm!(".origin 0", "nop");
94 match common.try_load_program(&prg.program) {
95 Err(LoadError::AddressInUse(0)) => (),
96 _ => panic!("program loaded when it shouldn't"),
97 };
98
99 let prg = pio_proc::pio_asm!("nop");
100 match common.try_load_program(&prg.program) {
101 Err(LoadError::InsufficientSpace) => (),
102 _ => panic!("program loaded when it shouldn't"),
103 };
104 }
105
106 // freeing some memory should allow further loads though.
107 unsafe {
108 common.free_instr(loaded3.used_memory);
109 }
110 {
111 let prg = pio_proc::pio_asm!(".origin 0", "nop");
112 match common.try_load_program(&prg.program) {
113 Ok(_) => (),
114 _ => panic!("program didn't loaded when it shouldn"),
115 };
116
117 let prg = pio_proc::pio_asm!("nop");
118 match common.try_load_program(&prg.program) {
119 Ok(_) => (),
120 _ => panic!("program didn't loaded when it shouldn"),
121 };
122 }
123
124 info!("Test OK");
125 cortex_m::asm::bkpt();
126}
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 3007cd1e6..17320649e 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -7,11 +7,11 @@ autobins = false
7 7
8[features] 8[features]
9stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill 9stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill
10stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma"] # Nucleo "sdmmc" 10stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma", "dac-adc-pin"] # Nucleo "sdmmc"
11stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo 11stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"] # Nucleo
12stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo 12stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo
13stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo 13stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo
14stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo 14stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma", "dac-adc-pin"] # Nucleo
15stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo 15stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo
16stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo 16stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo
17stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board 17stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board
@@ -23,6 +23,7 @@ ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
23mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] 23mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"]
24embassy-stm32-wpan = [] 24embassy-stm32-wpan = []
25not-gpdma = [] 25not-gpdma = []
26dac-adc-pin = []
26 27
27[dependencies] 28[dependencies]
28teleprobe-meta = "1" 29teleprobe-meta = "1"
@@ -42,6 +43,7 @@ cortex-m-rt = "0.7.0"
42embedded-hal = "0.2.6" 43embedded-hal = "0.2.6"
43embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } 44embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
44embedded-hal-async = { version = "=0.2.0-alpha.2" } 45embedded-hal-async = { version = "=0.2.0-alpha.2" }
46micromath = "2.0.0"
45panic-probe = { version = "0.3.0", features = ["print-defmt"] } 47panic-probe = { version = "0.3.0", features = ["print-defmt"] }
46rand_core = { version = "0.6", default-features = false } 48rand_core = { version = "0.6", default-features = false }
47rand_chacha = { version = "0.3", default-features = false } 49rand_chacha = { version = "0.3", default-features = false }
@@ -56,6 +58,11 @@ path = "src/bin/can.rs"
56required-features = [ "can",] 58required-features = [ "can",]
57 59
58[[bin]] 60[[bin]]
61name = "dac"
62path = "src/bin/dac.rs"
63required-features = [ "dac-adc-pin",]
64
65[[bin]]
59name = "gpio" 66name = "gpio"
60path = "src/bin/gpio.rs" 67path = "src/bin/gpio.rs"
61required-features = [] 68required-features = []
diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs
new file mode 100644
index 000000000..67a7d5b59
--- /dev/null
+++ b/tests/stm32/src/bin/dac.rs
@@ -0,0 +1,81 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5// required-features: dac-adc-pin
6
7#[path = "../common.rs"]
8mod common;
9use common::*;
10use defmt::assert;
11use embassy_executor::Spawner;
12use embassy_stm32::adc::Adc;
13use embassy_stm32::dac::{DacCh1, DacChannel, Value};
14use embassy_stm32::dma::NoDma;
15use embassy_time::{Delay, Duration, Timer};
16use {defmt_rtt as _, panic_probe as _};
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 // Initialize the board and obtain a Peripherals instance
21 let p: embassy_stm32::Peripherals = embassy_stm32::init(config());
22
23 #[cfg(feature = "stm32f429zi")]
24 let dac_peripheral = p.DAC;
25
26 #[cfg(any(feature = "stm32h755zi", feature = "stm32g071rb"))]
27 let dac_peripheral = p.DAC1;
28
29 let mut dac: DacCh1<'_, _, NoDma> = DacCh1::new(dac_peripheral, NoDma, p.PA4);
30 unwrap!(dac.set_trigger_enable(false));
31
32 let mut adc = Adc::new(p.ADC1, &mut Delay);
33
34 #[cfg(feature = "stm32h755zi")]
35 let normalization_factor = 256;
36 #[cfg(any(feature = "stm32f429zi", feature = "stm32g071rb"))]
37 let normalization_factor: i32 = 16;
38
39 unwrap!(dac.set(Value::Bit8(0)));
40 // Now wait a little to obtain a stable value
41 Timer::after(Duration::from_millis(30)).await;
42 let offset = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4);
43
44 for v in 0..=255 {
45 // First set the DAC output value
46 let dac_output_val = to_sine_wave(v);
47 unwrap!(dac.set(Value::Bit8(dac_output_val)));
48
49 // Now wait a little to obtain a stable value
50 Timer::after(Duration::from_millis(30)).await;
51
52 // Need to steal the peripherals here because PA4 is obviously in use already
53 let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4);
54 // Calibrate and normalize the measurement to get close to the dac_output_val
55 let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16;
56
57 info!("value / measured: {} / {}", dac_output_val, measured_normalized);
58
59 // The deviations are quite enormous but that does not matter since this is only a quick test
60 assert!((dac_output_val as i16 - measured_normalized).abs() < 15);
61 }
62
63 info!("Test OK");
64 cortex_m::asm::bkpt();
65}
66
67use core::f32::consts::PI;
68
69use micromath::F32Ext;
70
71fn to_sine_wave(v: u8) -> u8 {
72 if v >= 128 {
73 // top half
74 let r = PI * ((v - 128) as f32 / 128.0);
75 (r.sin() * 128.0 + 127.0) as u8
76 } else {
77 // bottom half
78 let r = PI + PI * (v as f32 / 128.0);
79 (r.sin() * 128.0 + 127.0) as u8
80 }
81}
diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs
index 819ecae3c..e51dd5bf2 100644
--- a/tests/stm32/src/bin/spi.rs
+++ b/tests/stm32/src/bin/spi.rs
@@ -35,15 +35,14 @@ async fn main(_spawner: Spawner) {
35 #[cfg(feature = "stm32c031c6")] 35 #[cfg(feature = "stm32c031c6")]
36 let (spi, sck, mosi, miso) = (p.SPI1, p.PA5, p.PA7, p.PA6); 36 let (spi, sck, mosi, miso) = (p.SPI1, p.PA5, p.PA7, p.PA6);
37 37
38 let mut spi_config = spi::Config::default();
39 spi_config.frequency = Hertz(1_000_000);
40
38 let mut spi = Spi::new( 41 let mut spi = Spi::new(
39 spi, 42 spi, sck, // Arduino D13
40 sck, // Arduino D13
41 mosi, // Arduino D11 43 mosi, // Arduino D11
42 miso, // Arduino D12 44 miso, // Arduino D12
43 NoDma, 45 NoDma, NoDma, spi_config,
44 NoDma,
45 Hertz(1_000_000),
46 spi::Config::default(),
47 ); 46 );
48 47
49 let data: [u8; 9] = [0x00, 0xFF, 0xAA, 0x55, 0xC0, 0xFF, 0xEE, 0xC0, 0xDE]; 48 let data: [u8; 9] = [0x00, 0xFF, 0xAA, 0x55, 0xC0, 0xFF, 0xEE, 0xC0, 0xDE];
diff --git a/tests/stm32/src/bin/spi_dma.rs b/tests/stm32/src/bin/spi_dma.rs
index 78aad24e1..d45cbe45b 100644
--- a/tests/stm32/src/bin/spi_dma.rs
+++ b/tests/stm32/src/bin/spi_dma.rs
@@ -34,15 +34,14 @@ async fn main(_spawner: Spawner) {
34 #[cfg(feature = "stm32c031c6")] 34 #[cfg(feature = "stm32c031c6")]
35 let (spi, sck, mosi, miso, tx_dma, rx_dma) = (p.SPI1, p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2); 35 let (spi, sck, mosi, miso, tx_dma, rx_dma) = (p.SPI1, p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2);
36 36
37 let mut spi_config = spi::Config::default();
38 spi_config.frequency = Hertz(1_000_000);
39
37 let mut spi = Spi::new( 40 let mut spi = Spi::new(
38 spi, 41 spi, sck, // Arduino D13
39 sck, // Arduino D13
40 mosi, // Arduino D11 42 mosi, // Arduino D11
41 miso, // Arduino D12 43 miso, // Arduino D12
42 tx_dma, 44 tx_dma, rx_dma, spi_config,
43 rx_dma,
44 Hertz(1_000_000),
45 spi::Config::default(),
46 ); 45 );
47 46
48 let data: [u8; 9] = [0x00, 0xFF, 0xAA, 0x55, 0xC0, 0xFF, 0xEE, 0xC0, 0xDE]; 47 let data: [u8; 9] = [0x00, 0xFF, 0xAA, 0x55, 0xC0, 0xFF, 0xEE, 0xC0, 0xDE];
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 3d2a9b8ef..ca5cb43ac 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -33,6 +33,7 @@ pub fn config() -> Config {
33 { 33 {
34 config.rcc.sys_ck = Some(Hertz(400_000_000)); 34 config.rcc.sys_ck = Some(Hertz(400_000_000));
35 config.rcc.pll1.q_ck = Some(Hertz(100_000_000)); 35 config.rcc.pll1.q_ck = Some(Hertz(100_000_000));
36 config.rcc.adc_clock_source = embassy_stm32::rcc::AdcClockSource::PerCk;
36 } 37 }
37 38
38 #[cfg(feature = "stm32u585ai")] 39 #[cfg(feature = "stm32u585ai")]