From 046a99aba01051c93d2f6a4d2f6e54ddde4f7fd4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 31 May 2023 13:56:12 +0200 Subject: [PATCH 01/98] Move doc building to new CI. --- .github/ci/doc.sh | 34 +++++++++++++++ .github/workflows/doc.yml | 87 ------------------------------------- embassy-cortex-m/Cargo.toml | 2 - 3 files changed, 34 insertions(+), 89 deletions(-) create mode 100755 .github/ci/doc.sh delete mode 100644 .github/workflows/doc.yml diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh new file mode 100755 index 000000000..eabde742b --- /dev/null +++ b/.github/ci/doc.sh @@ -0,0 +1,34 @@ +#!/bin/bash +## on push branch=main + +set -euo pipefail + +export RUSTUP_HOME=/ci/cache/rustup +export CARGO_HOME=/ci/cache/cargo +export CARGO_TARGET_DIR=/ci/cache/target +export BUILDER_THREADS=6 + +docserver-builder ./embassy-boot/boot crates/embassy-boot/git.zup +docserver-builder ./embassy-boot/nrf crates/embassy-boot-nrf/git.zup +docserver-builder ./embassy-boot/rp crates/embassy-boot-rp/git.zup +docserver-builder ./embassy-boot/stm32 crates/embassy-boot-stm32/git.zup +docserver-builder ./embassy-cortex-m crates/embassy-cortex-m/git.zup +docserver-builder ./embassy-embedded-hal crates/embassy-embedded-hal/git.zup +docserver-builder ./embassy-executor crates/embassy-executor/git.zup +docserver-builder ./embassy-futures crates/embassy-futures/git.zup +docserver-builder ./embassy-lora crates/embassy-lora/git.zup +docserver-builder ./embassy-net crates/embassy-net/git.zup +docserver-builder ./embassy-net-driver crates/embassy-net-driver/git.zup +docserver-builder ./embassy-net-driver-channel crates/embassy-net-driver-channel/git.zup +docserver-builder ./embassy-nrf crates/embassy-nrf/git.zup +docserver-builder ./embassy-rp crates/embassy-rp/git.zup +docserver-builder ./embassy-sync crates/embassy-sync/git.zup +docserver-builder ./embassy-time crates/embassy-time/git.zup +docserver-builder ./embassy-usb crates/embassy-usb/git.zup +docserver-builder ./embassy-usb-driver crates/embassy-usb-driver/git.zup +docserver-builder ./embassy-usb-logger crates/embassy-usb-logger/git.zup +#docserver-builder ./embassy-stm32 crates/embassy-stm32/git.zup + +export KUBECONFIG=/ci/secrets/kubeconfig.yml +POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) +kubectl cp crates $POD:/data diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml deleted file mode 100644 index a69a49718..000000000 --- a/.github/workflows/doc.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Docs - -on: - push: - branches: [main] - -env: - BUILDER_THREADS: '1' - -jobs: - doc: - runs-on: ubuntu-latest - - # Since stm32 crates take SO LONG to build, we split them - # into a separate job. This way it doesn't slow down updating - # the rest. - strategy: - matrix: - crates: - #- stm32 # runs out of disk space... - - rest - - # This will ensure at most one doc build job is running at a time - # (for stm32 and non-stm32 independently). - # If another job is already running, the new job will wait. - # If another job is already waiting, it'll be canceled. - # This means some commits will be skipped, but that's fine because - # we only care that the latest gets built. - concurrency: doc-${{ matrix.crates }} - - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - name: Install Rust targets - run: | - rustup target add x86_64-unknown-linux-gnu - rustup target add wasm32-unknown-unknown - rustup target add thumbv6m-none-eabi - rustup target add thumbv7m-none-eabi - rustup target add thumbv7em-none-eabi - rustup target add thumbv7em-none-eabihf - rustup target add thumbv8m.base-none-eabi - rustup target add thumbv8m.main-none-eabi - rustup target add thumbv8m.main-none-eabihf - - - name: Install docserver - run: | - wget -q -O /usr/local/bin/builder "https://github.com/embassy-rs/docserver/releases/download/v0.4/builder" - chmod +x /usr/local/bin/builder - - - name: build-stm32 - if: ${{ matrix.crates=='stm32' }} - run: | - mkdir crates - builder ./embassy-stm32 crates/embassy-stm32/git.zup - - - name: build-rest - if: ${{ matrix.crates=='rest' }} - run: | - mkdir crates - builder ./embassy-boot/boot crates/embassy-boot/git.zup - builder ./embassy-boot/nrf crates/embassy-boot-nrf/git.zup - builder ./embassy-boot/rp crates/embassy-boot-rp/git.zup - builder ./embassy-boot/stm32 crates/embassy-boot-stm32/git.zup - builder ./embassy-cortex-m crates/embassy-cortex-m/git.zup - builder ./embassy-embedded-hal crates/embassy-embedded-hal/git.zup - builder ./embassy-executor crates/embassy-executor/git.zup - builder ./embassy-futures crates/embassy-futures/git.zup - builder ./embassy-lora crates/embassy-lora/git.zup - builder ./embassy-net crates/embassy-net/git.zup - builder ./embassy-net-driver crates/embassy-net-driver/git.zup - builder ./embassy-net-driver-channel crates/embassy-net-driver-channel/git.zup - builder ./embassy-nrf crates/embassy-nrf/git.zup - builder ./embassy-rp crates/embassy-rp/git.zup - builder ./embassy-sync crates/embassy-sync/git.zup - builder ./embassy-time crates/embassy-time/git.zup - builder ./embassy-usb crates/embassy-usb/git.zup - builder ./embassy-usb-driver crates/embassy-usb-driver/git.zup - builder ./embassy-usb-logger crates/embassy-usb-logger/git.zup - - - name: upload - run: | - mkdir -p ~/.kube - echo "${{secrets.KUBECONFIG}}" > ~/.kube/config - POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) - kubectl cp crates $POD:/data diff --git a/embassy-cortex-m/Cargo.toml b/embassy-cortex-m/Cargo.toml index 2eb0cce2a..70adda7df 100644 --- a/embassy-cortex-m/Cargo.toml +++ b/embassy-cortex-m/Cargo.toml @@ -13,8 +13,6 @@ flavors = [ { name = "thumbv7m-none-eabi", target = "thumbv7m-none-eabi", features = [] }, { name = "thumbv7em-none-eabi", target = "thumbv7em-none-eabi", features = [] }, { name = "thumbv7em-none-eabihf", target = "thumbv7em-none-eabihf", features = [] }, - { name = "thumbv8m.base-none-eabi", target = "thumbv8m.base-none-eabi", features = [] }, - { name = "thumbv8m.main-none-eabi", target = "thumbv8m.main-none-eabi", features = [] }, { name = "thumbv8m.main-none-eabihf", target = "thumbv8m.main-none-eabihf", features = [] }, ] From 7fcded57058cbd119e6527308be750949337b0f5 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 31 May 2023 20:03:39 +0200 Subject: [PATCH 02/98] stm32/rtc: fix build failure in some L4s --- ci.sh | 1 + embassy-stm32/src/rtc/v3.rs | 7 +------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/ci.sh b/ci.sh index 8a3669f07..3d6e28796 100755 --- a/ci.sh +++ b/ci.sh @@ -71,6 +71,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h7b3ai,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l476vg,defmt,exti,time-driver-any,unstable-traits \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l422cb,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wb15cc,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l072cz,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l041f6,defmt,exti,time-driver-any,unstable-traits \ diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 546fe88c7..24f6496a6 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -9,11 +9,6 @@ impl<'d, T: Instance> super::Rtc<'d, T> { pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { // Unlock the backup domain unsafe { - #[cfg(any(rtc_v3u5, rcc_g0, rcc_g4))] - use crate::pac::rcc::vals::Rtcsel; - #[cfg(not(any(rtc_v3u5, rcc_g0, rcc_g4, rcc_wl5, rcc_wle)))] - use crate::pac::rtc::vals::Rtcsel; - #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] { crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); @@ -32,7 +27,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { let config_rtcsel = rtc_config.clock_config as u8; #[cfg(not(any(rcc_wl5, rcc_wle)))] - let config_rtcsel = Rtcsel(config_rtcsel); + let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel); if !reg.rtcen() || reg.rtcsel() != config_rtcsel { crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); From 25f367432d6065bbcdf25cba80f2734237c432e4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 31 May 2023 20:04:17 +0200 Subject: [PATCH 03/98] ci: build stm32 docs. --- .github/ci/doc.sh | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index eabde742b..7f7dfaa03 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -7,27 +7,28 @@ export RUSTUP_HOME=/ci/cache/rustup export CARGO_HOME=/ci/cache/cargo export CARGO_TARGET_DIR=/ci/cache/target export BUILDER_THREADS=6 +export BUILDER_COMPRESS=true -docserver-builder ./embassy-boot/boot crates/embassy-boot/git.zup -docserver-builder ./embassy-boot/nrf crates/embassy-boot-nrf/git.zup -docserver-builder ./embassy-boot/rp crates/embassy-boot-rp/git.zup -docserver-builder ./embassy-boot/stm32 crates/embassy-boot-stm32/git.zup -docserver-builder ./embassy-cortex-m crates/embassy-cortex-m/git.zup -docserver-builder ./embassy-embedded-hal crates/embassy-embedded-hal/git.zup -docserver-builder ./embassy-executor crates/embassy-executor/git.zup -docserver-builder ./embassy-futures crates/embassy-futures/git.zup -docserver-builder ./embassy-lora crates/embassy-lora/git.zup -docserver-builder ./embassy-net crates/embassy-net/git.zup -docserver-builder ./embassy-net-driver crates/embassy-net-driver/git.zup -docserver-builder ./embassy-net-driver-channel crates/embassy-net-driver-channel/git.zup -docserver-builder ./embassy-nrf crates/embassy-nrf/git.zup -docserver-builder ./embassy-rp crates/embassy-rp/git.zup -docserver-builder ./embassy-sync crates/embassy-sync/git.zup -docserver-builder ./embassy-time crates/embassy-time/git.zup -docserver-builder ./embassy-usb crates/embassy-usb/git.zup -docserver-builder ./embassy-usb-driver crates/embassy-usb-driver/git.zup -docserver-builder ./embassy-usb-logger crates/embassy-usb-logger/git.zup -#docserver-builder ./embassy-stm32 crates/embassy-stm32/git.zup +docserver-builder -i ./embassy-stm32 -o crates/embassy-stm32/git.zup +docserver-builder -i ./embassy-boot/boot -o crates/embassy-boot/git.zup +docserver-builder -i ./embassy-boot/nrf -o crates/embassy-boot-nrf/git.zup +docserver-builder -i ./embassy-boot/rp -o crates/embassy-boot-rp/git.zup +docserver-builder -i ./embassy-boot/stm32 -o crates/embassy-boot-stm32/git.zup +docserver-builder -i ./embassy-cortex-m -o crates/embassy-cortex-m/git.zup +docserver-builder -i ./embassy-embedded-hal -o crates/embassy-embedded-hal/git.zup +docserver-builder -i ./embassy-executor -o crates/embassy-executor/git.zup +docserver-builder -i ./embassy-futures -o crates/embassy-futures/git.zup +docserver-builder -i ./embassy-lora -o crates/embassy-lora/git.zup +docserver-builder -i ./embassy-net -o crates/embassy-net/git.zup +docserver-builder -i ./embassy-net-driver -o crates/embassy-net-driver/git.zup +docserver-builder -i ./embassy-net-driver-channel -o crates/embassy-net-driver-channel/git.zup +docserver-builder -i ./embassy-nrf -o crates/embassy-nrf/git.zup +docserver-builder -i ./embassy-rp -o crates/embassy-rp/git.zup +docserver-builder -i ./embassy-sync -o crates/embassy-sync/git.zup +docserver-builder -i ./embassy-time -o crates/embassy-time/git.zup +docserver-builder -i ./embassy-usb -o crates/embassy-usb/git.zup +docserver-builder -i ./embassy-usb-driver -o crates/embassy-usb-driver/git.zup +docserver-builder -i ./embassy-usb-logger -o crates/embassy-usb-logger/git.zup export KUBECONFIG=/ci/secrets/kubeconfig.yml POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) From d7d66bd74f2ef1bc8903b15df630ddbb8fe97df4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 1 Jun 2023 00:15:37 +0200 Subject: [PATCH 04/98] Document w5500, cyw43 --- .github/ci/doc.sh | 3 +++ cyw43-pio/Cargo.toml | 5 +++++ cyw43/Cargo.toml | 6 ++++++ embassy-net-w5500/Cargo.toml | 5 +++++ 4 files changed, 19 insertions(+) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 7f7dfaa03..736249368 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -29,6 +29,9 @@ docserver-builder -i ./embassy-time -o crates/embassy-time/git.zup docserver-builder -i ./embassy-usb -o crates/embassy-usb/git.zup docserver-builder -i ./embassy-usb-driver -o crates/embassy-usb-driver/git.zup docserver-builder -i ./embassy-usb-logger -o crates/embassy-usb-logger/git.zup +docserver-builder -i ./cyw43 -o crates/cyw43/git.zup +docserver-builder -i ./cyw43-pio -o crates/cyw43-pio/git.zup +docserver-builder -i ./embassy-net-w5500 -o crates/embassy-net-w5500/git.zup export KUBECONFIG=/ci/secrets/kubeconfig.yml POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 6e9e784a0..14c07178f 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -15,3 +15,8 @@ pio-proc = "0.2" pio = "0.2.1" fixed = "1.23.1" defmt = { version = "0.3", optional = true } + +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-pio-v$VERSION/cyw43-pio/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/cyw43-pio/src/" +target = "thumbv6m-none-eabi" diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index c7f8816f5..61caa0272 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -26,3 +26,9 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.10" } num_enum = { version = "0.5.7", default-features = false } + +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-v$VERSION/cyw43/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/cyw43/src/" +target = "thumbv6m-none-eabi" +features = ["defmt", "firmware-logs"] \ No newline at end of file diff --git a/embassy-net-w5500/Cargo.toml b/embassy-net-w5500/Cargo.toml index 3f19e3d39..37d15c7ac 100644 --- a/embassy-net-w5500/Cargo.toml +++ b/embassy-net-w5500/Cargo.toml @@ -14,3 +14,8 @@ embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver- embassy-time = { version = "0.1.0" } embassy-futures = { version = "0.1.0" } defmt = { version = "0.3", optional = true } + +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-w5500-v$VERSION/embassy-net-w5500/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-w5500/src/" +target = "thumbv7em-none-eabi" \ No newline at end of file From 1d8321b821d114b369d5a087a1a7a6600228b032 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 1 Jun 2023 01:32:11 +0200 Subject: [PATCH 05/98] Use make_static! from static-cell v1.1 --- embassy-executor/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-sync/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 4 +-- examples/nrf52840/src/bin/usb_ethernet.rs | 32 ++++++++----------- .../nrf52840/src/bin/usb_serial_multitask.rs | 23 ++++--------- examples/nrf5340/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- .../rp/src/bin/ethernet_w5500_multisocket.rs | 17 +++------- .../rp/src/bin/ethernet_w5500_tcp_client.rs | 17 +++------- .../rp/src/bin/ethernet_w5500_tcp_server.rs | 18 +++-------- examples/rp/src/bin/ethernet_w5500_udp.rs | 18 +++-------- .../rp/src/bin/lora_p2p_send_multicore.rs | 2 +- examples/rp/src/bin/multicore.rs | 2 +- examples/rp/src/bin/uart_buffered_split.rs | 15 ++------- examples/rp/src/bin/usb_ethernet.rs | 30 ++++++++--------- examples/rp/src/bin/wifi_ap_tcp_server.rs | 16 +++------- examples/rp/src/bin/wifi_scan.rs | 12 ++----- examples/rp/src/bin/wifi_tcp_server.rs | 16 +++------- examples/std/Cargo.toml | 2 +- examples/std/src/bin/net.rs | 18 ++++------- examples/std/src/bin/net_dns.rs | 18 ++++------- examples/std/src/bin/net_udp.rs | 18 ++++------- examples/std/src/bin/tcp_accept.rs | 18 ++++------- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f4/src/bin/usb_ethernet.rs | 32 ++++++++----------- examples/stm32f7/Cargo.toml | 2 +- examples/stm32f7/src/bin/eth.rs | 21 +++++------- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h5/src/bin/eth.rs | 21 +++++------- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h7/src/bin/eth.rs | 21 +++++------- examples/stm32h7/src/bin/eth_client.rs | 21 +++++------- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32l5/src/bin/usb_ethernet.rs | 30 ++++++++--------- 38 files changed, 168 insertions(+), 300 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index ce032479d..1e5494ef8 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -65,7 +65,7 @@ embassy-macros = { version = "0.2.0", path = "../embassy-macros" } embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true} atomic-polyfill = "1.0.1" critical-section = "1.1" -static_cell = "1.0" +static_cell = "1.1" # arch-cortex-m dependencies cortex-m = { version = "0.7.6", optional = true } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index e032dfdae..5f08c7f33 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -86,4 +86,4 @@ rp2040-boot2 = "0.3" [dev-dependencies] embassy-executor = { version = "0.2.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] } -static_cell = "1.0" +static_cell = "1.1" diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index bc06b92cd..340724eab 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -45,4 +45,4 @@ futures-util = { version = "0.3.17", features = [ "channel" ] } # Enable critical-section implementation for std, for tests critical-section = { version = "1.1", features = ["std"] } -static_cell = "1.0" +static_cell = "1.1" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 0f75b3ab7..6627b7861 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [features] default = ["nightly"] -nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-time/nightly", "embassy-time/unstable-traits", +nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-time/nightly", "embassy-time/unstable-traits", "static_cell/nightly", "embassy-usb", "embedded-io/async", "embassy-net", "embassy-lora", "lora-phy", "lorawan-device", "lorawan"] [dependencies] @@ -26,7 +26,7 @@ lorawan = { version = "0.7.3", default-features = false, features = ["default-cr defmt = "0.3" defmt-rtt = "0.4" -static_cell = "1.0" +static_cell = "1.1" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index 786025c43..1065f5b5d 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs @@ -16,7 +16,7 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, Config, UsbDevice}; use embedded_io::asynch::Write; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -27,15 +27,6 @@ bind_interrupts!(struct Irqs { type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - const MTU: usize = 1514; #[embassy_executor::task] @@ -83,11 +74,11 @@ async fn main(spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 128])[..], - &mut singleton!([0; 128])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 128])[..], + &mut make_static!([0; 128])[..], ); // Our MAC addr. @@ -96,14 +87,14 @@ async fn main(spawner: Spawner) { let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); @@ -120,7 +111,12 @@ async fn main(spawner: Spawner) { let seed = u64::from_le_bytes(seed); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); unwrap!(spawner.spawn(net_task(stack))); diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs index ac22d9499..cd4392903 100644 --- a/examples/nrf52840/src/bin/usb_serial_multitask.rs +++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs @@ -12,7 +12,7 @@ use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::{Builder, Config, UsbDevice}; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -20,15 +20,6 @@ bind_interrupts!(struct Irqs { POWER_CLOCK => usb::vbus_detect::InterruptHandler; }); -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>; #[embassy_executor::task] @@ -73,17 +64,17 @@ async fn main(spawner: Spawner) { config.device_protocol = 0x01; config.composite_with_iads = true; - let state = singleton!(State::new()); + let state = make_static!(State::new()); // Create embassy-usb DeviceBuilder using the driver and config. let mut builder = Builder::new( driver, config, - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 128])[..], - &mut singleton!([0; 128])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 128])[..], + &mut make_static!([0; 128])[..], ); // Create classes on the builder. diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 40422e7df..efb66bae6 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -42,7 +42,7 @@ embedded-io = { version = "0.4.0", features = [ "async" ]} defmt = "0.3" defmt-rtt = "0.4" -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 58b701915..e946b481d 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -45,7 +45,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } embedded-hal-async = "0.2.0-alpha.1" embedded-io = { version = "0.4.0", features = ["async", "defmt"] } embedded-storage = { version = "0.3" } -static_cell = "1.0.0" +static_cell = { version = "1.1", features = ["nightly"]} log = "0.4" pio-proc = "0.2" pio = "0.2.1" diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index c8e6d46a6..63e142e7d 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -19,18 +19,9 @@ use embassy_time::Duration; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::task] async fn ethernet_task( runner: Runner< @@ -62,7 +53,7 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PIN_20, Level::High); let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); + let state = make_static!(State::<8, 8>::new()); let (device, runner) = embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); @@ -71,10 +62,10 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( device, embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<3>::new()), + make_static!(StackResources::<3>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index 9a7c3ad19..a532de00d 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -21,18 +21,9 @@ use embassy_time::{Duration, Timer}; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::task] async fn ethernet_task( runner: Runner< @@ -65,7 +56,7 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PIN_20, Level::High); let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); + let state = make_static!(State::<8, 8>::new()); let (device, runner) = embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); @@ -74,10 +65,10 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( device, embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index f02543246..599f6b1e9 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -20,18 +20,8 @@ use embassy_time::Duration; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::task] async fn ethernet_task( runner: Runner< @@ -64,7 +54,7 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PIN_20, Level::High); let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); + let state = make_static!(State::<8, 8>::new()); let (device, runner) = embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); @@ -73,10 +63,10 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( device, embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 2c54f711e..ac5a65bb6 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -18,18 +18,8 @@ use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embedded_hal_async::spi::ExclusiveDevice; use rand::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::task] async fn ethernet_task( runner: Runner< @@ -61,7 +51,7 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PIN_20, Level::High); let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); + let state = make_static!(State::<8, 8>::new()); let (device, runner) = embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); @@ -70,10 +60,10 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( device, embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs index 5585606d8..eef2f7a53 100644 --- a/examples/rp/src/bin/lora_p2p_send_multicore.rs +++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs @@ -7,7 +7,6 @@ use defmt::*; use embassy_executor::Executor; -use embassy_executor::_export::StaticCell; use embassy_lora::iv::GenericSx126xInterfaceVariant; use embassy_rp::gpio::{AnyPin, Input, Level, Output, Pin, Pull}; use embassy_rp::multicore::{spawn_core1, Stack}; @@ -19,6 +18,7 @@ use embassy_time::{Delay, Duration, Timer}; use lora_phy::mod_params::*; use lora_phy::sx1261_2::SX1261_2; use lora_phy::LoRa; +use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; static mut CORE1_STACK: Stack<4096> = Stack::new(); diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 376b2b61e..57278dd6c 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -4,13 +4,13 @@ use defmt::*; use embassy_executor::Executor; -use embassy_executor::_export::StaticCell; use embassy_rp::gpio::{Level, Output}; use embassy_rp::multicore::{spawn_core1, Stack}; use embassy_rp::peripherals::PIN_25; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_time::{Duration, Timer}; +use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; static mut CORE1_STACK: Stack<4096> = Stack::new(); diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index d6f01b4de..9df99bd58 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -4,34 +4,25 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_executor::_export::StaticCell; use embassy_rp::bind_interrupts; use embassy_rp::peripherals::UART0; use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::{Read, Write}; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { UART0_IRQ => BufferedInterruptHandler; }); -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); - let tx_buf = &mut singleton!([0u8; 16])[..]; - let rx_buf = &mut singleton!([0u8; 16])[..]; + let tx_buf = &mut make_static!([0u8; 16])[..]; + let rx_buf = &mut make_static!([0u8; 16])[..]; let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); let (rx, mut tx) = uart.split(); diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 38ff1620d..16fbf5e91 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -13,7 +13,7 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, Config, UsbDevice}; use embedded_io::asynch::Write; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -22,15 +22,6 @@ bind_interrupts!(struct Irqs { type MyDriver = Driver<'static, peripherals::USB>; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - const MTU: usize = 1514; #[embassy_executor::task] @@ -73,10 +64,10 @@ async fn main(spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 128])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 128])[..], ); // Our MAC addr. @@ -85,14 +76,14 @@ async fn main(spawner: Spawner) { let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); @@ -106,7 +97,12 @@ async fn main(spawner: Spawner) { let seed = 1234; // guaranteed random, chosen by a fair dice roll // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); unwrap!(spawner.spawn(net_task(stack))); diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 15264524e..b27d3c9f8 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -16,17 +16,9 @@ use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; use embassy_rp::pio::Pio; use embassy_time::Duration; use embedded_io::asynch::Write; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -60,7 +52,7 @@ async fn main(spawner: Spawner) { let mut pio = Pio::new(p.PIO0); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); - let state = singleton!(cyw43::State::new()); + let state = make_static!(cyw43::State::new()); let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; unwrap!(spawner.spawn(wifi_task(runner))); @@ -80,10 +72,10 @@ async fn main(spawner: Spawner) { let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( net_device, config, - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index aa5e5a399..79534f229 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -13,17 +13,9 @@ use embassy_net::Stack; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; use embassy_rp::pio::Pio; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -57,7 +49,7 @@ async fn main(spawner: Spawner) { let mut pio = Pio::new(p.PIO0); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); - let state = singleton!(cyw43::State::new()); + let state = make_static!(cyw43::State::new()); let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; unwrap!(spawner.spawn(wifi_task(runner))); diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index eafa25f68..1a00bca96 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -16,17 +16,9 @@ use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; use embassy_rp::pio::Pio; use embassy_time::Duration; use embedded_io::asynch::Write; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -60,7 +52,7 @@ async fn main(spawner: Spawner) { let mut pio = Pio::new(p.PIO0); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); - let state = singleton!(cyw43::State::new()); + let state = make_static!(cyw43::State::new()); let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; unwrap!(spawner.spawn(wifi_task(runner))); @@ -80,10 +72,10 @@ async fn main(spawner: Spawner) { let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( net_device, config, - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 36770ca9c..878ad8c5a 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -22,4 +22,4 @@ libc = "0.2.101" clap = { version = "3.0.0-beta.5", features = ["derive"] } rand_core = { version = "0.6.3", features = ["std"] } heapless = { version = "0.7.5", default-features = false } -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index d93616254..b42bfc13b 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs @@ -11,21 +11,12 @@ use embedded_io::asynch::Write; use heapless::Vec; use log::*; use rand_core::{OsRng, RngCore}; -use static_cell::StaticCell; +use static_cell::{make_static, StaticCell}; #[path = "../tuntap.rs"] mod tuntap; use crate::tuntap::TunTapDevice; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[derive(Parser)] #[clap(version = "1.0")] struct Opts { @@ -66,7 +57,12 @@ async fn main_task(spawner: Spawner) { let seed = u64::from_le_bytes(seed); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<3>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<3>::new()), + seed + )); // Launch network task spawner.spawn(net_task(stack)).unwrap(); diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index d1e1f8212..932ac5831 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs @@ -9,21 +9,12 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; use heapless::Vec; use log::*; use rand_core::{OsRng, RngCore}; -use static_cell::StaticCell; +use static_cell::{make_static, StaticCell}; #[path = "../tuntap.rs"] mod tuntap; use crate::tuntap::TunTapDevice; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[derive(Parser)] #[clap(version = "1.0")] struct Opts { @@ -65,7 +56,12 @@ async fn main_task(spawner: Spawner) { let seed = u64::from_le_bytes(seed); // Init network stack - let stack: &Stack<_> = &*singleton!(Stack::new(device, config, singleton!(StackResources::<3>::new()), seed)); + let stack: &Stack<_> = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<3>::new()), + seed + )); // Launch network task spawner.spawn(net_task(stack)).unwrap(); diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index 4df23edf6..d89ec7643 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs @@ -7,21 +7,12 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; use heapless::Vec; use log::*; use rand_core::{OsRng, RngCore}; -use static_cell::StaticCell; +use static_cell::{make_static, StaticCell}; #[path = "../tuntap.rs"] mod tuntap; use crate::tuntap::TunTapDevice; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[derive(Parser)] #[clap(version = "1.0")] struct Opts { @@ -62,7 +53,12 @@ async fn main_task(spawner: Spawner) { let seed = u64::from_le_bytes(seed); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<3>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<3>::new()), + seed + )); // Launch network task spawner.spawn(net_task(stack)).unwrap(); diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index 97ce77f42..d24e218dc 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs @@ -12,21 +12,12 @@ use embedded_io::asynch::Write as _; use heapless::Vec; use log::*; use rand_core::{OsRng, RngCore}; -use static_cell::StaticCell; +use static_cell::{make_static, StaticCell}; #[path = "../tuntap.rs"] mod tuntap; use crate::tuntap::TunTapDevice; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[derive(Parser)] #[clap(version = "1.0")] struct Opts { @@ -77,7 +68,12 @@ async fn main_task(spawner: Spawner) { let seed = u64::from_le_bytes(seed); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<3>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<3>::new()), + seed + )); // Launch network task spawner.spawn(net_task(stack)).unwrap(); diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 9c59c45c6..ff134bb0e 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -16,4 +16,4 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] } -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 3d314e6c5..0fe9cb122 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -23,4 +23,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa heapless = { version = "0.7.5", default-features = false } nb = "1.0.0" embedded-storage = "0.3.0" -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index f5f8b632d..3a8efdd06 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -25,7 +25,7 @@ heapless = { version = "0.7.5", default-features = false } nb = "1.0.0" embedded-storage = "0.3.0" micromath = "2.0.0" -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} chrono = { version = "^0.4", default-features = false} [profile.release] diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index c4e395f0f..d229cc3ef 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs @@ -14,20 +14,11 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, UsbDevice}; use embedded_io::asynch::Write; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; type UsbDriver = Driver<'static, embassy_stm32::peripherals::USB_OTG_FS>; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - const MTU: usize = 1514; #[embassy_executor::task] @@ -60,7 +51,7 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(config); // Create the driver, from the HAL. - let ep_out_buffer = &mut singleton!([0; 256])[..]; + let ep_out_buffer = &mut make_static!([0; 256])[..]; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer); // Create embassy-usb Config @@ -81,10 +72,10 @@ async fn main(spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 128])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 128])[..], ); // Our MAC addr. @@ -93,14 +84,14 @@ async fn main(spawner: Spawner) { let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); @@ -117,7 +108,12 @@ async fn main(spawner: Spawner) { let seed = u64::from_le_bytes(seed); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); unwrap!(spawner.spawn(net_task(stack))); diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 6ddb7186e..7a650067c 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -26,4 +26,4 @@ nb = "1.0.0" rand_core = "0.6.3" critical-section = "1.1" embedded-storage = "0.3.0" -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 6d286c368..d8438241c 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -15,18 +15,8 @@ use embassy_stm32::{bind_interrupts, eth, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use rand_core::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; }); @@ -55,7 +45,7 @@ async fn main(spawner: Spawner) -> ! { let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; let device = Ethernet::new( - singleton!(PacketQueue::<16, 16>::new()), + make_static!(PacketQueue::<16, 16>::new()), p.ETH, Irqs, p.PA1, @@ -80,7 +70,12 @@ async fn main(spawner: Spawner) -> ! { //}); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); // Launch network task unwrap!(spawner.spawn(net_task(&stack))); diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index b9204fba8..d49a0dde7 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -30,7 +30,7 @@ critical-section = "1.1" micromath = "2.0.0" stm32-fmc = "0.2.4" embedded-storage = "0.3.0" -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} # cargo build/run [profile.dev] diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index fa1f225fe..5d1eadf4b 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -16,18 +16,8 @@ use embassy_stm32::{bind_interrupts, eth, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use rand_core::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; }); @@ -74,7 +64,7 @@ async fn main(spawner: Spawner) -> ! { let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; let device = Ethernet::new( - singleton!(PacketQueue::<4, 4>::new()), + make_static!(PacketQueue::<4, 4>::new()), p.ETH, Irqs, p.PA1, @@ -99,7 +89,12 @@ async fn main(spawner: Spawner) -> ! { //}); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); // Launch network task unwrap!(spawner.spawn(net_task(&stack))); diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 8b534ca05..08b57f988 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -30,7 +30,7 @@ critical-section = "1.1" micromath = "2.0.0" stm32-fmc = "0.2.4" embedded-storage = "0.3.0" -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} # cargo build/run [profile.dev] diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index dbfc90cf4..3aa7b2271 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -15,18 +15,8 @@ use embassy_stm32::{bind_interrupts, eth, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use rand_core::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; }); @@ -56,7 +46,7 @@ async fn main(spawner: Spawner) -> ! { let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; let device = Ethernet::new( - singleton!(PacketQueue::<16, 16>::new()), + make_static!(PacketQueue::<16, 16>::new()), p.ETH, Irqs, p.PA1, @@ -81,7 +71,12 @@ async fn main(spawner: Spawner) -> ! { //}); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); // Launch network task unwrap!(spawner.spawn(net_task(&stack))); diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 14e6b7914..575c716b6 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -16,18 +16,8 @@ use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; use rand_core::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; }); @@ -57,7 +47,7 @@ async fn main(spawner: Spawner) -> ! { let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; let device = Ethernet::new( - singleton!(PacketQueue::<16, 16>::new()), + make_static!(PacketQueue::<16, 16>::new()), p.ETH, Irqs, p.PA1, @@ -82,7 +72,12 @@ async fn main(spawner: Spawner) -> ! { //}); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); // Launch network task unwrap!(spawner.spawn(net_task(&stack))); diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index ffb6cdb43..235f1b0b3 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -31,4 +31,4 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } embedded-hal = "0.2.6" -static_cell = "1.0" +static_cell = "1.1" diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index acb48c765..2ac9c180d 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -25,4 +25,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa heapless = { version = "0.7.5", default-features = false } rand_core = { version = "0.6.3", default-features = false } embedded-io = { version = "0.4.0", features = ["async"] } -static_cell = "1.0" +static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index b84e53d3a..6163e0709 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -15,20 +15,11 @@ use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, UsbDevice}; use embedded_io::asynch::Write; use rand_core::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; type MyDriver = Driver<'static, embassy_stm32::peripherals::USB>; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - const MTU: usize = 1514; bind_interrupts!(struct Irqs { @@ -78,10 +69,10 @@ async fn main(spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 128])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 128])[..], ); // Our MAC addr. @@ -90,14 +81,14 @@ async fn main(spawner: Spawner) { let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); @@ -112,7 +103,12 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); unwrap!(spawner.spawn(net_task(stack))); From 2a435e53b761182dabf9496963052f8323125f3a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 1 Jun 2023 02:22:31 +0200 Subject: [PATCH 06/98] cortex-m: remove PeripheralMutex. --- embassy-cortex-m/src/lib.rs | 1 - embassy-cortex-m/src/peripheral.rs | 144 ----------------------------- 2 files changed, 145 deletions(-) delete mode 100644 embassy-cortex-m/src/peripheral.rs diff --git a/embassy-cortex-m/src/lib.rs b/embassy-cortex-m/src/lib.rs index e4b713a06..7bc16d3ba 100644 --- a/embassy-cortex-m/src/lib.rs +++ b/embassy-cortex-m/src/lib.rs @@ -7,4 +7,3 @@ pub(crate) mod fmt; pub use embassy_executor as executor; pub mod interrupt; -pub mod peripheral; diff --git a/embassy-cortex-m/src/peripheral.rs b/embassy-cortex-m/src/peripheral.rs deleted file mode 100644 index e2f295579..000000000 --- a/embassy-cortex-m/src/peripheral.rs +++ /dev/null @@ -1,144 +0,0 @@ -//! Peripheral interrupt handling specific to cortex-m devices. -use core::mem::MaybeUninit; - -use cortex_m::peripheral::scb::VectActive; -use cortex_m::peripheral::{NVIC, SCB}; -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; - -use crate::interrupt::{Interrupt, InterruptExt, Priority}; - -/// A type which can be used as state with `PeripheralMutex`. -/// -/// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt, -/// and `&mut T` is only `Send` where `T: Send`. -pub trait PeripheralState: Send { - /// The interrupt that is used for this peripheral. - type Interrupt: Interrupt; - - /// The interrupt handler that should be invoked for the peripheral. Implementations need to clear the appropriate interrupt flags to ensure the handle will not be called again. - fn on_interrupt(&mut self); -} - -/// A type for storing the state of a peripheral that can be stored in a static. -pub struct StateStorage(MaybeUninit); - -impl StateStorage { - /// Create a new instance for storing peripheral state. - pub const fn new() -> Self { - Self(MaybeUninit::uninit()) - } -} - -/// A type for a peripheral that keeps the state of a peripheral that can be accessed from thread mode and an interrupt handler in -/// a safe way. -pub struct PeripheralMutex<'a, S: PeripheralState> { - state: *mut S, - irq: PeripheralRef<'a, S::Interrupt>, -} - -/// Whether `irq` can be preempted by the current interrupt. -pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool { - match SCB::vect_active() { - // Thread mode can't preempt anything. - VectActive::ThreadMode => false, - // Exceptions don't always preempt interrupts, - // but there isn't much of a good reason to be keeping a `PeripheralMutex` in an exception anyway. - VectActive::Exception(_) => true, - VectActive::Interrupt { irqn } => { - #[derive(Clone, Copy)] - struct NrWrap(u16); - unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { - fn number(self) -> u16 { - self.0 - } - } - NVIC::get_priority(NrWrap(irqn.into())) < irq.get_priority().into() - } - } -} - -impl<'a, S: PeripheralState> PeripheralMutex<'a, S> { - /// Create a new `PeripheralMutex` wrapping `irq`, with `init` initializing the initial state. - /// - /// Registers `on_interrupt` as the `irq`'s handler, and enables it. - pub fn new( - irq: impl Peripheral

+ 'a, - storage: &'a mut StateStorage, - init: impl FnOnce() -> S, - ) -> Self { - into_ref!(irq); - - if can_be_preempted(&*irq) { - panic!( - "`PeripheralMutex` cannot be created in an interrupt with higher priority than the interrupt it wraps" - ); - } - - let state_ptr = storage.0.as_mut_ptr(); - - // Safety: The pointer is valid and not used by anyone else - // because we have the `&mut StateStorage`. - unsafe { state_ptr.write(init()) }; - - irq.disable(); - irq.set_handler(|p| unsafe { - // Safety: it's OK to get a &mut to the state, since - // - We checked that the thread owning the `PeripheralMutex` can't preempt us in `new`. - // Interrupts' priorities can only be changed with raw embassy `Interrupts`, - // which can't safely store a `PeripheralMutex` across invocations. - // - We can't have preempted a with() call because the irq is disabled during it. - let state = &mut *(p as *mut S); - state.on_interrupt(); - }); - irq.set_handler_context(state_ptr as *mut ()); - irq.enable(); - - Self { irq, state: state_ptr } - } - - /// Access the peripheral state ensuring interrupts are disabled so that the state can be - /// safely accessed. - pub fn with(&mut self, f: impl FnOnce(&mut S) -> R) -> R { - self.irq.disable(); - - // Safety: it's OK to get a &mut to the state, since the irq is disabled. - let state = unsafe { &mut *self.state }; - let r = f(state); - - self.irq.enable(); - - r - } - - /// Returns whether the wrapped interrupt is currently in a pending state. - pub fn is_pending(&self) -> bool { - self.irq.is_pending() - } - - /// Forces the wrapped interrupt into a pending state. - pub fn pend(&self) { - self.irq.pend() - } - - /// Forces the wrapped interrupt out of a pending state. - pub fn unpend(&self) { - self.irq.unpend() - } - - /// Gets the priority of the wrapped interrupt. - pub fn priority(&self) -> Priority { - self.irq.get_priority() - } -} - -impl<'a, S: PeripheralState> Drop for PeripheralMutex<'a, S> { - fn drop(&mut self) { - self.irq.disable(); - self.irq.remove_handler(); - - // safety: - // - we initialized the state in `new`, so we know it's initialized. - // - the irq is disabled, so it won't preempt us while dropping. - unsafe { self.state.drop_in_place() } - } -} From 404aa292890503806a32eac5ae518dbeeadd60eb Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 1 Jun 2023 02:22:46 +0200 Subject: [PATCH 07/98] cortex-m: remove owned interrupts. --- embassy-cortex-m/src/interrupt.rs | 180 +++++------------- embassy-lora/src/iv.rs | 6 +- embassy-macros/src/lib.rs | 11 -- .../src/macros/cortex_m_interrupt_declare.rs | 21 +- .../src/macros/cortex_m_interrupt_take.rs | 57 ------ embassy-macros/src/macros/mod.rs | 1 - embassy-nrf/src/buffered_uarte.rs | 8 +- embassy-nrf/src/gpiote.rs | 56 +++--- embassy-nrf/src/i2s.rs | 5 +- embassy-nrf/src/lib.rs | 2 +- embassy-nrf/src/pdm.rs | 6 +- embassy-nrf/src/qdec.rs | 7 +- embassy-nrf/src/qspi.rs | 6 +- embassy-nrf/src/rng.rs | 7 +- embassy-nrf/src/saadc.rs | 6 +- embassy-nrf/src/spim.rs | 6 +- embassy-nrf/src/spis.rs | 6 +- embassy-nrf/src/temp.rs | 7 +- embassy-nrf/src/time_driver.rs | 7 +- embassy-nrf/src/twim.rs | 6 +- embassy-nrf/src/twis.rs | 6 +- embassy-nrf/src/uarte.rs | 14 +- embassy-nrf/src/usb/mod.rs | 6 +- embassy-nrf/src/usb/vbus_detect.rs | 6 +- embassy-rp/src/adc.rs | 6 +- embassy-rp/src/dma.rs | 9 +- embassy-rp/src/gpio.rs | 9 +- embassy-rp/src/i2c.rs | 14 +- embassy-rp/src/interrupt.rs | 2 +- embassy-rp/src/multicore.rs | 5 +- embassy-rp/src/pio.rs | 16 +- embassy-rp/src/timer.rs | 10 +- embassy-rp/src/uart/buffered.rs | 14 +- embassy-rp/src/uart/mod.rs | 14 +- embassy-rp/src/usb.rs | 8 +- embassy-stm32/src/dcmi.rs | 6 +- embassy-stm32/src/dma/bdma.rs | 7 +- embassy-stm32/src/dma/dma.rs | 7 +- embassy-stm32/src/dma/gpdma.rs | 7 +- embassy-stm32/src/eth/v1/mod.rs | 6 +- embassy-stm32/src/eth/v2/mod.rs | 6 +- embassy-stm32/src/exti.rs | 4 +- embassy-stm32/src/flash/asynch.rs | 7 +- embassy-stm32/src/i2c/v2.rs | 6 +- embassy-stm32/src/lib.rs | 2 +- embassy-stm32/src/sdmmc/mod.rs | 8 +- embassy-stm32/src/time_driver.rs | 7 +- embassy-stm32/src/tl_mbox/mod.rs | 10 +- embassy-stm32/src/usart/buffered.rs | 18 +- embassy-stm32/src/usart/mod.rs | 10 +- embassy-stm32/src/usb/usb.rs | 6 +- embassy-stm32/src/usb_otg/usb.rs | 8 +- examples/boot/bootloader/rp/Cargo.toml | 1 + examples/std/src/bin/tcp_accept.rs | 2 +- 54 files changed, 239 insertions(+), 439 deletions(-) delete mode 100644 embassy-macros/src/macros/cortex_m_interrupt_take.rs diff --git a/embassy-cortex-m/src/interrupt.rs b/embassy-cortex-m/src/interrupt.rs index 3a82726df..0e790eaaf 100644 --- a/embassy-cortex-m/src/interrupt.rs +++ b/embassy-cortex-m/src/interrupt.rs @@ -1,10 +1,8 @@ //! Interrupt handling for cortex-m devices. -use core::{mem, ptr}; +use core::mem; +use core::sync::atomic::{compiler_fence, Ordering}; -use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering}; use cortex_m::peripheral::NVIC; -use embassy_hal_common::Peripheral; -pub use embassy_macros::cortex_m_interrupt_take as take; /// Do not use. Used for macros and HALs only. Not covered by semver guarantees. #[doc(hidden)] @@ -43,22 +41,6 @@ pub trait Handler { /// This allows drivers to check bindings at compile-time. pub unsafe trait Binding> {} -/// Implementation detail, do not use outside embassy crates. -#[doc(hidden)] -pub struct DynHandler { - pub func: AtomicPtr<()>, - pub ctx: AtomicPtr<()>, -} - -impl DynHandler { - pub const fn new() -> Self { - Self { - func: AtomicPtr::new(ptr::null_mut()), - ctx: AtomicPtr::new(ptr::null_mut()), - } - } -} - #[derive(Clone, Copy)] pub(crate) struct NrWrap(pub(crate) u16); unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { @@ -69,144 +51,68 @@ unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { /// Represents an interrupt type that can be configured by embassy to handle /// interrupts. -pub unsafe trait Interrupt: Peripheral

{ +pub unsafe trait Interrupt { /// Return the NVIC interrupt number for this interrupt. - fn number(&self) -> u16; - /// Steal an instance of this interrupt - /// - /// # Safety - /// - /// This may panic if the interrupt has already been stolen and configured. - unsafe fn steal() -> Self; + fn number() -> u16; - /// Implementation detail, do not use outside embassy crates. - #[doc(hidden)] - unsafe fn __handler(&self) -> &'static DynHandler; -} - -/// Represents additional behavior for all interrupts. -pub trait InterruptExt: Interrupt { - /// Configure the interrupt handler for this interrupt. - /// - /// # Safety - /// - /// It is the responsibility of the caller to ensure the handler - /// points to a valid handler as long as interrupts are enabled. - fn set_handler(&self, func: unsafe fn(*mut ())); - - /// Remove the interrupt handler for this interrupt. - fn remove_handler(&self); - - /// Set point to a context that is passed to the interrupt handler when - /// an interrupt is pending. - /// - /// # Safety - /// - /// It is the responsibility of the caller to ensure the context - /// points to a valid handler as long as interrupts are enabled. - fn set_handler_context(&self, ctx: *mut ()); - - /// Enable the interrupt. Once enabled, the interrupt handler may - /// be called "any time". - fn enable(&self); + /// Enable the interrupt. + #[inline] + unsafe fn enable() { + compiler_fence(Ordering::SeqCst); + NVIC::unmask(NrWrap(Self::number())) + } /// Disable the interrupt. - fn disable(&self); + #[inline] + fn disable() { + NVIC::mask(NrWrap(Self::number())); + compiler_fence(Ordering::SeqCst); + } /// Check if interrupt is being handled. + #[inline] #[cfg(not(armv6m))] - fn is_active(&self) -> bool; + fn is_active() -> bool { + NVIC::is_active(NrWrap(Self::number())) + } /// Check if interrupt is enabled. - fn is_enabled(&self) -> bool; + #[inline] + fn is_enabled() -> bool { + NVIC::is_enabled(NrWrap(Self::number())) + } /// Check if interrupt is pending. - fn is_pending(&self) -> bool; + #[inline] + fn is_pending() -> bool { + NVIC::is_pending(NrWrap(Self::number())) + } /// Set interrupt pending. - fn pend(&self); + #[inline] + fn pend() { + NVIC::pend(NrWrap(Self::number())) + } /// Unset interrupt pending. - fn unpend(&self); + #[inline] + fn unpend() { + NVIC::unpend(NrWrap(Self::number())) + } /// Get the priority of the interrupt. - fn get_priority(&self) -> Priority; + #[inline] + fn get_priority() -> Priority { + Priority::from(NVIC::get_priority(NrWrap(Self::number()))) + } /// Set the interrupt priority. - fn set_priority(&self, prio: Priority); -} - -impl InterruptExt for T { - fn set_handler(&self, func: unsafe fn(*mut ())) { - compiler_fence(Ordering::SeqCst); - let handler = unsafe { self.__handler() }; - handler.func.store(func as *mut (), Ordering::Relaxed); - compiler_fence(Ordering::SeqCst); - } - - fn remove_handler(&self) { - compiler_fence(Ordering::SeqCst); - let handler = unsafe { self.__handler() }; - handler.func.store(ptr::null_mut(), Ordering::Relaxed); - compiler_fence(Ordering::SeqCst); - } - - fn set_handler_context(&self, ctx: *mut ()) { - let handler = unsafe { self.__handler() }; - handler.ctx.store(ctx, Ordering::Relaxed); - } - #[inline] - fn enable(&self) { - compiler_fence(Ordering::SeqCst); - unsafe { - NVIC::unmask(NrWrap(self.number())); - } - } - - #[inline] - fn disable(&self) { - NVIC::mask(NrWrap(self.number())); - compiler_fence(Ordering::SeqCst); - } - - #[inline] - #[cfg(not(armv6m))] - fn is_active(&self) -> bool { - NVIC::is_active(NrWrap(self.number())) - } - - #[inline] - fn is_enabled(&self) -> bool { - NVIC::is_enabled(NrWrap(self.number())) - } - - #[inline] - fn is_pending(&self) -> bool { - NVIC::is_pending(NrWrap(self.number())) - } - - #[inline] - fn pend(&self) { - NVIC::pend(NrWrap(self.number())) - } - - #[inline] - fn unpend(&self) { - NVIC::unpend(NrWrap(self.number())) - } - - #[inline] - fn get_priority(&self) -> Priority { - Priority::from(NVIC::get_priority(NrWrap(self.number()))) - } - - #[inline] - fn set_priority(&self, prio: Priority) { - unsafe { + fn set_priority(prio: Priority) { + critical_section::with(|_| unsafe { let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); - nvic.set_priority(NrWrap(self.number()), prio.into()) - } + nvic.set_priority(NrWrap(Self::number()), prio.into()) + }) } } diff --git a/embassy-lora/src/iv.rs b/embassy-lora/src/iv.rs index d515bc365..8d521040f 100644 --- a/embassy-lora/src/iv.rs +++ b/embassy-lora/src/iv.rs @@ -22,7 +22,7 @@ pub struct InterruptHandler {} #[cfg(feature = "stm32wl")] impl interrupt::Handler for InterruptHandler { unsafe fn on_interrupt() { - unsafe { SUBGHZ_RADIO::steal() }.disable(); + interrupt::SUBGHZ_RADIO::disable(); IRQ_SIGNAL.signal(()); } } @@ -49,7 +49,7 @@ where rf_switch_rx: Option, rf_switch_tx: Option, ) -> Result { - unsafe { interrupt::SUBGHZ_RADIO::steal() }.disable(); + interrupt::SUBGHZ_RADIO::disable(); Ok(Self { board_type: BoardType::Stm32wlSx1262, // updated when associated with a specific LoRa board rf_switch_rx, @@ -95,7 +95,7 @@ where } async fn await_irq(&mut self) -> Result<(), RadioError> { - unsafe { interrupt::SUBGHZ_RADIO::steal() }.enable(); + unsafe { interrupt::SUBGHZ_RADIO::enable() }; IRQ_SIGNAL.wait().await; Ok(()) } diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index dc5b519ff..d7ca1f69c 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -169,14 +169,3 @@ pub fn cortex_m_interrupt_declare(item: TokenStream) -> TokenStream { let name = syn::parse_macro_input!(item as syn::Ident); cortex_m_interrupt_declare::run(name).unwrap_or_else(|x| x).into() } - -/// # interrupt_take procedural macro -/// -/// core::panic! is used as a default way to panic in this macro as there is no sensible way of enabling/disabling defmt for macro generation. -/// We are aware that this brings bloat in the form of core::fmt, but the bloat is already included with e.g. array indexing panics. -/// To get rid of this bloat, use the compiler flags `-Zbuild-std=core -Zbuild-std-features=panic_immediate_abort`. -#[proc_macro] -pub fn cortex_m_interrupt_take(item: TokenStream) -> TokenStream { - let name = syn::parse_macro_input!(item as syn::Ident); - cortex_m_interrupt_take::run(name).unwrap_or_else(|x| x).into() -} diff --git a/embassy-macros/src/macros/cortex_m_interrupt_declare.rs b/embassy-macros/src/macros/cortex_m_interrupt_declare.rs index 699883efa..b317482f5 100644 --- a/embassy-macros/src/macros/cortex_m_interrupt_declare.rs +++ b/embassy-macros/src/macros/cortex_m_interrupt_declare.rs @@ -3,32 +3,19 @@ use quote::{format_ident, quote}; pub fn run(name: syn::Ident) -> Result { let name = format_ident!("{}", name); - let name_interrupt = format_ident!("{}", name); - let name_handler = format!("__EMBASSY_{}_HANDLER", name); - - let doc = format!("{} interrupt singleton.", name); + let doc = format!("{} interrupt.", name); let result = quote! { #[doc = #doc] #[allow(non_camel_case_types)] - pub struct #name_interrupt(()); - unsafe impl ::embassy_cortex_m::interrupt::Interrupt for #name_interrupt { - fn number(&self) -> u16 { + pub enum #name{} + unsafe impl ::embassy_cortex_m::interrupt::Interrupt for #name { + fn number() -> u16 { use cortex_m::interrupt::InterruptNumber; let irq = InterruptEnum::#name; irq.number() as u16 } - unsafe fn steal() -> Self { - Self(()) - } - unsafe fn __handler(&self) -> &'static ::embassy_cortex_m::interrupt::DynHandler { - #[export_name = #name_handler] - static HANDLER: ::embassy_cortex_m::interrupt::DynHandler = ::embassy_cortex_m::interrupt::DynHandler::new(); - &HANDLER - } } - - ::embassy_hal_common::impl_peripheral!(#name_interrupt); }; Ok(result) } diff --git a/embassy-macros/src/macros/cortex_m_interrupt_take.rs b/embassy-macros/src/macros/cortex_m_interrupt_take.rs deleted file mode 100644 index 4806d1c12..000000000 --- a/embassy-macros/src/macros/cortex_m_interrupt_take.rs +++ /dev/null @@ -1,57 +0,0 @@ -use proc_macro2::TokenStream; -use quote::{format_ident, quote}; - -pub fn run(name: syn::Ident) -> Result { - let name = format!("{}", name); - let name_interrupt = format_ident!("{}", name); - let name_handler = format!("__EMBASSY_{}_HANDLER", name); - - #[cfg(feature = "rtos-trace-interrupt")] - let (isr_enter, isr_exit) = ( - quote! { - ::embassy_executor::rtos_trace_interrupt! { - ::embassy_executor::_export::trace::isr_enter(); - } - }, - quote! { - ::embassy_executor::rtos_trace_interrupt! { - ::embassy_executor::_export::trace::isr_exit(); - } - }, - ); - - #[cfg(not(feature = "rtos-trace-interrupt"))] - let (isr_enter, isr_exit) = (quote! {}, quote! {}); - - let result = quote! { - { - #[allow(non_snake_case)] - #[export_name = #name] - pub unsafe extern "C" fn trampoline() { - extern "C" { - #[link_name = #name_handler] - static HANDLER: interrupt::DynHandler; - } - - let func = HANDLER.func.load(interrupt::_export::atomic::Ordering::Relaxed); - let ctx = HANDLER.ctx.load(interrupt::_export::atomic::Ordering::Relaxed); - let func: fn(*mut ()) = ::core::mem::transmute(func); - #isr_enter - - func(ctx); - #isr_exit - - } - - static TAKEN: interrupt::_export::atomic::AtomicBool = interrupt::_export::atomic::AtomicBool::new(false); - - if TAKEN.compare_exchange(false, true, interrupt::_export::atomic::Ordering::AcqRel, interrupt::_export::atomic::Ordering::Acquire).is_err() { - core::panic!("IRQ Already taken"); - } - - let irq: interrupt::#name_interrupt = unsafe { ::core::mem::transmute(()) }; - irq - } - }; - Ok(result) -} diff --git a/embassy-macros/src/macros/mod.rs b/embassy-macros/src/macros/mod.rs index e547736fc..a5e7a50e6 100644 --- a/embassy-macros/src/macros/mod.rs +++ b/embassy-macros/src/macros/mod.rs @@ -1,5 +1,4 @@ pub mod cortex_m_interrupt; pub mod cortex_m_interrupt_declare; -pub mod cortex_m_interrupt_take; pub mod main; pub mod task; diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 4d053c023..b4fe2d874 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -24,7 +24,7 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari use crate::gpio::sealed::Pin; use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; -use crate::interrupt::{self, InterruptExt}; +use crate::interrupt::{self}; use crate::ppi::{ self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, }; @@ -362,8 +362,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { ppi_ch2.disable(); ppi_group.add_channel(&ppi_ch2); - unsafe { U::Interrupt::steal() }.pend(); - unsafe { U::Interrupt::steal() }.enable(); + U::Interrupt::pend(); + unsafe { U::Interrupt::enable() }; Self { _peri: peri, @@ -375,7 +375,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { } fn pend_irq() { - unsafe { ::steal() }.pend() + U::Interrupt::pend() } /// Adjust the baud rate to the provided value. diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 66c682b43..2ec5220a7 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -9,7 +9,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin}; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::ppi::{Event, Task}; use crate::{interrupt, pac, peripherals}; @@ -74,42 +74,38 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) { } // Enable interrupts - cfg_if::cfg_if! { - if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s"))] { - let irq = unsafe { interrupt::GPIOTE0::steal() }; - } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns"))] { - let irq = unsafe { interrupt::GPIOTE1::steal() }; - } else { - let irq = unsafe { interrupt::GPIOTE::steal() }; - } - } + #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))] + type Irq = interrupt::GPIOTE0; + #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))] + type Irq = interrupt::GPIOTE1; + #[cfg(any(feature = "_nrf52", feature = "nrf5340-net"))] + type Irq = interrupt::GPIOTE; - irq.unpend(); - irq.set_priority(irq_prio); - irq.enable(); + Irq::unpend(); + Irq::set_priority(irq_prio); + unsafe { Irq::enable() }; let g = regs(); g.events_port.write(|w| w); g.intenset.write(|w| w.port().set()); } -cfg_if::cfg_if! { - if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s"))] { - #[interrupt] - fn GPIOTE0() { - unsafe { handle_gpiote_interrupt() }; - } - } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns"))] { - #[interrupt] - fn GPIOTE1() { - unsafe { handle_gpiote_interrupt() }; - } - } else { - #[interrupt] - fn GPIOTE() { - unsafe { handle_gpiote_interrupt() }; - } - } +#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))] +#[interrupt] +fn GPIOTE0() { + unsafe { handle_gpiote_interrupt() }; +} + +#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))] +#[interrupt] +fn GPIOTE1() { + unsafe { handle_gpiote_interrupt() }; +} + +#[cfg(any(feature = "_nrf52", feature = "nrf5340-net"))] +#[interrupt] +fn GPIOTE() { + unsafe { handle_gpiote_interrupt() }; } unsafe fn handle_gpiote_interrupt() { diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs index 8a1188ce4..13db77d3b 100644 --- a/embassy-nrf/src/i2s.rs +++ b/embassy-nrf/src/i2s.rs @@ -9,7 +9,6 @@ use core::ops::{Deref, DerefMut}; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::InterruptExt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -564,8 +563,8 @@ impl<'d, T: Instance> I2S<'d, T> { } fn setup_interrupt(&self) { - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; let device = Device::::new(); device.disable_tx_ptr_interrupt(); diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index d4d7a1cad..6b57c2545 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -96,7 +96,7 @@ mod chip; pub mod interrupt { //! Interrupt definitions and macros to bind them. pub use cortex_m::interrupt::{CriticalSection, Mutex}; - pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, InterruptExt, Priority}; + pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, Priority}; pub use crate::chip::irqs::*; diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 8815bb316..9df685a26 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -14,7 +14,7 @@ use futures::future::poll_fn; use crate::chip::EASY_DMA_SIZE; use crate::gpio::sealed::Pin; use crate::gpio::{AnyPin, Pin as GpioPin}; -use crate::interrupt::{self, InterruptExt}; +use crate::interrupt::{self}; use crate::Peripheral; /// Interrupt handler. @@ -94,8 +94,8 @@ impl<'d, T: Instance> Pdm<'d, T> { r.gainr.write(|w| w.gainr().default_gain()); // IRQ - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; r.enable.write(|w| w.enable().set_bit()); diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs index c845492fc..5761d04e1 100644 --- a/embassy-nrf/src/qdec.rs +++ b/embassy-nrf/src/qdec.rs @@ -6,12 +6,11 @@ use core::future::poll_fn; use core::marker::PhantomData; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, PeripheralRef}; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Pin as GpioPin}; -use crate::interrupt::InterruptExt; +use crate::interrupt::Interrupt; use crate::{interrupt, Peripheral}; /// Quadrature decoder driver. @@ -134,8 +133,8 @@ impl<'d, T: Instance> Qdec<'d, T> { SamplePeriod::_131ms => w.sampleper()._131ms(), }); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; // Enable peripheral r.enable.write(|w| w.enable().set_bit()); diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index 2e16c2ff5..3f48568b3 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs @@ -12,7 +12,7 @@ use embassy_hal_common::{into_ref, PeripheralRef}; use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; use crate::gpio::{self, Pin as GpioPin}; -use crate::interrupt::{self, Interrupt, InterruptExt}; +use crate::interrupt::{self, Interrupt}; pub use crate::pac::qspi::ifconfig0::{ ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode, }; @@ -207,8 +207,8 @@ impl<'d, T: Instance> Qspi<'d, T> { w }); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; // Enable it r.enable.write(|w| w.enable().enabled()); diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index a5602248d..7e9b35481 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs @@ -8,12 +8,11 @@ use core::ptr; use core::sync::atomic::{AtomicPtr, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; -use crate::interrupt::InterruptExt; +use crate::interrupt::Interrupt; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -99,8 +98,8 @@ impl<'d, T: Instance> Rng<'d, T> { this.stop(); this.disable_irq(); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; this } diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index 8aff7df16..39764e380 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -6,7 +6,7 @@ use core::future::poll_fn; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -189,8 +189,8 @@ impl<'d, const N: usize> Saadc<'d, N> { // Disable all events interrupts r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); - unsafe { interrupt::SAADC::steal() }.unpend(); - unsafe { interrupt::SAADC::steal() }.enable(); + interrupt::SAADC::unpend(); + unsafe { interrupt::SAADC::enable() }; Self { _p: saadc } } diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 89cbdfee9..bb9cda323 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -15,7 +15,7 @@ pub use pac::spim0::frequency::FREQUENCY_A as Frequency; use crate::chip::FORCE_COPY_BUFFER_SIZE; use crate::gpio::sealed::Pin as _; use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; -use crate::interrupt::{self, Interrupt, InterruptExt}; +use crate::interrupt::{self, Interrupt}; use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; use crate::{pac, Peripheral}; @@ -207,8 +207,8 @@ impl<'d, T: Instance> Spim<'d, T> { // Disable all events interrupts r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; Self { _p: spim } } diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs index 55b5e060e..a1d6803ed 100644 --- a/embassy-nrf/src/spis.rs +++ b/embassy-nrf/src/spis.rs @@ -13,7 +13,7 @@ pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MO use crate::chip::FORCE_COPY_BUFFER_SIZE; use crate::gpio::sealed::Pin as _; use crate::gpio::{self, AnyPin, Pin as GpioPin}; -use crate::interrupt::{self, Interrupt, InterruptExt}; +use crate::interrupt::{self, Interrupt}; use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; use crate::{pac, Peripheral}; @@ -214,8 +214,8 @@ impl<'d, T: Instance> Spis<'d, T> { // Disable all events interrupts. r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; Self { _p: spis } } diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs index 0653710af..8a127efc5 100644 --- a/embassy-nrf/src/temp.rs +++ b/embassy-nrf/src/temp.rs @@ -3,13 +3,12 @@ use core::future::poll_fn; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use fixed::types::I30F2; -use crate::interrupt::InterruptExt; +use crate::interrupt::Interrupt; use crate::peripherals::TEMP; use crate::{interrupt, pac, Peripheral}; @@ -42,8 +41,8 @@ impl<'d> Temp<'d> { into_ref!(_peri); // Enable interrupt that signals temperature values - unsafe { interrupt::TEMP::steal() }.unpend(); - unsafe { interrupt::TEMP::steal() }.enable(); + interrupt::TEMP::unpend(); + unsafe { interrupt::TEMP::enable() }; Self { _peri } } diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs index c82c238cc..4feff8a75 100644 --- a/embassy-nrf/src/time_driver.rs +++ b/embassy-nrf/src/time_driver.rs @@ -7,7 +7,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; use embassy_time::driver::{AlarmHandle, Driver}; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::{interrupt, pac}; fn rtc() -> &'static pac::rtc0::RegisterBlock { @@ -142,9 +142,8 @@ impl RtcDriver { // Wait for clear while r.counter.read().bits() != 0 {} - let irq = unsafe { interrupt::RTC1::steal() }; - irq.set_priority(irq_prio); - irq.enable(); + interrupt::RTC1::set_priority(irq_prio); + unsafe { interrupt::RTC1::enable() }; } fn on_interrupt(&self) { diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs index cab36884f..dea398a67 100644 --- a/embassy-nrf/src/twim.rs +++ b/embassy-nrf/src/twim.rs @@ -16,7 +16,7 @@ use embassy_time::{Duration, Instant}; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::gpio::Pin as GpioPin; -use crate::interrupt::{self, Interrupt, InterruptExt}; +use crate::interrupt::{self, Interrupt}; use crate::util::{slice_in_ram, slice_in_ram_or}; use crate::{gpio, pac, Peripheral}; @@ -174,8 +174,8 @@ impl<'d, T: Instance> Twim<'d, T> { // Disable all events interrupts r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; Self { _p: twim } } diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs index f68a9940a..752a8c046 100644 --- a/embassy-nrf/src/twis.rs +++ b/embassy-nrf/src/twis.rs @@ -15,7 +15,7 @@ use embassy_time::{Duration, Instant}; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::gpio::Pin as GpioPin; -use crate::interrupt::{self, Interrupt, InterruptExt}; +use crate::interrupt::{self, Interrupt}; use crate::util::slice_in_ram_or; use crate::{gpio, pac, Peripheral}; @@ -204,8 +204,8 @@ impl<'d, T: Instance> Twis<'d, T> { // Generate suspend on read event r.shorts.write(|w| w.read_suspend().enabled()); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; Self { _p: twis } } diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 032089635..6c6941ee8 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -27,7 +27,7 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::gpio::sealed::Pin as _; use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; -use crate::interrupt::{self, Interrupt, InterruptExt}; +use crate::interrupt::{self, Interrupt}; use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; use crate::timer::{Frequency, Instance as TimerInstance, Timer}; use crate::util::slice_in_ram_or; @@ -168,8 +168,8 @@ impl<'d, T: Instance> Uarte<'d, T> { } r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; let hardware_flow_control = match (rts.is_some(), cts.is_some()) { (false, false) => false, @@ -358,8 +358,8 @@ impl<'d, T: Instance> UarteTx<'d, T> { let hardware_flow_control = cts.is_some(); configure(r, config, hardware_flow_control); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; let s = T::state(); s.tx_rx_refcount.store(1, Ordering::Relaxed); @@ -551,8 +551,8 @@ impl<'d, T: Instance> UarteRx<'d, T> { r.psel.txd.write(|w| w.connect().disconnected()); r.psel.cts.write(|w| w.connect().disconnected()); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; let hardware_flow_control = rts.is_some(); configure(r, config, hardware_flow_control); diff --git a/embassy-nrf/src/usb/mod.rs b/embassy-nrf/src/usb/mod.rs index c1f3f48cb..3c62b4452 100644 --- a/embassy-nrf/src/usb/mod.rs +++ b/embassy-nrf/src/usb/mod.rs @@ -18,7 +18,7 @@ use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo use pac::usbd::RegisterBlock; use self::vbus_detect::VbusDetect; -use crate::interrupt::{self, Interrupt, InterruptExt}; +use crate::interrupt::{self, Interrupt}; use crate::util::slice_in_ram; use crate::{pac, Peripheral}; @@ -103,8 +103,8 @@ impl<'d, T: Instance, V: VbusDetect> Driver<'d, T, V> { ) -> Self { into_ref!(usb); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; Self { _p: usb, diff --git a/embassy-nrf/src/usb/vbus_detect.rs b/embassy-nrf/src/usb/vbus_detect.rs index cecd4c595..a6a959905 100644 --- a/embassy-nrf/src/usb/vbus_detect.rs +++ b/embassy-nrf/src/usb/vbus_detect.rs @@ -7,7 +7,7 @@ use core::task::Poll; use embassy_sync::waitqueue::AtomicWaker; use super::BUS_WAKER; -use crate::interrupt::{self, Interrupt, InterruptExt}; +use crate::interrupt::{self, Interrupt}; use crate::pac; /// Trait for detecting USB VBUS power. @@ -80,8 +80,8 @@ impl HardwareVbusDetect { pub fn new(_irq: impl interrupt::Binding + 'static) -> Self { let regs = unsafe { &*UsbRegPeri::ptr() }; - unsafe { UsbRegIrq::steal() }.unpend(); - unsafe { UsbRegIrq::steal() }.enable(); + UsbRegIrq::unpend(); + unsafe { UsbRegIrq::enable() }; regs.intenset .write(|w| w.usbdetected().set().usbremoved().set().usbpwrrdy().set()); diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 59c7a47ce..86a353670 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -8,7 +8,7 @@ use embassy_sync::waitqueue::AtomicWaker; use embedded_hal_02::adc::{Channel, OneShot}; use crate::gpio::Pin; -use crate::interrupt::{self, InterruptExt, ADC_IRQ_FIFO}; +use crate::interrupt::{self, ADC_IRQ_FIFO}; use crate::peripherals::ADC; use crate::{pac, peripherals, Peripheral}; static WAKER: AtomicWaker = AtomicWaker::new(); @@ -63,8 +63,8 @@ impl<'d> Adc<'d> { // Setup IRQ unsafe { - ADC_IRQ_FIFO::steal().unpend(); - ADC_IRQ_FIFO::steal().enable(); + ADC_IRQ_FIFO::unpend(); + ADC_IRQ_FIFO::enable(); }; Self { phantom: PhantomData } diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index ba07a88df..74f4e6998 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -4,7 +4,7 @@ use core::pin::Pin; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use pac::dma::vals::DataSize; @@ -29,13 +29,12 @@ unsafe fn DMA_IRQ_0() { } pub(crate) unsafe fn init() { - let irq = interrupt::DMA_IRQ_0::steal(); - irq.disable(); - irq.set_priority(interrupt::Priority::P3); + interrupt::DMA_IRQ_0::disable(); + interrupt::DMA_IRQ_0::set_priority(interrupt::Priority::P3); pac::DMA.inte0().write(|w| w.set_inte0(0xFFFF)); - irq.enable(); + interrupt::DMA_IRQ_0::enable(); } pub unsafe fn read<'a, C: Channel, W: Word>( diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index da8efba91..f213bfeab 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -3,7 +3,7 @@ use core::future::Future; use core::pin::Pin as FuturePin; use core::task::{Context, Poll}; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -137,10 +137,9 @@ pub enum InterruptTrigger { } pub(crate) unsafe fn init() { - let irq = interrupt::IO_IRQ_BANK0::steal(); - irq.disable(); - irq.set_priority(interrupt::Priority::P3); - irq.enable(); + interrupt::IO_IRQ_BANK0::disable(); + interrupt::IO_IRQ_BANK0::set_priority(interrupt::Priority::P3); + interrupt::IO_IRQ_BANK0::enable(); } #[interrupt] diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 6ce77f073..124f1c00a 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -2,7 +2,7 @@ use core::future; use core::marker::PhantomData; use core::task::Poll; -use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::{self, Binding, Interrupt}; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use pac::i2c; @@ -82,14 +82,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let i2c = Self::new_inner(peri, scl.map_into(), sda.map_into(), config); - unsafe { - let i2c = T::regs(); + let r = T::regs(); - // mask everything initially - i2c.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)); - T::Interrupt::steal().unpend(); - T::Interrupt::steal().enable(); - } + // mask everything initially + unsafe { r.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)) } + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; i2c } diff --git a/embassy-rp/src/interrupt.rs b/embassy-rp/src/interrupt.rs index 1db13deef..c9298644d 100644 --- a/embassy-rp/src/interrupt.rs +++ b/embassy-rp/src/interrupt.rs @@ -1,7 +1,7 @@ //! Interrupt definitions and macros to bind them. pub use cortex_m::interrupt::{CriticalSection, Mutex}; use embassy_cortex_m::interrupt::_export::declare; -pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, InterruptExt, Priority}; +pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, Priority}; use crate::pac::Interrupt as InterruptEnum; declare!(TIMER_IRQ_0); diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index a13209f74..807fda57b 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -50,7 +50,7 @@ use core::mem::ManuallyDrop; use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::peripherals::CORE1; use crate::{gpio, interrupt, pac}; @@ -156,8 +156,7 @@ where IS_CORE1_INIT.store(true, Ordering::Release); // Enable fifo interrupt on CORE1 for `pause` functionality. - let irq = unsafe { interrupt::SIO_IRQ_PROC1::steal() }; - irq.enable(); + unsafe { interrupt::SIO_IRQ_PROC1::enable() }; entry() } diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index cbe45334a..93e5bd34b 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -5,7 +5,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; use atomic_polyfill::{AtomicU32, AtomicU8}; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use fixed::types::extra::U8; @@ -110,17 +110,15 @@ unsafe fn PIO1_IRQ_0() { } pub(crate) unsafe fn init() { - let irq = interrupt::PIO0_IRQ_0::steal(); - irq.disable(); - irq.set_priority(interrupt::Priority::P3); + interrupt::PIO0_IRQ_0::disable(); + interrupt::PIO0_IRQ_0::set_priority(interrupt::Priority::P3); pac::PIO0.irqs(0).inte().write(|m| m.0 = 0); - irq.enable(); + interrupt::PIO0_IRQ_0::enable(); - let irq = interrupt::PIO1_IRQ_0::steal(); - irq.disable(); - irq.set_priority(interrupt::Priority::P3); + interrupt::PIO1_IRQ_0::disable(); + interrupt::PIO1_IRQ_0::set_priority(interrupt::Priority::P3); pac::PIO1.irqs(0).inte().write(|m| m.0 = 0); - irq.enable(); + interrupt::PIO1_IRQ_0::enable(); } /// Future that waits for TX-FIFO to become writable diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs index 80efd779f..68793950f 100644 --- a/embassy-rp/src/timer.rs +++ b/embassy-rp/src/timer.rs @@ -6,7 +6,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; use embassy_time::driver::{AlarmHandle, Driver}; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::{interrupt, pac}; struct AlarmState { @@ -145,10 +145,10 @@ pub unsafe fn init() { w.set_alarm(2, true); w.set_alarm(3, true); }); - interrupt::TIMER_IRQ_0::steal().enable(); - interrupt::TIMER_IRQ_1::steal().enable(); - interrupt::TIMER_IRQ_2::steal().enable(); - interrupt::TIMER_IRQ_3::steal().enable(); + interrupt::TIMER_IRQ_0::enable(); + interrupt::TIMER_IRQ_1::enable(); + interrupt::TIMER_IRQ_2::enable(); + interrupt::TIMER_IRQ_3::enable(); } #[interrupt] diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index 12d6b8d91..bb808c467 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs @@ -3,7 +3,7 @@ use core::slice; use core::task::Poll; use atomic_polyfill::{AtomicU8, Ordering}; -use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::{self, Binding, Interrupt}; use embassy_hal_common::atomic_ring_buffer::RingBuffer; use embassy_sync::waitqueue::AtomicWaker; use embassy_time::{Duration, Timer}; @@ -80,8 +80,8 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>( w.set_txim(true); }); - T::Interrupt::steal().unpend(); - T::Interrupt::steal().enable(); + T::Interrupt::unpend(); + T::Interrupt::enable(); }; } @@ -362,7 +362,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> { // FIFO and the number of bytes drops below a threshold. When the // FIFO was empty we have to manually pend the interrupt to shovel // TX data from the buffer into the FIFO. - unsafe { T::Interrupt::steal() }.pend(); + T::Interrupt::pend(); Poll::Ready(Ok(n)) }) } @@ -398,7 +398,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> { // FIFO and the number of bytes drops below a threshold. When the // FIFO was empty we have to manually pend the interrupt to shovel // TX data from the buffer into the FIFO. - unsafe { T::Interrupt::steal() }.pend(); + T::Interrupt::pend(); return Ok(n); } } @@ -460,7 +460,7 @@ impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { // TX is inactive if the the buffer is not available. // We can now unregister the interrupt handler if state.tx_buf.len() == 0 { - T::Interrupt::steal().disable(); + T::Interrupt::disable(); } } } @@ -475,7 +475,7 @@ impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> { // RX is inactive if the the buffer is not available. // We can now unregister the interrupt handler if state.rx_buf.len() == 0 { - T::Interrupt::steal().disable(); + T::Interrupt::disable(); } } } diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 44e0ca0f6..a83d94e49 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use core::task::Poll; use atomic_polyfill::{AtomicU16, Ordering}; -use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::{self, Binding, Interrupt}; use embassy_futures::select::{select, Either}; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -245,12 +245,10 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { fn new_inner(has_irq: bool, rx_dma: Option>) -> Self { debug_assert_eq!(has_irq, rx_dma.is_some()); if has_irq { - unsafe { - // disable all error interrupts initially - T::regs().uartimsc().write(|w| w.0 = 0); - T::Interrupt::steal().unpend(); - T::Interrupt::steal().enable(); - } + // disable all error interrupts initially + unsafe { T::regs().uartimsc().write(|w| w.0 = 0) } + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; } Self { rx_dma, @@ -295,7 +293,7 @@ impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> { fn drop(&mut self) { if let Some(_) = self.rx_dma { unsafe { - T::Interrupt::steal().disable(); + T::Interrupt::disable(); // clear dma flags. irq handlers use these to disambiguate among themselves. T::regs().uartdmacr().write_clear(|reg| { reg.set_rxdmae(true); diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index fada2790f..cc88226df 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -11,7 +11,7 @@ use embassy_usb_driver::{ Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, }; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::{pac, peripherals, Peripheral, RegExt}; pub(crate) mod sealed { @@ -106,10 +106,8 @@ pub struct Driver<'d, T: Instance> { impl<'d, T: Instance> Driver<'d, T> { pub fn new(_usb: impl Peripheral

+ 'd, _irq: impl Binding>) -> Self { - unsafe { - T::Interrupt::steal().unpend(); - T::Interrupt::steal().enable(); - } + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; let regs = T::regs(); unsafe { diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 5f3fc6a93..c13915a1b 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -8,7 +8,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::dma::Transfer; use crate::gpio::sealed::AFType; use crate::gpio::Speed; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -346,8 +346,8 @@ where }); } - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; Self { inner: peri, dma } } diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 9dafa26d0..7a1ecda35 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -14,7 +14,7 @@ use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError}; use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::BDMA_CHANNEL_COUNT; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::pac; use crate::pac::bdma::{regs, vals}; @@ -70,9 +70,8 @@ static STATE: State = State::new(); pub(crate) unsafe fn init(irq_priority: Priority) { foreach_interrupt! { ($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => { - let irq = crate::interrupt::$irq::steal(); - irq.set_priority(irq_priority); - irq.enable(); + crate::interrupt::$irq::set_priority(irq_priority); + crate::interrupt::$irq::enable(); }; } crate::_generated::init_bdma(); diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 47b749ece..3b602b991 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -13,7 +13,7 @@ use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError}; use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::DMA_CHANNEL_COUNT; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::pac::dma::{regs, vals}; use crate::{interrupt, pac}; @@ -149,9 +149,8 @@ static STATE: State = State::new(); pub(crate) unsafe fn init(irq_priority: Priority) { foreach_interrupt! { ($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => { - let irq = interrupt::$irq::steal(); - irq.set_priority(irq_priority); - irq.enable(); + interrupt::$irq::set_priority(irq_priority); + interrupt::$irq::enable(); }; } crate::_generated::init_dma(); diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index 5a516ccda..7f8b82b46 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -12,7 +12,7 @@ use embassy_sync::waitqueue::AtomicWaker; use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::GPDMA_CHANNEL_COUNT; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::pac; use crate::pac::gpdma::vals; @@ -56,9 +56,8 @@ static STATE: State = State::new(); pub(crate) unsafe fn init(irq_priority: Priority) { foreach_interrupt! { ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { - let irq = crate::interrupt::$irq::steal(); - irq.set_priority(irq_priority); - irq.enable(); + crate::interrupt::$irq::set_priority(irq_priority); + crate::interrupt::$irq::enable(); }; } crate::_generated::init_gpdma(); diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 8ef2c3584..a5f1a268d 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -5,7 +5,7 @@ mod tx_desc; use core::sync::atomic::{fence, Ordering}; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, PeripheralRef}; use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf}; @@ -267,8 +267,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { P::phy_reset(&mut this); P::phy_init(&mut this); - interrupt::ETH::steal().unpend(); - interrupt::ETH::steal().enable(); + interrupt::ETH::unpend(); + interrupt::ETH::enable(); this } diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index b56c3e8ab..9efa436ac 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -2,7 +2,7 @@ mod descriptors; use core::sync::atomic::{fence, Ordering}; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, PeripheralRef}; pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; @@ -238,8 +238,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { P::phy_reset(&mut this); P::phy_init(&mut this); - interrupt::ETH::steal().unpend(); - interrupt::ETH::steal().enable(); + interrupt::ETH::unpend(); + interrupt::ETH::enable(); this } diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 10109e56a..c2fa31b20 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -354,13 +354,13 @@ impl_exti!(EXTI15, 15); macro_rules! enable_irq { ($e:ident) => { - crate::interrupt::$e::steal().enable(); + crate::interrupt::$e::enable(); }; } /// safety: must be called only once pub(crate) unsafe fn init() { - use crate::interrupt::{Interrupt, InterruptExt}; + use crate::interrupt::Interrupt; foreach_exti_irq!(enable_irq); diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 3c3ece99a..872614d4e 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; use atomic_polyfill::{fence, Ordering}; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::into_ref; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; @@ -23,9 +23,8 @@ impl<'d> Flash<'d, Async> { ) -> Self { into_ref!(p); - let flash_irq = unsafe { crate::interrupt::FLASH::steal() }; - flash_irq.unpend(); - flash_irq.enable(); + crate::interrupt::FLASH::unpend(); + unsafe { crate::interrupt::FLASH::enable() }; Self { inner: p, diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 642ddc18c..10f57f700 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -3,7 +3,7 @@ use core::future::poll_fn; use core::marker::PhantomData; use core::task::Poll; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_embedded_hal::SetConfig; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -133,8 +133,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { }); } - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; Self { _peri: peri, diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 6533509eb..75d8af3dd 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -75,7 +75,7 @@ pub(crate) mod _generated { pub mod interrupt { //! Interrupt definitions and macros to bind them. pub use cortex_m::interrupt::{CriticalSection, Mutex}; - pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, InterruptExt, Priority}; + pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, Priority}; pub use crate::_generated::interrupt::*; diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index be03a1bac..3cc17aa68 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -14,7 +14,7 @@ use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, use crate::dma::NoDma; use crate::gpio::sealed::{AFType, Pin}; use crate::gpio::{AnyPin, Pull, Speed}; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::pac::sdmmc::Sdmmc as RegBlock; use crate::rcc::RccPeripheral; use crate::time::Hertz; @@ -447,8 +447,8 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { T::enable(); T::reset(); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; let regs = T::regs(); unsafe { @@ -1288,7 +1288,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { impl<'d, T: Instance, Dma: SdmmcDma + 'd> Drop for Sdmmc<'d, T, Dma> { fn drop(&mut self) { - unsafe { T::Interrupt::steal() }.disable(); + T::Interrupt::disable(); unsafe { Self::on_drop() }; critical_section::with(|_| unsafe { diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 2236fde28..bab700993 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -11,7 +11,7 @@ use embassy_time::driver::{AlarmHandle, Driver}; use embassy_time::TICK_HZ; use stm32_metapac::timer::regs; -use crate::interrupt::InterruptExt; +use crate::interrupt::Interrupt; use crate::pac::timer::vals; use crate::rcc::sealed::RccPeripheral; use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance}; @@ -177,9 +177,8 @@ impl RtcDriver { w.set_ccie(0, true); }); - let irq: ::Interrupt = core::mem::transmute(()); - irq.unpend(); - irq.enable(); + ::Interrupt::unpend(); + ::Interrupt::enable(); r.cr1().modify(|w| w.set_cen(true)); }) diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs index 616f7dc56..efbbf2d1d 100644 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ b/embassy-stm32/src/tl_mbox/mod.rs @@ -2,7 +2,7 @@ use core::mem::MaybeUninit; use atomic_polyfill::{compiler_fence, Ordering}; use bit_field::BitField; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; @@ -379,11 +379,11 @@ impl<'d> TlMbox<'d> { MemoryManager::enable(); // enable interrupts - unsafe { crate::interrupt::IPCC_C1_RX::steal() }.unpend(); - unsafe { crate::interrupt::IPCC_C1_TX::steal() }.unpend(); + crate::interrupt::IPCC_C1_RX::unpend(); + crate::interrupt::IPCC_C1_TX::unpend(); - unsafe { crate::interrupt::IPCC_C1_RX::steal() }.enable(); - unsafe { crate::interrupt::IPCC_C1_TX::steal() }.enable(); + unsafe { crate::interrupt::IPCC_C1_RX::enable() }; + unsafe { crate::interrupt::IPCC_C1_TX::enable() }; Self { _ipcc: ipcc } } diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 9f1da3583..252e945da 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -216,8 +216,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { }); } - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; Self { rx: BufferedUartRx { phantom: PhantomData }, @@ -245,7 +245,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { rx_reader.pop_done(len); if do_pend { - unsafe { T::Interrupt::steal().pend() }; + T::Interrupt::pend(); } return Poll::Ready(Ok(len)); @@ -271,7 +271,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { rx_reader.pop_done(len); if do_pend { - unsafe { T::Interrupt::steal().pend() }; + T::Interrupt::pend(); } return Ok(len); @@ -301,7 +301,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { let full = state.rx_buf.is_full(); rx_reader.pop_done(amt); if full { - unsafe { T::Interrupt::steal().pend() }; + T::Interrupt::pend(); } } } @@ -324,7 +324,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { tx_writer.push_done(n); if empty { - unsafe { T::Interrupt::steal() }.pend(); + T::Interrupt::pend(); } Poll::Ready(Ok(n)) @@ -358,7 +358,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { tx_writer.push_done(n); if empty { - unsafe { T::Interrupt::steal() }.pend(); + T::Interrupt::pend(); } return Ok(n); @@ -385,7 +385,7 @@ impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> { // TX is inactive if the the buffer is not available. // We can now unregister the interrupt handler if state.tx_buf.len() == 0 { - T::Interrupt::steal().disable(); + T::Interrupt::disable(); } } } @@ -400,7 +400,7 @@ impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> { // RX is inactive if the the buffer is not available. // We can now unregister the interrupt handler if state.rx_buf.len() == 0 { - T::Interrupt::steal().disable(); + T::Interrupt::disable(); } } } diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 05ccb8749..ef1080153 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -5,7 +5,7 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use futures::future::{select, Either}; @@ -331,8 +331,8 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { configure(r, &config, T::frequency(), T::KIND, true, false); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; // create state once! let _s = T::state(); @@ -732,8 +732,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { configure(r, &config, T::frequency(), T::KIND, true, true); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; // create state once! let _s = T::state(); diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index a9ff284ae..134107978 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -14,7 +14,7 @@ use embassy_usb_driver::{ use super::{DmPin, DpPin, Instance}; use crate::gpio::sealed::AFType; -use crate::interrupt::{Interrupt, InterruptExt}; +use crate::interrupt::Interrupt; use crate::pac::usb::regs; use crate::pac::usb::vals::{EpType, Stat}; use crate::pac::USBRAM; @@ -260,8 +260,8 @@ impl<'d, T: Instance> Driver<'d, T> { dm: impl Peripheral

> + 'd, ) -> Self { into_ref!(dp, dm); - unsafe { T::Interrupt::steal() }.unpend(); - unsafe { T::Interrupt::steal() }.enable(); + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; let regs = T::regs(); diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index 921a73c8b..c7f19f6e9 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; use core::task::Poll; use atomic_polyfill::{AtomicBool, AtomicU16, Ordering}; -use embassy_cortex_m::interrupt::InterruptExt; +use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, Peripheral}; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver::{ @@ -629,7 +629,7 @@ impl<'d, T: Instance> Bus<'d, T> { } fn disable(&mut self) { - unsafe { T::Interrupt::steal() }.disable(); + T::Interrupt::disable(); ::disable(); @@ -902,8 +902,8 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { ::enable(); ::reset(); - T::Interrupt::steal().unpend(); - T::Interrupt::steal().enable(); + T::Interrupt::unpend(); + T::Interrupt::enable(); let r = T::regs(); let core_id = r.cid().read().0; diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index 8d60f18be..c1dc99eec 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml @@ -30,3 +30,4 @@ debug = ["defmt-rtt", "defmt"] [profile.release] debug = true +opt-level = 's' diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index d24e218dc..01695baea 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs @@ -108,7 +108,7 @@ async fn main_task(spawner: Spawner) { info!("Closing the connection"); socket.abort(); info!("Flushing the RST out..."); - socket.flush().await; + _ = socket.flush().await; info!("Finished with the socket"); } } From fa7510968acb930324986309f197273177b3071c Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 2 Jun 2023 03:44:49 +0200 Subject: [PATCH 08/98] rp/spi: start rx dma first. --- embassy-rp/src/spi.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 742a35d49..2cd2aa753 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -360,18 +360,22 @@ impl<'d, T: Instance> Spi<'d, T, Async> { reg.set_txdmae(true); }) }; - let tx_ch = self.tx_dma.as_mut().unwrap(); - let tx_transfer = unsafe { - // If we don't assign future to a variable, the data register pointer - // is held across an await and makes the future non-Send. - crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ) - }; + + // Start RX first. Transfer starts when TX starts, if RX + // is not started yet we might lose bytes. let rx_ch = self.rx_dma.as_mut().unwrap(); let rx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) }; + + let tx_ch = self.tx_dma.as_mut().unwrap(); + let tx_transfer = unsafe { + // If we don't assign future to a variable, the data register pointer + // is held across an await and makes the future non-Send. + crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ) + }; join(tx_transfer, rx_transfer).await; Ok(()) } @@ -395,6 +399,15 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }) }; + // Start RX first. Transfer starts when TX starts, if RX + // is not started yet we might lose bytes. + let rx_ch = self.rx_dma.as_mut().unwrap(); + let rx_transfer = unsafe { + // If we don't assign future to a variable, the data register pointer + // is held across an await and makes the future non-Send. + crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) + }; + let mut tx_ch = self.tx_dma.as_mut().unwrap(); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. @@ -411,13 +424,6 @@ impl<'d, T: Instance> Spi<'d, T, Async> { } } }; - - let rx_ch = self.rx_dma.as_mut().unwrap(); - let rx_transfer = unsafe { - // If we don't assign future to a variable, the data register pointer - // is held across an await and makes the future non-Send. - crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) - }; join(tx_transfer, rx_transfer).await; // if tx > rx we should clear any overflow of the FIFO SPI buffer From dd5ce985bda5f36fdd934fe27de55c46a9972a1a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 2 Jun 2023 04:04:38 +0200 Subject: [PATCH 09/98] rp/spi: enable rxdmae/txdmae only once at init. see https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_spi/spi.c#L27-L28 --- embassy-rp/src/spi.rs | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 2cd2aa753..7da214743 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -90,10 +90,16 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { w.set_sph(config.phase == Phase::CaptureOnSecondTransition); w.set_scr(postdiv); }); - p.cr1().write(|w| { - w.set_sse(true); // enable + + // Always enable DREQ signals -- harmless if DMA is not listening + p.dmacr().write(|reg| { + reg.set_rxdmae(true); + reg.set_txdmae(true); }); + // finally, enable. + p.cr1().write(|w| w.set_sse(true)); + if let Some(pin) = &clk { pin.io().ctrl().write(|w| w.set_funcsel(1)); } @@ -329,9 +335,6 @@ impl<'d, T: Instance> Spi<'d, T, Async> { pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { let tx_ch = self.tx_dma.as_mut().unwrap(); let tx_transfer = unsafe { - self.inner.regs().dmacr().modify(|reg| { - reg.set_txdmae(true); - }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. crate::dma::write(tx_ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) @@ -354,13 +357,6 @@ impl<'d, T: Instance> Spi<'d, T, Async> { } pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - unsafe { - self.inner.regs().dmacr().write(|reg| { - reg.set_rxdmae(true); - reg.set_txdmae(true); - }) - }; - // Start RX first. Transfer starts when TX starts, if RX // is not started yet we might lose bytes. let rx_ch = self.rx_dma.as_mut().unwrap(); @@ -392,13 +388,6 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let (_, tx_len) = crate::dma::slice_ptr_parts(tx_ptr); let (_, rx_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); - unsafe { - self.inner.regs().dmacr().write(|reg| { - reg.set_rxdmae(true); - reg.set_txdmae(true); - }) - }; - // Start RX first. Transfer starts when TX starts, if RX // is not started yet we might lose bytes. let rx_ch = self.rx_dma.as_mut().unwrap(); From 3539dd7d4cad23b1bdf7edbf7811fa2cd1755e72 Mon Sep 17 00:00:00 2001 From: gak Date: Sat, 3 Jun 2023 06:59:31 +1000 Subject: [PATCH 10/98] Fix #1528 HS USB on STM32F7 --- embassy-stm32/src/usb_otg/usb.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index c7f19f6e9..e602bcb70 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs @@ -828,6 +828,30 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); } + #[cfg(stm32f7)] + { + // Enable ULPI clock if external PHY is used + let ulpien = !self.phy_type.internal(); + critical_section::with(|_| { + crate::pac::RCC.ahb1enr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hsulpien(ulpien); + } else { + w.set_usb_otg_hsen(ulpien); + } + }); + + // Low power mode + crate::pac::RCC.ahb1lpenr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hsulpilpen(ulpien); + } else { + w.set_usb_otg_hslpen(ulpien); + } + }); + }); + } + #[cfg(stm32h7)] { // If true, VDD33USB is generated by internal regulator from VDD50USB From 2f269f32560ab178f62d08730909745f49b8eaef Mon Sep 17 00:00:00 2001 From: Carl St-Laurent Date: Sat, 3 Jun 2023 22:05:24 -0400 Subject: [PATCH 11/98] stm32/rcc: Implement basic PLL support for STM32G4 series --- embassy-stm32/src/rcc/g4.rs | 163 +++++++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 7e748c7b5..13dced73d 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -1,4 +1,4 @@ -use stm32_metapac::rcc::vals::{Hpre, Ppre, Sw}; +use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; use crate::pac::{PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; @@ -15,6 +15,7 @@ pub const LSI_FREQ: Hertz = Hertz(32_000); pub enum ClockSrc { HSE(Hertz), HSI16, + PLL(PllSrc, PllM, PllN, PllClkDiv), } /// AHB prescaler @@ -41,6 +42,128 @@ pub enum APBPrescaler { Div16, } +/// PLL clock input source +#[derive(Clone, Copy, Debug)] +pub enum PllSrc { + HSI16, + HSE(Hertz), +} + +impl Into for PllSrc { + fn into(self) -> Pllsrc { + match self { + PllSrc::HSE(..) => Pllsrc::HSE, + PllSrc::HSI16 => Pllsrc::HSI16, + } + } +} + +#[derive(Clone, Copy)] +pub enum PllClkDiv { + Div2, + Div4, + Div6, + Div8, +} + +impl PllClkDiv { + pub fn to_div(self) -> u32 { + let val: u8 = self.into(); + (val as u32 + 1) * 2 + } +} + +impl From for u8 { + fn from(val: PllClkDiv) -> u8 { + match val { + PllClkDiv::Div2 => 0b00, + PllClkDiv::Div4 => 0b01, + PllClkDiv::Div6 => 0b10, + PllClkDiv::Div8 => 0b11, + } + } +} + +seq_macro::seq!(N in 8..=127 { + #[derive(Clone, Copy)] + pub enum PllN { + #( + Mul~N, + )* + } + + impl From for u8 { + fn from(val: PllN) -> u8 { + match val { + #( + PllN::Mul~N => N, + )* + } + } + } + + impl PllN { + pub fn to_mul(self) -> u32 { + match self { + #( + PllN::Mul~N => N, + )* + } + } + } +}); + +// Pre-division +#[derive(Copy, Clone)] +pub enum PllM { + Div1, + Div2, + Div3, + Div4, + Div5, + Div6, + Div7, + Div8, + Div9, + Div10, + Div11, + Div12, + Div13, + Div14, + Div15, + Div16, +} + +impl PllM { + pub fn to_div(self) -> u32 { + let val: u8 = self.into(); + val as u32 + 1 + } +} + +impl From for u8 { + fn from(val: PllM) -> u8 { + match val { + PllM::Div1 => 0b0000, + PllM::Div2 => 0b0001, + PllM::Div3 => 0b0010, + PllM::Div4 => 0b0011, + PllM::Div5 => 0b0100, + PllM::Div6 => 0b0101, + PllM::Div7 => 0b0110, + PllM::Div8 => 0b0111, + PllM::Div9 => 0b1000, + PllM::Div10 => 0b1001, + PllM::Div11 => 0b1010, + PllM::Div12 => 0b1011, + PllM::Div13 => 0b1100, + PllM::Div14 => 0b1101, + PllM::Div15 => 0b1110, + PllM::Div16 => 0b1111, + } + } +} + impl AHBPrescaler { const fn div(self) -> u32 { match self { @@ -135,6 +258,44 @@ pub(crate) unsafe fn init(config: Config) { (freq.0, Sw::HSE) } + ClockSrc::PLL(src, prediv, mul, div) => { + let src_freq = match src { + PllSrc::HSI16 => { + // Enable HSI16 + RCC.cr().write(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + + HSI_FREQ.0 + } + PllSrc::HSE(freq) => { + // Enable HSE + RCC.cr().write(|w| w.set_hseon(true)); + while !RCC.cr().read().hserdy() {} + + freq.0 + } + }; + + // Disable PLL + RCC.cr().modify(|w| w.set_pllon(false)); + while RCC.cr().read().pllrdy() {} + + let freq = src_freq / prediv.to_div() * mul.to_mul() / div.to_div(); + assert!(freq <= 170_000_000); + + RCC.pllcfgr().write(move |w| { + w.set_plln(mul.into()); + w.set_pllm(prediv.into()); + w.set_pllr(div.into()); + w.set_pllsrc(src.into()); + }); + + RCC.cr().modify(|w| w.set_pllon(true)); + while !RCC.cr().read().pllrdy() {} + RCC.pllcfgr().modify(|w| w.set_pllren(true)); + + (freq, Sw::PLLRCLK) + } }; RCC.cfgr().modify(|w| { From 675499449fa3e348d27aebc5aae2b7f736648609 Mon Sep 17 00:00:00 2001 From: Carl St-Laurent Date: Sat, 3 Jun 2023 22:10:43 -0400 Subject: [PATCH 12/98] Example using PLL --- examples/stm32g4/src/bin/pll.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 examples/stm32g4/src/bin/pll.rs diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs new file mode 100644 index 000000000..5dcdf4e53 --- /dev/null +++ b/examples/stm32g4/src/bin/pll.rs @@ -0,0 +1,27 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::rcc::{ClockSrc, PllClkDiv, PllM, PllN, PllSrc}; +use embassy_stm32::time::mhz; +use embassy_stm32::Config; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + + // Configure PLL to max frequency of 170 MHz + config.rcc.mux = ClockSrc::PLL(PllSrc::HSE(mhz(16)), PllM::Div4, PllN::Mul85, PllClkDiv::Div2); + + let _p = embassy_stm32::init(config); + info!("Hello World!"); + + loop { + Timer::after(Duration::from_millis(1000)).await; + info!("1s elapsed"); + } +} From 24c4ea71b11ce6c07d92dd6876fec6a9b0f6ed10 Mon Sep 17 00:00:00 2001 From: ZhangYong Date: Sat, 3 Jun 2023 17:44:25 +0800 Subject: [PATCH 13/98] sync/pipe: write all user data to pipe sync/pipe: add write_all function --- embassy-sync/src/pipe.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/embassy-sync/src/pipe.rs b/embassy-sync/src/pipe.rs index ee27cdec8..db6ebb08b 100644 --- a/embassy-sync/src/pipe.rs +++ b/embassy-sync/src/pipe.rs @@ -294,6 +294,16 @@ where WriteFuture { pipe: self, buf } } + /// Write all bytes to the pipe. + /// + /// This method writes all bytes from `buf` into the pipe + pub async fn write_all(&self, mut buf: &[u8]) { + while !buf.is_empty() { + let n = self.write(buf).await; + buf = &buf[n..]; + } + } + /// Attempt to immediately write some bytes to the pipe. /// /// This method will either write a nonzero amount of bytes to the pipe immediately, From 6fe853a7d353edcc8b0fba8773915c4269599179 Mon Sep 17 00:00:00 2001 From: Carl St-Laurent Date: Sun, 4 Jun 2023 10:58:44 -0400 Subject: [PATCH 14/98] Better comments --- embassy-stm32/src/rcc/g4.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 13dced73d..7d061192b 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -261,14 +261,14 @@ pub(crate) unsafe fn init(config: Config) { ClockSrc::PLL(src, prediv, mul, div) => { let src_freq = match src { PllSrc::HSI16 => { - // Enable HSI16 + // Enable HSI16 as clock source for PLL RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} HSI_FREQ.0 } PllSrc::HSE(freq) => { - // Enable HSE + // Enable HSE as clock source for PLL RCC.cr().write(|w| w.set_hseon(true)); while !RCC.cr().read().hserdy() {} @@ -276,7 +276,7 @@ pub(crate) unsafe fn init(config: Config) { } }; - // Disable PLL + // Make sure PLL is disabled while we configure it RCC.cr().modify(|w| w.set_pllon(false)); while RCC.cr().read().pllrdy() {} @@ -290,6 +290,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_pllsrc(src.into()); }); + // Enable PLL RCC.cr().modify(|w| w.set_pllon(true)); while !RCC.cr().read().pllrdy() {} RCC.pllcfgr().modify(|w| w.set_pllren(true)); From e83762e9790d79f0716af5b3f1fcfd730f6fab35 Mon Sep 17 00:00:00 2001 From: Carl St-Laurent Date: Sun, 4 Jun 2023 11:05:13 -0400 Subject: [PATCH 15/98] Use HSI16 for exemple since HSE might have a different value depending on board --- examples/stm32g4/src/bin/pll.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs index 5dcdf4e53..580afe03d 100644 --- a/examples/stm32g4/src/bin/pll.rs +++ b/examples/stm32g4/src/bin/pll.rs @@ -5,7 +5,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::rcc::{ClockSrc, PllClkDiv, PllM, PllN, PllSrc}; -use embassy_stm32::time::mhz; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -14,8 +13,8 @@ use {defmt_rtt as _, panic_probe as _}; async fn main(_spawner: Spawner) { let mut config = Config::default(); - // Configure PLL to max frequency of 170 MHz - config.rcc.mux = ClockSrc::PLL(PllSrc::HSE(mhz(16)), PllM::Div4, PllN::Mul85, PllClkDiv::Div2); + // Configure PLL to 128Mhz frequency + config.rcc.mux = ClockSrc::PLL(PllSrc::HSI16, PllM::Div4, PllN::Mul64, PllClkDiv::Div2); let _p = embassy_stm32::init(config); info!("Hello World!"); From ade46489f190df685b5a81e0ccc267efc05b2de6 Mon Sep 17 00:00:00 2001 From: Carl St-Laurent Date: Sun, 4 Jun 2023 11:57:42 -0400 Subject: [PATCH 16/98] Added Vcore boost mode and Flash wait state --- embassy-stm32/src/rcc/g4.rs | 35 +++++++++++++++++++++++++++++++++ examples/stm32g4/src/bin/pll.rs | 4 ++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 7d061192b..6b1206c6a 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -1,4 +1,6 @@ +use stm32_metapac::flash::vals::Latency; use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; +use stm32_metapac::FLASH; use crate::pac::{PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; @@ -283,6 +285,39 @@ pub(crate) unsafe fn init(config: Config) { let freq = src_freq / prediv.to_div() * mul.to_mul() / div.to_div(); assert!(freq <= 170_000_000); + if freq >= 150_000_000 { + // Enable Core Boost mode ([RM0440] p234) + PWR.cr5() + .modify(|w: &mut stm32_metapac::pwr::regs::Cr5| w.set_r1mode(false)); + // Set flash wait state in boost mode based on frequency ([RM0440] p191) + if freq <= 36_000_000 { + FLASH.acr().modify(|w| w.set_latency(Latency::WS0)); + } else if freq <= 68_000_000 { + FLASH.acr().modify(|w| w.set_latency(Latency::WS1)); + } else if freq <= 102_000_000 { + FLASH.acr().modify(|w| w.set_latency(Latency::WS2)); + } else if freq <= 136_000_000 { + FLASH.acr().modify(|w| w.set_latency(Latency::WS3)); + } else { + FLASH.acr().modify(|w| w.set_latency(Latency::WS4)); + } + } else { + PWR.cr5() + .modify(|w: &mut stm32_metapac::pwr::regs::Cr5| w.set_r1mode(true)); + // Set flash wait state in normal mode based on frequency ([RM0440] p191) + if freq <= 30_000_000 { + FLASH.acr().modify(|w| w.set_latency(Latency::WS0)); + } else if freq <= 60_000_000 { + FLASH.acr().modify(|w| w.set_latency(Latency::WS1)); + } else if freq <= 80_000_000 { + FLASH.acr().modify(|w| w.set_latency(Latency::WS2)); + } else if freq <= 120_000_000 { + FLASH.acr().modify(|w| w.set_latency(Latency::WS3)); + } else { + FLASH.acr().modify(|w| w.set_latency(Latency::WS4)); + } + } + RCC.pllcfgr().write(move |w| { w.set_plln(mul.into()); w.set_pllm(prediv.into()); diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs index 580afe03d..bde30c284 100644 --- a/examples/stm32g4/src/bin/pll.rs +++ b/examples/stm32g4/src/bin/pll.rs @@ -13,8 +13,8 @@ use {defmt_rtt as _, panic_probe as _}; async fn main(_spawner: Spawner) { let mut config = Config::default(); - // Configure PLL to 128Mhz frequency - config.rcc.mux = ClockSrc::PLL(PllSrc::HSI16, PllM::Div4, PllN::Mul64, PllClkDiv::Div2); + // Configure PLL to max frequency of 170 MHz + config.rcc.mux = ClockSrc::PLL(PllSrc::HSI16, PllM::Div4, PllN::Mul85, PllClkDiv::Div2); let _p = embassy_stm32::init(config); info!("Hello World!"); From 4185c10bf83b96f015ef8d861b37555fff241061 Mon Sep 17 00:00:00 2001 From: Carl St-Laurent Date: Sun, 4 Jun 2023 12:09:03 -0400 Subject: [PATCH 17/98] Cleanup --- embassy-stm32/src/rcc/g4.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 6b1206c6a..3ba9e7eb0 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -286,9 +286,8 @@ pub(crate) unsafe fn init(config: Config) { assert!(freq <= 170_000_000); if freq >= 150_000_000 { - // Enable Core Boost mode ([RM0440] p234) - PWR.cr5() - .modify(|w: &mut stm32_metapac::pwr::regs::Cr5| w.set_r1mode(false)); + // Enable Core Boost mode on freq >= 150Mhz ([RM0440] p234) + PWR.cr5().modify(|w| w.set_r1mode(false)); // Set flash wait state in boost mode based on frequency ([RM0440] p191) if freq <= 36_000_000 { FLASH.acr().modify(|w| w.set_latency(Latency::WS0)); @@ -302,8 +301,7 @@ pub(crate) unsafe fn init(config: Config) { FLASH.acr().modify(|w| w.set_latency(Latency::WS4)); } } else { - PWR.cr5() - .modify(|w: &mut stm32_metapac::pwr::regs::Cr5| w.set_r1mode(true)); + PWR.cr5().modify(|w| w.set_r1mode(true)); // Set flash wait state in normal mode based on frequency ([RM0440] p191) if freq <= 30_000_000 { FLASH.acr().modify(|w| w.set_latency(Latency::WS0)); From a4b8fc420a377bd231d413dbdb2543550e3726ef Mon Sep 17 00:00:00 2001 From: ExplodingWaffle Date: Mon, 5 Jun 2023 01:30:34 +0100 Subject: [PATCH 18/98] Replace Into for Level with From for bool --- embassy-rp/src/gpio.rs | 6 +++--- embassy-stm32/src/gpio.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index f213bfeab..91cef8609 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -31,9 +31,9 @@ impl From for Level { } } -impl Into for Level { - fn into(self) -> bool { - match self { +impl From for bool { + fn from(level: Level) -> bool { + match level { Level::Low => false, Level::High => true, } diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 4895684e0..7a066a4ca 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -341,9 +341,9 @@ impl From for Level { } } -impl Into for Level { - fn into(self) -> bool { - match self { +impl From for bool { + fn from(level: Level) -> bool { + match level { Level::Low => false, Level::High => true, } From 44624b2d7a15ccc94971fc8d2091800f67821c58 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Thu, 1 Jun 2023 17:10:18 +0200 Subject: [PATCH 19/98] Put proto-ipv4 behind a feature flag --- embassy-net/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 0a47c5d94..4ac572577 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -26,7 +26,8 @@ unstable-traits = [] udp = ["smoltcp/socket-udp"] tcp = ["smoltcp/socket-tcp"] dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"] -dhcpv4 = ["medium-ethernet", "smoltcp/socket-dhcpv4"] +dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"] +proto-ipv4 = ["smoltcp/proto-ipv4"] proto-ipv6 = ["smoltcp/proto-ipv6"] medium-ethernet = ["smoltcp/medium-ethernet"] medium-ip = ["smoltcp/medium-ip"] @@ -38,7 +39,6 @@ defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } smoltcp = { version = "0.9.0", default-features = false, features = [ - "proto-ipv4", "socket", "async", ]} From 5ee26a5dd1af3e172610b94b2657af709b319dad Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 5 Jun 2023 22:28:14 +0200 Subject: [PATCH 20/98] rp/dma: fix use-after-free read. --- embassy-rp/src/dma.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 74f4e6998..1cbb4651a 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -75,16 +75,17 @@ pub unsafe fn write<'a, C: Channel, W: Word>( ) } +static DUMMY: u32 = 0; + pub unsafe fn write_repeated<'a, C: Channel, W: Word>( ch: impl Peripheral

+ 'a, to: *mut W, len: usize, dreq: u8, ) -> Transfer<'a, C> { - let dummy: u32 = 0; copy_inner( ch, - &dummy as *const u32, + &DUMMY as *const u32, to as *mut u32, len, W::size(), From adf053a935d03711b48859e3243e86d3038fa7c4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 5 Jun 2023 22:54:25 +0200 Subject: [PATCH 21/98] rp/flash: unify FLASH_BASE const. --- embassy-rp/src/flash.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 0410429e0..838b987dc 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -9,7 +9,7 @@ use embedded_storage::nor_flash::{ use crate::pac; use crate::peripherals::FLASH; -pub const FLASH_BASE: usize = 0x10000000; +pub const FLASH_BASE: *const u32 = 0x10000000 as _; // **NOTE**: // @@ -63,8 +63,8 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { trace!( "Reading from 0x{:x} to 0x{:x}", - FLASH_BASE + offset as usize, - FLASH_BASE + offset as usize + bytes.len() + FLASH_BASE as u32 + offset, + FLASH_BASE as u32 + offset + bytes.len() as u32 ); check_read(self, offset, bytes.len())?; @@ -242,6 +242,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Flash<'d, T, FLASH_S mod ram_helpers { use core::marker::PhantomData; + use super::*; use crate::rom_data; #[repr(C)] @@ -321,7 +322,7 @@ mod ram_helpers { pub unsafe fn flash_range_erase(addr: u32, len: u32, use_boot2: bool) { let mut boot2 = [0u32; 256 / 4]; let ptrs = if use_boot2 { - rom_data::memcpy44(&mut boot2 as *mut _, super::FLASH_BASE as *const _, 256); + rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(true, false, &boot2) } else { flash_function_pointers(true, false) @@ -351,7 +352,7 @@ mod ram_helpers { pub unsafe fn flash_range_erase_and_program(addr: u32, data: &[u8], use_boot2: bool) { let mut boot2 = [0u32; 256 / 4]; let ptrs = if use_boot2 { - rom_data::memcpy44(&mut boot2 as *mut _, super::FLASH_BASE as *const _, 256); + rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(true, true, &boot2) } else { flash_function_pointers(true, true) @@ -386,7 +387,7 @@ mod ram_helpers { pub unsafe fn flash_range_program(addr: u32, data: &[u8], use_boot2: bool) { let mut boot2 = [0u32; 256 / 4]; let ptrs = if use_boot2 { - rom_data::memcpy44(&mut boot2 as *mut _, super::FLASH_BASE as *const _, 256); + rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(false, true, &boot2) } else { flash_function_pointers(false, true) @@ -511,7 +512,7 @@ mod ram_helpers { pub unsafe fn flash_unique_id(out: &mut [u8], use_boot2: bool) { let mut boot2 = [0u32; 256 / 4]; let ptrs = if use_boot2 { - rom_data::memcpy44(&mut boot2 as *mut _, 0x10000000 as *const _, 256); + rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(false, false, &boot2) } else { flash_function_pointers(false, false) @@ -539,7 +540,7 @@ mod ram_helpers { pub unsafe fn flash_jedec_id(use_boot2: bool) -> u32 { let mut boot2 = [0u32; 256 / 4]; let ptrs = if use_boot2 { - rom_data::memcpy44(&mut boot2 as *mut _, 0x10000000 as *const _, 256); + rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(false, false, &boot2) } else { flash_function_pointers(false, false) From 70e1b976d87c5bde4b07e7e0b0fcf1499e4d98ef Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 5 Jun 2023 23:40:34 +0200 Subject: [PATCH 22/98] rp/flash: fix missing clobbers, do not clobber frame pointer (r7). --- embassy-rp/src/flash.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 838b987dc..cd34e605e 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -587,7 +587,6 @@ mod ram_helpers { "ldr r4, [r5, #4]", "blx r4", // flash_exit_xip() - "mov r7, r10", // cmd "movs r4, #0x18", "lsls r4, r4, #24", // 0x18000000, SSI, RP2040 datasheet 4.10.13 @@ -604,8 +603,9 @@ mod ram_helpers { "str r1, [r4, #0]", // Write ctrlr1 with len-1 - "ldr r0, [r7, #8]", // dummy_len - "ldr r1, [r7, #16]", // data_len + "mov r3, r10", // cmd + "ldr r0, [r3, #8]", // dummy_len + "ldr r1, [r3, #16]", // data_len "add r0, r1", "subs r0, #1", "str r0, [r4, #0x04]", // CTRLR1 @@ -617,8 +617,8 @@ mod ram_helpers { // Write cmd/addr phase to DR "mov r2, r4", "adds r2, 0x60", // &DR - "ldr r0, [r7, #0]", // cmd_addr - "ldr r1, [r7, #4]", // cmd_addr_len + "ldr r0, [r3, #0]", // cmd_addr + "ldr r1, [r3, #4]", // cmd_addr_len "10:", "ldrb r3, [r0]", "strb r3, [r2]", // DR @@ -627,7 +627,8 @@ mod ram_helpers { "bne 10b", // Skip any dummy cycles - "ldr r1, [r7, #8]", // dummy_len + "mov r3, r10", // cmd + "ldr r1, [r3, #8]", // dummy_len "cmp r1, #0", "beq 9f", "4:", @@ -644,8 +645,9 @@ mod ram_helpers { // Read RX fifo "9:", - "ldr r0, [r7, #12]", // data - "ldr r1, [r7, #16]", // data_len + "mov r2, r10", // cmd + "ldr r0, [r2, #12]", // data + "ldr r1, [r2, #16]", // data_len "2:", "ldr r3, [r4, #0x28]", // SR @@ -679,13 +681,12 @@ mod ram_helpers { out("r2") _, out("r3") _, out("r4") _, + out("r5") _, // Registers r8-r10 are used to store values // from r0-r2 in registers not clobbered by // function calls. // The values can't be passed in using r8-r10 directly // due to https://github.com/rust-lang/rust/issues/99071 - out("r8") _, - out("r9") _, out("r10") _, clobber_abi("C"), ); From 162d48530436be9cfa6a0d4aba88d97f52a5ad4a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 5 Jun 2023 23:41:26 +0200 Subject: [PATCH 23/98] rp/flash: centralize `USE_BOOT2` in a single const. --- embassy-rp/src/flash.rs | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index cd34e605e..0372afb1e 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -10,6 +10,7 @@ use crate::pac; use crate::peripherals::FLASH; pub const FLASH_BASE: *const u32 = 0x10000000 as _; +pub const USE_BOOT2: bool = true; // **NOTE**: // @@ -89,7 +90,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { let len = to - from; - unsafe { self.in_ram(|| ram_helpers::flash_range_erase(from, len, true))? }; + unsafe { self.in_ram(|| ram_helpers::flash_range_erase(from, len))? }; Ok(()) } @@ -114,7 +115,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { let unaligned_offset = offset as usize - start; - unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf, true))? } + unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? } } let remaining_len = bytes.len() - start_padding; @@ -132,12 +133,12 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { if bytes.as_ptr() as usize >= 0x2000_0000 { let aligned_data = &bytes[start_padding..end_padding]; - unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, aligned_data, true))? } + unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, aligned_data))? } } else { for chunk in bytes[start_padding..end_padding].chunks_exact(PAGE_SIZE) { let mut ram_buf = [0xFF_u8; PAGE_SIZE]; ram_buf.copy_from_slice(chunk); - unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, &ram_buf, true))? } + unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, &ram_buf))? } aligned_offset += PAGE_SIZE; } } @@ -152,7 +153,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { let unaligned_offset = end_offset - (PAGE_SIZE - rem_offset); - unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf, true))? } + unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? } } Ok(()) @@ -190,7 +191,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { /// Read SPI flash unique ID pub fn unique_id(&mut self, uid: &mut [u8]) -> Result<(), Error> { - unsafe { self.in_ram(|| ram_helpers::flash_unique_id(uid, true))? }; + unsafe { self.in_ram(|| ram_helpers::flash_unique_id(uid))? }; Ok(()) } @@ -199,7 +200,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { let mut jedec = None; unsafe { self.in_ram(|| { - jedec.replace(ram_helpers::flash_jedec_id(true)); + jedec.replace(ram_helpers::flash_jedec_id()); })?; }; Ok(jedec.unwrap()) @@ -307,7 +308,7 @@ mod ram_helpers { /// /// `addr` and `len` must be multiples of 4096 /// - /// If `use_boot2` is `true`, a copy of the 2nd stage boot loader + /// If `USE_BOOT2` is `true`, a copy of the 2nd stage boot loader /// is used to re-initialize the XIP engine after flashing. /// /// # Safety @@ -319,9 +320,9 @@ mod ram_helpers { /// - DMA must not access flash memory /// /// `addr` and `len` parameters must be valid and are not checked. - pub unsafe fn flash_range_erase(addr: u32, len: u32, use_boot2: bool) { + pub unsafe fn flash_range_erase(addr: u32, len: u32) { let mut boot2 = [0u32; 256 / 4]; - let ptrs = if use_boot2 { + let ptrs = if USE_BOOT2 { rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(true, false, &boot2) } else { @@ -337,7 +338,7 @@ mod ram_helpers { /// /// `addr` and `data.len()` must be multiples of 4096 /// - /// If `use_boot2` is `true`, a copy of the 2nd stage boot loader + /// If `USE_BOOT2` is `true`, a copy of the 2nd stage boot loader /// is used to re-initialize the XIP engine after flashing. /// /// # Safety @@ -349,9 +350,9 @@ mod ram_helpers { /// - DMA must not access flash memory /// /// `addr` and `len` parameters must be valid and are not checked. - pub unsafe fn flash_range_erase_and_program(addr: u32, data: &[u8], use_boot2: bool) { + pub unsafe fn flash_range_erase_and_program(addr: u32, data: &[u8]) { let mut boot2 = [0u32; 256 / 4]; - let ptrs = if use_boot2 { + let ptrs = if USE_BOOT2 { rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(true, true, &boot2) } else { @@ -372,7 +373,7 @@ mod ram_helpers { /// /// `addr` and `data.len()` must be multiples of 256 /// - /// If `use_boot2` is `true`, a copy of the 2nd stage boot loader + /// If `USE_BOOT2` is `true`, a copy of the 2nd stage boot loader /// is used to re-initialize the XIP engine after flashing. /// /// # Safety @@ -384,9 +385,9 @@ mod ram_helpers { /// - DMA must not access flash memory /// /// `addr` and `len` parameters must be valid and are not checked. - pub unsafe fn flash_range_program(addr: u32, data: &[u8], use_boot2: bool) { + pub unsafe fn flash_range_program(addr: u32, data: &[u8]) { let mut boot2 = [0u32; 256 / 4]; - let ptrs = if use_boot2 { + let ptrs = if USE_BOOT2 { rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(false, true, &boot2) } else { @@ -509,9 +510,9 @@ mod ram_helpers { /// - DMA must not access flash memory /// /// Credit: taken from `rp2040-flash` (also licensed Apache+MIT) - pub unsafe fn flash_unique_id(out: &mut [u8], use_boot2: bool) { + pub unsafe fn flash_unique_id(out: &mut [u8]) { let mut boot2 = [0u32; 256 / 4]; - let ptrs = if use_boot2 { + let ptrs = if USE_BOOT2 { rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(false, false, &boot2) } else { @@ -537,9 +538,9 @@ mod ram_helpers { /// - DMA must not access flash memory /// /// Credit: taken from `rp2040-flash` (also licensed Apache+MIT) - pub unsafe fn flash_jedec_id(use_boot2: bool) -> u32 { + pub unsafe fn flash_jedec_id() -> u32 { let mut boot2 = [0u32; 256 / 4]; - let ptrs = if use_boot2 { + let ptrs = if USE_BOOT2 { rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); flash_function_pointers_with_boot2(false, false, &boot2) } else { From 4f03dff577f08bb9af1ea3fc118857973baa686e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 6 Jun 2023 00:06:32 +0200 Subject: [PATCH 24/98] rp: add run-from-ram feature. --- embassy-rp/Cargo.toml | 5 +++++ embassy-rp/src/flash.rs | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 5f08c7f33..ddada655b 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -41,6 +41,11 @@ boot2-ram-memcpy = [] boot2-w25q080 = [] boot2-w25x10cl = [] +# Indicate code is running from RAM. +# Set this if all code is in RAM, and the cores never access memory-mapped flash memory through XIP. +# This allows the flash driver to not force pausing execution on both cores when doing flash operations. +run-from-ram = [] + # Enable nightly-only features nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb-driver", "dep:embedded-io"] diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 0372afb1e..5d928abad 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -10,7 +10,10 @@ use crate::pac; use crate::peripherals::FLASH; pub const FLASH_BASE: *const u32 = 0x10000000 as _; -pub const USE_BOOT2: bool = true; + +// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead. +// TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance. +pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram"); // **NOTE**: // From 593fc78dd892338386a2a81400e0621372264053 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 6 Jun 2023 00:07:03 +0200 Subject: [PATCH 25/98] tests/rp: enable run-from-ram. Otherwise the flash test is flaky because it attempts to use boot2. --- tests/rp/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 1786baee3..6bcac373c 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -10,7 +10,7 @@ teleprobe-meta = "1" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] } -embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics"] } +embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3.0" From 6701606e4c7811082808271b67caa1cdc9387163 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 6 Jun 2023 02:28:00 +0200 Subject: [PATCH 26/98] cyw43: add perf HIL test. --- ci.sh | 2 +- tests/perf-server/Cargo.toml | 8 + tests/perf-server/deploy.sh | 11 ++ tests/perf-server/perf-server.service | 16 ++ tests/perf-server/src/main.rs | 90 +++++++++ tests/rp/Cargo.toml | 6 +- tests/rp/src/bin/cyw43-perf.rs | 267 ++++++++++++++++++++++++++ 7 files changed, 398 insertions(+), 2 deletions(-) create mode 100644 tests/perf-server/Cargo.toml create mode 100755 tests/perf-server/deploy.sh create mode 100644 tests/perf-server/perf-server.service create mode 100644 tests/perf-server/src/main.rs create mode 100644 tests/rp/src/bin/cyw43-perf.rs diff --git a/ci.sh b/ci.sh index 3d6e28796..08558a18f 100755 --- a/ci.sh +++ b/ci.sh @@ -3,7 +3,7 @@ set -euo pipefail export RUSTFLAGS=-Dwarnings -export DEFMT_LOG=trace +export DEFMT_LOG=trace,cyw43=info,cyw43_pio=info,smoltcp=info # needed by wifi examples export WIFI_NETWORK=x diff --git a/tests/perf-server/Cargo.toml b/tests/perf-server/Cargo.toml new file mode 100644 index 000000000..532039050 --- /dev/null +++ b/tests/perf-server/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "perf-server" +version = "0.1.0" +edition = "2021" + +[dependencies] +log = "0.4.17" +pretty_env_logger = "0.4.0" diff --git a/tests/perf-server/deploy.sh b/tests/perf-server/deploy.sh new file mode 100755 index 000000000..032e99c30 --- /dev/null +++ b/tests/perf-server/deploy.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -euxo pipefail + +HOST=root@192.168.1.3 + +cargo build --release +ssh $HOST -- systemctl stop perf-server +scp target/release/perf-server $HOST:/root +scp perf-server.service $HOST:/etc/systemd/system/ +ssh $HOST -- 'systemctl daemon-reload; systemctl restart perf-server' \ No newline at end of file diff --git a/tests/perf-server/perf-server.service b/tests/perf-server/perf-server.service new file mode 100644 index 000000000..c14c5d16f --- /dev/null +++ b/tests/perf-server/perf-server.service @@ -0,0 +1,16 @@ +[Unit] +Description=perf-server +After=network.target +StartLimitIntervalSec=0 + +[Service] +Type=simple +Restart=always +RestartSec=1 +User=root +ExecStart=/root/perf-server +Environment=RUST_BACKTRACE=1 +Environment=RUST_LOG=info + +[Install] +WantedBy=multi-user.target diff --git a/tests/perf-server/src/main.rs b/tests/perf-server/src/main.rs new file mode 100644 index 000000000..f6e7efc59 --- /dev/null +++ b/tests/perf-server/src/main.rs @@ -0,0 +1,90 @@ +use std::io::{Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::thread::spawn; +use std::time::Duration; + +use log::info; + +fn main() { + pretty_env_logger::init(); + spawn(|| rx_listen()); + spawn(|| rxtx_listen()); + tx_listen(); +} + +fn tx_listen() { + info!("tx: listening on 0.0.0.0:4321"); + let listener = TcpListener::bind("0.0.0.0:4321").unwrap(); + loop { + let (socket, addr) = listener.accept().unwrap(); + info!("tx: received connection from: {}", addr); + spawn(|| tx_conn(socket)); + } +} + +fn tx_conn(mut socket: TcpStream) { + socket.set_read_timeout(Some(Duration::from_secs(30))).unwrap(); + socket.set_write_timeout(Some(Duration::from_secs(30))).unwrap(); + + let buf = [0; 1024]; + loop { + if let Err(e) = socket.write_all(&buf) { + info!("tx: failed to write to socket; err = {:?}", e); + return; + } + } +} + +fn rx_listen() { + info!("rx: listening on 0.0.0.0:4322"); + let listener = TcpListener::bind("0.0.0.0:4322").unwrap(); + loop { + let (socket, addr) = listener.accept().unwrap(); + info!("rx: received connection from: {}", addr); + spawn(|| rx_conn(socket)); + } +} + +fn rx_conn(mut socket: TcpStream) { + socket.set_read_timeout(Some(Duration::from_secs(30))).unwrap(); + socket.set_write_timeout(Some(Duration::from_secs(30))).unwrap(); + + let mut buf = [0; 1024]; + loop { + if let Err(e) = socket.read_exact(&mut buf) { + info!("rx: failed to read from socket; err = {:?}", e); + return; + } + } +} + +fn rxtx_listen() { + info!("rxtx: listening on 0.0.0.0:4323"); + let listener = TcpListener::bind("0.0.0.0:4323").unwrap(); + loop { + let (socket, addr) = listener.accept().unwrap(); + info!("rxtx: received connection from: {}", addr); + spawn(|| rxtx_conn(socket)); + } +} + +fn rxtx_conn(mut socket: TcpStream) { + socket.set_read_timeout(Some(Duration::from_secs(30))).unwrap(); + socket.set_write_timeout(Some(Duration::from_secs(30))).unwrap(); + + let mut buf = [0; 1024]; + loop { + match socket.read(&mut buf) { + Ok(n) => { + if let Err(e) = socket.write_all(&buf[..n]) { + info!("rxtx: failed to write to socket; err = {:?}", e); + return; + } + } + Err(e) => { + info!("rxtx: failed to read from socket; err = {:?}", e); + return; + } + } + } +} diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 6bcac373c..fa97fdcc4 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -5,13 +5,16 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -teleprobe-meta = "1" +teleprobe-meta = "1.1" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] } embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } +cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } +cyw43-pio = { path = "../../cyw43-pio", features = ["defmt", "overclock"] } defmt = "0.3.0" defmt-rtt = "0.4" @@ -25,6 +28,7 @@ panic-probe = { version = "0.3.0", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } embedded-io = { version = "0.4.0", features = ["async"] } embedded-storage = { version = "0.3" } +static_cell = { version = "1.1", features = ["nightly"]} [profile.dev] debug = 2 diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs new file mode 100644 index 000000000..568f1b826 --- /dev/null +++ b/tests/rp/src/bin/cyw43-perf.rs @@ -0,0 +1,267 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#[path = "../common.rs"] +mod common; + +use cyw43_pio::PioSpi; +use defmt::{assert, panic, *}; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Config, Ipv4Address, Stack, StackResources}; +use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; +use embassy_rp::pio::Pio; +use embassy_rp::rom_data; +use embassy_time::{with_timeout, Duration, Timer}; +use static_cell::make_static; +use {defmt_rtt as _, panic_probe as _}; + +teleprobe_meta::timeout!(120); + +#[embassy_executor::task] +async fn wifi_task( + runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + info!("Hello World!"); + let p = embassy_rp::init(Default::default()); + + // needed for reading the firmware from flash via XIP. + unsafe { + rom_data::flash_exit_xip(); + rom_data::flash_enter_cmd_xip(); + } + + // cyw43 firmware needs to be flashed manually: + // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x101c0000 + // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x101f8000 + let fw = unsafe { core::slice::from_raw_parts(0x101c0000 as *const u8, 224190) }; + let clm = unsafe { core::slice::from_raw_parts(0x101f8000 as *const u8, 4752) }; + + let pwr = Output::new(p.PIN_23, Level::Low); + let cs = Output::new(p.PIN_25, Level::High); + let mut pio = Pio::new(p.PIO0); + let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); + + let state = make_static!(cyw43::State::new()); + let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; + unwrap!(spawner.spawn(wifi_task(runner))); + + control.init(clm).await; + control + .set_power_management(cyw43::PowerManagementMode::PowerSave) + .await; + + let config = Config::Dhcp(Default::default()); + //let config = embassy_net::Config::Static(embassy_net::Config { + // address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), + // dns_servers: Vec::new(), + // gateway: Some(Ipv4Address::new(192, 168, 69, 1)), + //}); + + // Generate random seed + let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. + + // Init network stack + let stack = &*make_static!(Stack::new( + net_device, + config, + make_static!(StackResources::<2>::new()), + seed + )); + + unwrap!(spawner.spawn(net_task(stack))); + + loop { + match control.join_wpa2(WIFI_NETWORK, WIFI_PASSWORD).await { + Ok(_) => break, + Err(err) => { + panic!("join failed with status={}", err.status); + } + } + } + + info!("Waiting for DHCP up..."); + while stack.config().is_none() { + Timer::after(Duration::from_millis(100)).await; + } + info!("IP addressing up!"); + + let down = test_download(stack).await; + let up = test_upload(stack).await; + let updown = test_upload_download(stack).await; + + assert!(down > TEST_EXPECTED_DOWNLOAD_KBPS); + assert!(up > TEST_EXPECTED_UPLOAD_KBPS); + assert!(updown > TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} + +// Test-only wifi network, no internet access! +const WIFI_NETWORK: &str = "EmbassyTest"; +const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; + +const TEST_DURATION: usize = 10; +const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 500; +const TEST_EXPECTED_UPLOAD_KBPS: usize = 500; +const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 400; +const RX_BUFFER_SIZE: usize = 4096; +const TX_BUFFER_SIZE: usize = 4096; +const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2); +const DOWNLOAD_PORT: u16 = 4321; +const UPLOAD_PORT: u16 = 4322; +const UPLOAD_DOWNLOAD_PORT: u16 = 4323; + +async fn test_download(stack: &'static Stack>) -> usize { + info!("Testing download..."); + + let mut rx_buffer = [0; RX_BUFFER_SIZE]; + let mut tx_buffer = [0; TX_BUFFER_SIZE]; + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + info!("connecting to {:?}:{}...", SERVER_ADDRESS, DOWNLOAD_PORT); + if let Err(e) = socket.connect((SERVER_ADDRESS, DOWNLOAD_PORT)).await { + error!("connect error: {:?}", e); + return 0; + } + info!("connected, testing..."); + + let mut rx_buf = [0; 4096]; + let mut total: usize = 0; + with_timeout(Duration::from_secs(TEST_DURATION as _), async { + loop { + match socket.read(&mut rx_buf).await { + Ok(0) => { + error!("read EOF"); + return 0; + } + Ok(n) => total += n, + Err(e) => { + error!("read error: {:?}", e); + return 0; + } + } + } + }) + .await + .ok(); + + let kbps = (total + 512) / 1024 / TEST_DURATION; + info!("download: {} kB/s", kbps); + kbps +} + +async fn test_upload(stack: &'static Stack>) -> usize { + info!("Testing upload..."); + + let mut rx_buffer = [0; RX_BUFFER_SIZE]; + let mut tx_buffer = [0; TX_BUFFER_SIZE]; + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + info!("connecting to {:?}:{}...", SERVER_ADDRESS, UPLOAD_PORT); + if let Err(e) = socket.connect((SERVER_ADDRESS, UPLOAD_PORT)).await { + error!("connect error: {:?}", e); + return 0; + } + info!("connected, testing..."); + + let buf = [0; 4096]; + let mut total: usize = 0; + with_timeout(Duration::from_secs(TEST_DURATION as _), async { + loop { + match socket.write(&buf).await { + Ok(0) => { + error!("write zero?!??!?!"); + return 0; + } + Ok(n) => total += n, + Err(e) => { + error!("write error: {:?}", e); + return 0; + } + } + } + }) + .await + .ok(); + + let kbps = (total + 512) / 1024 / TEST_DURATION; + info!("upload: {} kB/s", kbps); + kbps +} + +async fn test_upload_download(stack: &'static Stack>) -> usize { + info!("Testing upload+download..."); + + let mut rx_buffer = [0; RX_BUFFER_SIZE]; + let mut tx_buffer = [0; TX_BUFFER_SIZE]; + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + info!("connecting to {:?}:{}...", SERVER_ADDRESS, UPLOAD_DOWNLOAD_PORT); + if let Err(e) = socket.connect((SERVER_ADDRESS, UPLOAD_DOWNLOAD_PORT)).await { + error!("connect error: {:?}", e); + return 0; + } + info!("connected, testing..."); + + let (mut reader, mut writer) = socket.split(); + + let tx_buf = [0; 4096]; + let mut rx_buf = [0; 4096]; + let mut total: usize = 0; + let tx_fut = async { + loop { + match writer.write(&tx_buf).await { + Ok(0) => { + error!("write zero?!??!?!"); + return 0; + } + Ok(_) => {} + Err(e) => { + error!("write error: {:?}", e); + return 0; + } + } + } + }; + + let rx_fut = async { + loop { + match reader.read(&mut rx_buf).await { + Ok(0) => { + error!("read EOF"); + return 0; + } + Ok(n) => total += n, + Err(e) => { + error!("read error: {:?}", e); + return 0; + } + } + } + }; + + with_timeout(Duration::from_secs(TEST_DURATION as _), join(tx_fut, rx_fut)) + .await + .ok(); + + let kbps = (total + 512) / 1024 / TEST_DURATION; + info!("upload+download: {} kB/s", kbps); + kbps +} From 54bab33c7342510be538bc6d8545fe50146557cf Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Mon, 5 Jun 2023 14:57:17 +0200 Subject: [PATCH 27/98] Rename StaticConfig to StaticConfigV4 --- embassy-net/src/lib.rs | 12 ++++++------ examples/nrf52840/src/bin/usb_ethernet.rs | 2 +- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 2 +- examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 2 +- examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 2 +- examples/rp/src/bin/ethernet_w5500_udp.rs | 2 +- examples/rp/src/bin/usb_ethernet.rs | 2 +- examples/rp/src/bin/wifi_ap_tcp_server.rs | 2 +- examples/rp/src/bin/wifi_tcp_server.rs | 2 +- examples/std/src/bin/net.rs | 2 +- examples/std/src/bin/net_dns.rs | 2 +- examples/std/src/bin/net_udp.rs | 2 +- examples/std/src/bin/tcp_accept.rs | 2 +- examples/stm32f4/src/bin/usb_ethernet.rs | 2 +- examples/stm32f7/src/bin/eth.rs | 2 +- examples/stm32h5/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth_client.rs | 2 +- examples/stm32l5/src/bin/usb_ethernet.rs | 2 +- 19 files changed, 24 insertions(+), 24 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index bccbad521..ddb325c6c 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -68,7 +68,7 @@ impl StackResources { /// Static IP address configuration. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct StaticConfig { +pub struct StaticConfigV4 { /// IP address and subnet mask. pub address: Ipv4Cidr, /// Default gateway. @@ -114,7 +114,7 @@ impl Default for DhcpConfig { /// Network stack configuration. pub enum Config { /// Use a static IP address configuration. - Static(StaticConfig), + Static(StaticConfigV4), /// Use DHCP to obtain an IP address configuration. #[cfg(feature = "dhcpv4")] Dhcp(DhcpConfig), @@ -131,7 +131,7 @@ pub struct Stack { struct Inner { device: D, link_up: bool, - config: Option, + config: Option, #[cfg(feature = "dhcpv4")] dhcp_socket: Option, #[cfg(feature = "dns")] @@ -243,7 +243,7 @@ impl Stack { } /// Get the current IP configuration. - pub fn config(&self) -> Option { + pub fn config(&self) -> Option { self.with(|_s, i| i.config.clone()) } @@ -374,7 +374,7 @@ impl SocketStack { } impl Inner { - fn apply_config(&mut self, s: &mut SocketStack, config: StaticConfig) { + fn apply_config(&mut self, s: &mut SocketStack, config: StaticConfigV4) { #[cfg(feature = "medium-ethernet")] let medium = self.device.capabilities().medium; @@ -470,7 +470,7 @@ impl Inner { None => {} Some(dhcpv4::Event::Deconfigured) => self.unapply_config(s), Some(dhcpv4::Event::Configured(config)) => { - let config = StaticConfig { + let config = StaticConfigV4 { address: config.address, gateway: config.router, dns_servers: config.dns_servers, diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index 1065f5b5d..b4316f5a4 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs @@ -98,7 +98,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::StaticConfig { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 63e142e7d..7e9e20b28 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -120,7 +120,7 @@ async fn listen_task(stack: &'static Stack>, id: u8, port: u16) } } -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { if let Some(config) = stack.config() { return config.clone(); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index a532de00d..c0275be1b 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -108,7 +108,7 @@ async fn main(spawner: Spawner) { } } -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { if let Some(config) = stack.config() { return config.clone(); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 599f6b1e9..da73e41ff 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -116,7 +116,7 @@ async fn main(spawner: Spawner) { } } -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { if let Some(config) = stack.config() { return config.clone(); diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index ac5a65bb6..4c861cbd2 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -95,7 +95,7 @@ async fn main(spawner: Spawner) { } } -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { if let Some(config) = stack.config() { return config.clone(); diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 16fbf5e91..d33d9c72e 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -87,7 +87,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::StaticConfig { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index b27d3c9f8..970cf4b32 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { .await; // Use a link-local address for communication without DHCP server - let config = Config::Static(embassy_net::StaticConfig { + let config = Config::StaticV4(embassy_net::StaticConfigV4 { address: embassy_net::Ipv4Cidr::new(embassy_net::Ipv4Address::new(169, 254, 1, 1), 16), dns_servers: heapless::Vec::new(), gateway: None, diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 1a00bca96..9f95f8b03 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { .await; let config = Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::Config { + //let config = embassy_net::Config::StaticV4(embassy_net::Config { // address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(192, 168, 69, 1)), diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index b42bfc13b..14cf3f25b 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs @@ -42,7 +42,7 @@ async fn main_task(spawner: Spawner) { // Choose between dhcp or static ip let config = if opts.static_ip { - Config::Static(embassy_net::StaticConfig { + Config::StaticV4(embassy_net::StaticConfigV4 { address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), dns_servers: Vec::new(), gateway: Some(Ipv4Address::new(192, 168, 69, 1)), diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index 932ac5831..0a479a744 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs @@ -40,7 +40,7 @@ async fn main_task(spawner: Spawner) { // Choose between dhcp or static ip let config = if opts.static_ip { - Config::Static(embassy_net::StaticConfig { + Config::StaticV4(embassy_net::StaticConfigV4 { address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 1), 24), dns_servers: Vec::from_slice(&[Ipv4Address::new(8, 8, 4, 4).into(), Ipv4Address::new(8, 8, 8, 8).into()]) .unwrap(), diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index d89ec7643..0ede5d998 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs @@ -38,7 +38,7 @@ async fn main_task(spawner: Spawner) { // Choose between dhcp or static ip let config = if opts.static_ip { - Config::Static(embassy_net::StaticConfig { + Config::StaticV4(embassy_net::StaticConfigV4 { address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), dns_servers: Vec::new(), gateway: Some(Ipv4Address::new(192, 168, 69, 1)), diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index 01695baea..4379d0439 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs @@ -53,7 +53,7 @@ async fn main_task(spawner: Spawner) { // Choose between dhcp or static ip let config = if opts.static_ip { - Config::Static(embassy_net::StaticConfig { + Config::StaticV4(embassy_net::StaticConfigV4 { address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), dns_servers: Vec::new(), gateway: Some(Ipv4Address::new(192, 168, 69, 1)), diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index d229cc3ef..0856b4842 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs @@ -95,7 +95,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::StaticConfig { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index d8438241c..ebdf0d8a0 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) -> ! { ); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::StaticConfig { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 5d1eadf4b..811f74c88 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -82,7 +82,7 @@ async fn main(spawner: Spawner) -> ! { ); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::StaticConfig { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 3aa7b2271..5360a213a 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) -> ! { ); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::StaticConfig { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 575c716b6..42781cfdc 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -65,7 +65,7 @@ async fn main(spawner: Spawner) -> ! { ); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticConfig(embassy_net::Config { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 6163e0709..d96d2f350 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -92,7 +92,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::StaticConfig { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), From e871324bde25bd61241aed83416caf6e49376d5a Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Mon, 5 Jun 2023 16:00:53 +0200 Subject: [PATCH 28/98] net: StaticV4 config behind proto-ipv4 --- embassy-net/src/device.rs | 5 +- embassy-net/src/dns.rs | 1 + embassy-net/src/lib.rs | 46 ++++++++++++++----- embassy-net/src/tcp.rs | 3 ++ .../rp/src/bin/ethernet_w5500_multisocket.rs | 2 +- .../rp/src/bin/ethernet_w5500_tcp_client.rs | 2 +- .../rp/src/bin/ethernet_w5500_tcp_server.rs | 2 +- examples/rp/src/bin/ethernet_w5500_udp.rs | 2 +- 8 files changed, 47 insertions(+), 16 deletions(-) diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index 5daa00544..583cdc87f 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs @@ -59,7 +59,10 @@ where smolcaps.checksum.ipv4 = convert(caps.checksum.ipv4); smolcaps.checksum.tcp = convert(caps.checksum.tcp); smolcaps.checksum.udp = convert(caps.checksum.udp); - smolcaps.checksum.icmpv4 = convert(caps.checksum.icmpv4); + #[cfg(feature = "proto-ipv4")] + { + smolcaps.checksum.icmpv4 = convert(caps.checksum.icmpv4); + } #[cfg(feature = "proto-ipv6")] { smolcaps.checksum.icmpv6 = convert(caps.checksum.icmpv6); diff --git a/embassy-net/src/dns.rs b/embassy-net/src/dns.rs index 3fd235b2c..94f75f108 100644 --- a/embassy-net/src/dns.rs +++ b/embassy-net/src/dns.rs @@ -88,6 +88,7 @@ where let addrs = self.query(host, qtype).await?; if let Some(first) = addrs.get(0) { Ok(match first { + #[cfg(feature = "proto-ipv4")] IpAddress::Ipv4(addr) => IpAddr::V4(addr.0.into()), #[cfg(feature = "proto-ipv6")] IpAddress::Ipv6(addr) => IpAddr::V6(addr.0.into()), diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index ddb325c6c..2e713cd10 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -34,7 +34,9 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig}; pub use smoltcp::wire::IpListenEndpoint; #[cfg(feature = "medium-ethernet")] pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; -pub use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; +pub use smoltcp::wire::{IpAddress, IpCidr}; +#[cfg(feature = "proto-ipv4")] +pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; #[cfg(feature = "proto-ipv6")] pub use smoltcp::wire::{Ipv6Address, Ipv6Cidr}; @@ -67,6 +69,7 @@ impl StackResources { } /// Static IP address configuration. +#[cfg(feature = "proto-ipv4")] #[derive(Debug, Clone, PartialEq, Eq)] pub struct StaticConfigV4 { /// IP address and subnet mask. @@ -114,7 +117,8 @@ impl Default for DhcpConfig { /// Network stack configuration. pub enum Config { /// Use a static IP address configuration. - Static(StaticConfigV4), + #[cfg(feature = "proto-ipv4")] + StaticV4(StaticConfigV4), /// Use DHCP to obtain an IP address configuration. #[cfg(feature = "dhcpv4")] Dhcp(DhcpConfig), @@ -131,7 +135,8 @@ pub struct Stack { struct Inner { device: D, link_up: bool, - config: Option, + #[cfg(feature = "proto-ipv4")] + static_v4: Option, #[cfg(feature = "dhcpv4")] dhcp_socket: Option, #[cfg(feature = "dns")] @@ -187,7 +192,8 @@ impl Stack { let mut inner = Inner { device, link_up: false, - config: None, + #[cfg(feature = "proto-ipv4")] + static_v4: None, #[cfg(feature = "dhcpv4")] dhcp_socket: None, #[cfg(feature = "dns")] @@ -200,7 +206,8 @@ impl Stack { }; match config { - Config::Static(config) => { + #[cfg(feature = "proto-ipv4")] + Config::StaticV4(config) => { inner.apply_config(&mut socket, config); } #[cfg(feature = "dhcpv4")] @@ -239,12 +246,21 @@ impl Stack { /// Get whether the network stack has a valid IP configuration. /// This is true if the network stack has a static IP configuration or if DHCP has completed pub fn is_config_up(&self) -> bool { - self.with(|_s, i| i.config.is_some()) + #[cfg(feature = "proto-ipv4")] + { + return self.config_v4().is_some(); + } + + #[cfg(not(any(feature = "proto-ipv4")))] + { + false + } } /// Get the current IP configuration. - pub fn config(&self) -> Option { - self.with(|_s, i| i.config.clone()) + #[cfg(feature = "proto-ipv4")] + pub fn config_v4(&self) -> Option { + self.with(|_s, i| i.static_v4.clone()) } /// Run the network stack. @@ -264,6 +280,7 @@ impl Stack { pub async fn dns_query(&self, name: &str, qtype: dns::DnsQueryType) -> Result, dns::Error> { // For A and AAAA queries we try detect whether `name` is just an IP address match qtype { + #[cfg(feature = "proto-ipv4")] dns::DnsQueryType::A => { if let Ok(ip) = name.parse().map(IpAddress::Ipv4) { return Ok([ip].into_iter().collect()); @@ -374,6 +391,7 @@ impl SocketStack { } impl Inner { + #[cfg(feature = "proto-ipv4")] fn apply_config(&mut self, s: &mut SocketStack, config: StaticConfigV4) { #[cfg(feature = "medium-ethernet")] let medium = self.device.capabilities().medium; @@ -410,7 +428,7 @@ impl Inner { socket.update_servers(&servers[..]); } - self.config = Some(config) + self.static_v4 = Some(config) } #[cfg(feature = "dhcpv4")] @@ -430,9 +448,15 @@ impl Inner { s.iface.update_ip_addrs(|ip_addrs| ip_addrs.clear()); #[cfg(feature = "medium-ethernet")] if medium == Medium::Ethernet { - s.iface.routes_mut().remove_default_ipv4_route(); + #[cfg(feature = "proto-ipv4")] + { + s.iface.routes_mut().remove_default_ipv4_route(); + } + } + #[cfg(feature = "proto-ipv4")] + { + self.static_v4 = None } - self.config = None } fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index 7babb5293..52fee6883 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs @@ -472,7 +472,10 @@ pub mod client { Self: 'a, { let addr: crate::IpAddress = match remote.ip() { + #[cfg(feature = "proto-ipv4")] IpAddr::V4(addr) => crate::IpAddress::Ipv4(crate::Ipv4Address::from_bytes(&addr.octets())), + #[cfg(not(feature = "proto-ipv4"))] + IpAddr::V4(_) => panic!("ipv4 support not enabled"), #[cfg(feature = "proto-ipv6")] IpAddr::V6(addr) => crate::IpAddress::Ipv6(crate::Ipv6Address::from_bytes(&addr.octets())), #[cfg(not(feature = "proto-ipv6"))] diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 7e9e20b28..066ecf2bc 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -122,7 +122,7 @@ async fn listen_task(stack: &'static Stack>, id: u8, port: u16) async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { - if let Some(config) = stack.config() { + if let Some(config) = stack.config_v4() { return config.clone(); } yield_now().await; diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index c0275be1b..3e0f5d136 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -110,7 +110,7 @@ async fn main(spawner: Spawner) { async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { - if let Some(config) = stack.config() { + if let Some(config) = stack.config_v4() { return config.clone(); } yield_now().await; diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index da73e41ff..db178d49d 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -118,7 +118,7 @@ async fn main(spawner: Spawner) { async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { - if let Some(config) = stack.config() { + if let Some(config) = stack.config_v4() { return config.clone(); } yield_now().await; diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 4c861cbd2..21943c3c6 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -97,7 +97,7 @@ async fn main(spawner: Spawner) { async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { - if let Some(config) = stack.config() { + if let Some(config) = stack.config_v4() { return config.clone(); } yield_now().await; From d7f674e410a674f06a749859bde4081a99718f58 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Mon, 5 Jun 2023 16:12:24 +0200 Subject: [PATCH 29/98] net: Allow setting an IPv6 in the stack --- embassy-net/src/lib.rs | 72 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 2e713cd10..9f83cb4ea 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -80,6 +80,18 @@ pub struct StaticConfigV4 { pub dns_servers: Vec, } +/// Static IPv6 address configuration +#[cfg(feature = "proto-ipv6")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct StaticConfigV6 { + /// IP address and subnet mask. + pub address: Ipv6Cidr, + /// Default gateway. + pub gateway: Option, + /// DNS servers. + pub dns_servers: Vec, +} + /// DHCP configuration. #[cfg(feature = "dhcpv4")] #[derive(Debug, Clone, PartialEq, Eq)] @@ -116,9 +128,12 @@ impl Default for DhcpConfig { /// Network stack configuration. pub enum Config { - /// Use a static IP address configuration. + /// Use a static IPv4 address configuration. #[cfg(feature = "proto-ipv4")] StaticV4(StaticConfigV4), + /// Use a static IPv6 address configuration. + #[cfg(feature = "proto-ipv6")] + StaticV6(StaticConfigV6), /// Use DHCP to obtain an IP address configuration. #[cfg(feature = "dhcpv4")] Dhcp(DhcpConfig), @@ -137,6 +152,8 @@ struct Inner { link_up: bool, #[cfg(feature = "proto-ipv4")] static_v4: Option, + #[cfg(feature = "proto-ipv6")] + static_v6: Option, #[cfg(feature = "dhcpv4")] dhcp_socket: Option, #[cfg(feature = "dns")] @@ -194,6 +211,8 @@ impl Stack { link_up: false, #[cfg(feature = "proto-ipv4")] static_v4: None, + #[cfg(feature = "proto-ipv6")] + static_v6: None, #[cfg(feature = "dhcpv4")] dhcp_socket: None, #[cfg(feature = "dns")] @@ -208,7 +227,11 @@ impl Stack { match config { #[cfg(feature = "proto-ipv4")] Config::StaticV4(config) => { - inner.apply_config(&mut socket, config); + inner.apply_config_v4(&mut socket, config); + } + #[cfg(feature = "proto-ipv6")] + Config::StaticV6(config) => { + inner.apply_config_v6(&mut socket, config); } #[cfg(feature = "dhcpv4")] Config::Dhcp(config) => { @@ -392,7 +415,7 @@ impl SocketStack { impl Inner { #[cfg(feature = "proto-ipv4")] - fn apply_config(&mut self, s: &mut SocketStack, config: StaticConfigV4) { + fn apply_config_v4(&mut self, s: &mut SocketStack, config: StaticConfigV4) { #[cfg(feature = "medium-ethernet")] let medium = self.device.capabilities().medium; @@ -431,6 +454,47 @@ impl Inner { self.static_v4 = Some(config) } + /// Replaces the current IPv6 static configuration with a newly supplied config. + #[cfg(feature = "proto-ipv6")] + fn apply_config_v6(&mut self, s: &mut SocketStack, config: StaticConfigV6) { + #[cfg(feature = "medium-ethernet")] + let medium = self.device.capabilities().medium; + + debug!("Acquired IPv6 configuration:"); + + debug!(" IP address: {}", config.address); + s.iface.update_ip_addrs(|addrs| { + if addrs.is_empty() { + addrs.push(IpCidr::Ipv6(config.address)).unwrap(); + } else { + addrs[0] = IpCidr::Ipv6(config.address); + } + }); + + #[cfg(feature = "medium-ethernet")] + if Medium::Ethernet == medium { + if let Some(gateway) = config.gateway { + debug!(" Default gateway: {}", gateway); + s.iface.routes_mut().add_default_ipv6_route(gateway).unwrap(); + } else { + debug!(" Default gateway: None"); + s.iface.routes_mut().remove_default_ipv6_route(); + } + } + for (i, s) in config.dns_servers.iter().enumerate() { + debug!(" DNS server {}: {}", i, s); + } + + #[cfg(feature = "dns")] + { + let socket = s.sockets.get_mut::(self.dns_socket); + let servers: Vec = config.dns_servers.iter().map(|c| IpAddress::Ipv6(*c)).collect(); + socket.update_servers(&servers[..]); + } + + self.static_v6 = Some(config) + } + #[cfg(feature = "dhcpv4")] fn apply_dhcp_config(&self, socket: &mut smoltcp::socket::dhcpv4::Socket, config: DhcpConfig) { socket.set_ignore_naks(config.ignore_naks); @@ -499,7 +563,7 @@ impl Inner { gateway: config.router, dns_servers: config.dns_servers, }; - self.apply_config(s, config) + self.apply_config_v4(s, config) } } } else if old_link_up { From 18578fd15f29e92280e4e317ff3148ea498566dd Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Mon, 5 Jun 2023 16:35:31 +0200 Subject: [PATCH 30/98] net: Allow a combined use of IPv4 and IPv6 DNS servers --- embassy-net/src/lib.rs | 49 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 9f83cb4ea..23ec33262 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -444,14 +444,12 @@ impl Inner { debug!(" DNS server {}: {}", i, s); } + self.static_v4 = Some(config); + #[cfg(feature = "dns")] { - let socket = s.sockets.get_mut::(self.dns_socket); - let servers: Vec = config.dns_servers.iter().map(|c| IpAddress::Ipv4(*c)).collect(); - socket.update_servers(&servers[..]); + self.update_dns_servers(s) } - - self.static_v4 = Some(config) } /// Replaces the current IPv6 static configuration with a newly supplied config. @@ -485,14 +483,47 @@ impl Inner { debug!(" DNS server {}: {}", i, s); } + self.static_v6 = Some(config); + #[cfg(feature = "dns")] { - let socket = s.sockets.get_mut::(self.dns_socket); - let servers: Vec = config.dns_servers.iter().map(|c| IpAddress::Ipv6(*c)).collect(); - socket.update_servers(&servers[..]); + self.update_dns_servers(s) + } + } + + #[cfg(feature = "dns")] + fn update_dns_servers(&mut self, s: &mut SocketStack) { + let socket = s.sockets.get_mut::(self.dns_socket); + + let servers_v4; + #[cfg(feature = "proto-ipv4")] + { + servers_v4 = self + .static_v4 + .iter() + .flat_map(|cfg| cfg.dns_servers.iter().map(|c| IpAddress::Ipv4(*c))); + }; + #[cfg(not(feature = "proto-ipv4"))] + { + servers_v4 = core::iter::empty(); } - self.static_v6 = Some(config) + let servers_v6; + #[cfg(feature = "proto-ipv6")] + { + servers_v6 = self + .static_v6 + .iter() + .flat_map(|cfg| cfg.dns_servers.iter().map(|c| IpAddress::Ipv6(*c))); + } + #[cfg(not(feature = "proto-ipv6"))] + { + servers_v6 = core::iter::empty(); + } + + // Prefer the v6 DNS servers over the v4 servers + let servers: Vec = servers_v6.chain(servers_v4).collect(); + socket.update_servers(&servers[..]); } #[cfg(feature = "dhcpv4")] From d2a6c5c6082dbf3c9783b809d89faf9b369ed1c9 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Mon, 5 Jun 2023 16:42:46 +0200 Subject: [PATCH 31/98] CI: Add proto-ipv6 tests without ipv4 to CI --- ci.sh | 4 ++++ ci_stable.sh | 2 ++ 2 files changed, 6 insertions(+) diff --git a/ci.sh b/ci.sh index 3d6e28796..91e7abcee 100755 --- a/ci.sh +++ b/ci.sh @@ -30,6 +30,10 @@ cargo batch \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits,nightly \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,nightly \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits,nightly \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52805,gpiote,time-driver-rtc1 \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52810,gpiote,time-driver-rtc1 \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52811,gpiote,time-driver-rtc1 \ diff --git a/ci_stable.sh b/ci_stable.sh index a67087ffb..72318fc43 100755 --- a/ci_stable.sh +++ b/ci_stable.sh @@ -17,6 +17,8 @@ cargo batch \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,medium-ethernet \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52805,gpiote,time-driver-rtc1 \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52810,gpiote,time-driver-rtc1 \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52811,gpiote,time-driver-rtc1 \ From ada7ec2289c1d396ab8ddcf90943ea593d334c52 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Mon, 5 Jun 2023 17:14:20 +0200 Subject: [PATCH 32/98] CI: add proto-ipv4 to embassy-net test --- ci.sh | 4 ++-- ci_stable.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci.sh b/ci.sh index 91e7abcee..852e512cd 100755 --- a/ci.sh +++ b/ci.sh @@ -25,7 +25,7 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \ --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \ --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features nightly,unstable-traits,defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly \ @@ -163,4 +163,4 @@ if [[ -z "${TELEPROBE_TOKEN-}" ]]; then exit fi -teleprobe client run -r out/tests \ No newline at end of file +teleprobe client run -r out/tests diff --git a/ci_stable.sh b/ci_stable.sh index 72318fc43..daae98961 100755 --- a/ci_stable.sh +++ b/ci_stable.sh @@ -14,7 +14,7 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features log \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features defmt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ From ae1dedc0596832f5ec2389d8ff845b10c0a480f1 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Tue, 6 Jun 2023 11:17:02 +0200 Subject: [PATCH 33/98] net: proto-ipv6 in is_config_up --- embassy-net/src/lib.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 23ec33262..4cc191d44 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -269,23 +269,42 @@ impl Stack { /// Get whether the network stack has a valid IP configuration. /// This is true if the network stack has a static IP configuration or if DHCP has completed pub fn is_config_up(&self) -> bool { + let v4_up; + let v6_up; + #[cfg(feature = "proto-ipv4")] { - return self.config_v4().is_some(); + v4_up = self.config_v4().is_some(); + } + #[cfg(not(feature = "proto-ipv4"))] + { + v4_up = false; } - #[cfg(not(any(feature = "proto-ipv4")))] + #[cfg(feature = "proto-ipv6")] { - false + v6_up = self.config_v6().is_some(); } + #[cfg(not(feature = "proto-ipv6"))] + { + v6_up = false; + } + + v4_up || v6_up } - /// Get the current IP configuration. + /// Get the current IPv4 configuration. #[cfg(feature = "proto-ipv4")] pub fn config_v4(&self) -> Option { self.with(|_s, i| i.static_v4.clone()) } + /// Get the current IPv6 configuration. + #[cfg(feature = "proto-ipv6")] + pub fn config_v6(&self) -> Option { + self.with(|_s, i| i.static_v6.clone()) + } + /// Run the network stack. /// /// You must call this in a background task, to process network events. From ca47af6978e85012ff70a98726fcb63ed985109d Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Tue, 6 Jun 2023 18:21:45 +0200 Subject: [PATCH 34/98] CI: introduce tests for dual stack v4 and v6 --- ci.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci.sh b/ci.sh index 852e512cd..f4f59177f 100755 --- a/ci.sh +++ b/ci.sh @@ -34,6 +34,10 @@ cargo batch \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,nightly \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits,nightly \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet,unstable-traits \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet,nightly \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet,unstable-traits,nightly \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52805,gpiote,time-driver-rtc1 \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52810,gpiote,time-driver-rtc1 \ --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52811,gpiote,time-driver-rtc1 \ From 2eb08b2dc92bc0393dc417de6ccdc039d30f6dd5 Mon Sep 17 00:00:00 2001 From: Russ Hewgill Date: Tue, 6 Jun 2023 09:49:38 -0700 Subject: [PATCH 35/98] updated can_recv and may_recv to match the smoltcp functions. --- embassy-net/src/tcp.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index 7babb5293..515bbc5be 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs @@ -278,10 +278,18 @@ impl<'a> TcpSocket<'a> { self.io.with(|s, _| s.may_send()) } - /// Get whether the socket is ready to receive data, i.e. whether there is some pending data in the receive buffer. + /// return whether the recieve half of the full-duplex connection is open. + /// This function returns true if it’s possible to receive data from the remote endpoint. + /// It will return true while there is data in the receive buffer, and if there isn’t, + /// as long as the remote endpoint has not closed the connection. pub fn may_recv(&self) -> bool { self.io.with(|s, _| s.may_recv()) } + + /// Get whether the socket is ready to receive data, i.e. whether there is some pending data in the receive buffer. + pub fn can_recv(&self) -> bool { + self.io.with(|s, _| s.can_recv()) + } } impl<'a> Drop for TcpSocket<'a> { From 352f0b6c3823797576c36f417d6be40189bca5d5 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Wed, 7 Jun 2023 12:04:15 +0200 Subject: [PATCH 36/98] =?UTF-8?q?net:=20Support=20dual=20stack=C2=A0IP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- embassy-net/src/lib.rs | 75 +++++++++++++++---- examples/nrf52840/src/bin/usb_ethernet.rs | 6 +- .../rp/src/bin/ethernet_w5500_multisocket.rs | 2 +- .../rp/src/bin/ethernet_w5500_tcp_client.rs | 2 +- .../rp/src/bin/ethernet_w5500_tcp_server.rs | 2 +- examples/rp/src/bin/ethernet_w5500_udp.rs | 2 +- examples/rp/src/bin/usb_ethernet.rs | 4 +- examples/rp/src/bin/wifi_ap_tcp_server.rs | 2 +- examples/rp/src/bin/wifi_tcp_server.rs | 4 +- examples/std/src/bin/net.rs | 4 +- examples/std/src/bin/net_dns.rs | 4 +- examples/std/src/bin/net_udp.rs | 4 +- examples/std/src/bin/tcp_accept.rs | 4 +- examples/stm32f4/src/bin/usb_ethernet.rs | 4 +- examples/stm32f7/src/bin/eth.rs | 4 +- examples/stm32h5/src/bin/eth.rs | 4 +- examples/stm32h7/src/bin/eth.rs | 4 +- examples/stm32h7/src/bin/eth_client.rs | 4 +- examples/stm32l5/src/bin/usb_ethernet.rs | 4 +- 19 files changed, 94 insertions(+), 45 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 4cc191d44..cf7ebad3f 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -127,16 +127,61 @@ impl Default for DhcpConfig { } /// Network stack configuration. -pub enum Config { - /// Use a static IPv4 address configuration. +pub struct Config { #[cfg(feature = "proto-ipv4")] - StaticV4(StaticConfigV4), - /// Use a static IPv6 address configuration. + pub ipv4: ConfigV4, #[cfg(feature = "proto-ipv6")] - StaticV6(StaticConfigV6), + pub ipv6: ConfigV6, +} + +impl Config { + #[cfg(feature = "proto-ipv4")] + pub fn ipv4_static(config: StaticConfigV4) -> Self { + Self { + ipv4: ConfigV4::Static(config), + #[cfg(feature = "proto-ipv6")] + ipv6: ConfigV6::None, + } + } + + #[cfg(feature = "proto-ipv6")] + pub fn ipv6_static(config: StaticConfigV6) -> Self { + Self { + #[cfg(feature = "proto-ipv4")] + ipv4: ConfigV4::None, + ipv6: ConfigV6::Static(config), + } + } + + #[cfg(feature = "dhcpv4")] + pub fn dhcpv4(config: DhcpConfig) -> Self { + Self { + ipv4: ConfigV4::Dhcp(config), + #[cfg(feature = "proto-ipv6")] + ipv6: ConfigV6::None, + } + } +} + +/// Network stack IPv4 configuration. +#[cfg(feature = "proto-ipv4")] +pub enum ConfigV4 { + /// Use a static IPv4 address configuration. + Static(StaticConfigV4), /// Use DHCP to obtain an IP address configuration. #[cfg(feature = "dhcpv4")] Dhcp(DhcpConfig), + /// Do not configure IPv6. + None, +} + +/// Network stack IPv6 configuration. +#[cfg(feature = "proto-ipv6")] +pub enum ConfigV6 { + /// Use a static IPv6 address configuration. + Static(StaticConfigV6), + /// Do not configure IPv6. + None, } /// A network stack. @@ -224,22 +269,26 @@ impl Stack { dns_waker: WakerRegistration::new(), }; - match config { - #[cfg(feature = "proto-ipv4")] - Config::StaticV4(config) => { + #[cfg(feature = "proto-ipv4")] + match config.ipv4 { + ConfigV4::Static(config) => { inner.apply_config_v4(&mut socket, config); } - #[cfg(feature = "proto-ipv6")] - Config::StaticV6(config) => { - inner.apply_config_v6(&mut socket, config); - } #[cfg(feature = "dhcpv4")] - Config::Dhcp(config) => { + ConfigV4::Dhcp(config) => { let mut dhcp_socket = smoltcp::socket::dhcpv4::Socket::new(); inner.apply_dhcp_config(&mut dhcp_socket, config); let handle = socket.sockets.add(dhcp_socket); inner.dhcp_socket = Some(handle); } + ConfigV4::None => {} + } + #[cfg(feature = "proto-ipv6")] + match config.ipv6 { + ConfigV6::Static(config) => { + inner.apply_config_v6(&mut socket, config); + } + ConfigV6::None => {} } Self { diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index b4316f5a4..f527c0d7f 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs @@ -97,12 +97,12 @@ async fn main(spawner: Spawner) { let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), - //}); + // }); // Generate random seed let mut rng = Rng::new(p.RNG, Irqs); diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 066ecf2bc..82568254a 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { // Init network stack let stack = &*make_static!(Stack::new( device, - embassy_net::Config::Dhcp(Default::default()), + embassy_net::Config::dhcpv4(Default::default()), make_static!(StackResources::<3>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index 3e0f5d136..d562defad 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -67,7 +67,7 @@ async fn main(spawner: Spawner) { // Init network stack let stack = &*make_static!(Stack::new( device, - embassy_net::Config::Dhcp(Default::default()), + embassy_net::Config::dhcpv4(Default::default()), make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index db178d49d..7f521cdb4 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -65,7 +65,7 @@ async fn main(spawner: Spawner) { // Init network stack let stack = &*make_static!(Stack::new( device, - embassy_net::Config::Dhcp(Default::default()), + embassy_net::Config::dhcpv4(Default::default()), make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 21943c3c6..ada86ae55 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { // Init network stack let stack = &*make_static!(Stack::new( device, - embassy_net::Config::Dhcp(Default::default()), + embassy_net::Config::dhcpv4(Default::default()), make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index d33d9c72e..91d1ec8e7 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -86,8 +86,8 @@ async fn main(spawner: Spawner) { let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 970cf4b32..e8197390c 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { .await; // Use a link-local address for communication without DHCP server - let config = Config::StaticV4(embassy_net::StaticConfigV4 { + let config = Config::ipv4_static(embassy_net::StaticConfigV4 { address: embassy_net::Ipv4Cidr::new(embassy_net::Ipv4Address::new(169, 254, 1, 1), 16), dns_servers: heapless::Vec::new(), gateway: None, diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 9f95f8b03..026e056fa 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -61,8 +61,8 @@ async fn main(spawner: Spawner) { .set_power_management(cyw43::PowerManagementMode::PowerSave) .await; - let config = Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::Config { + let config = Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(192, 168, 69, 1)), diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 14cf3f25b..3aadb029d 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs @@ -42,13 +42,13 @@ async fn main_task(spawner: Spawner) { // Choose between dhcp or static ip let config = if opts.static_ip { - Config::StaticV4(embassy_net::StaticConfigV4 { + Config::ipv4_static(embassy_net::StaticConfigV4 { address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), dns_servers: Vec::new(), gateway: Some(Ipv4Address::new(192, 168, 69, 1)), }) } else { - Config::Dhcp(Default::default()) + Config::dhcpv4(Default::default()) }; // Generate random seed diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index 0a479a744..65b5a2cd9 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs @@ -40,14 +40,14 @@ async fn main_task(spawner: Spawner) { // Choose between dhcp or static ip let config = if opts.static_ip { - Config::StaticV4(embassy_net::StaticConfigV4 { + Config::ipv4_static(embassy_net::StaticConfigV4 { address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 1), 24), dns_servers: Vec::from_slice(&[Ipv4Address::new(8, 8, 4, 4).into(), Ipv4Address::new(8, 8, 8, 8).into()]) .unwrap(), gateway: Some(Ipv4Address::new(192, 168, 69, 100)), }) } else { - Config::Dhcp(Default::default()) + Config::dhcpv4(Default::default()) }; // Generate random seed diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index 0ede5d998..3fc46156c 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs @@ -38,13 +38,13 @@ async fn main_task(spawner: Spawner) { // Choose between dhcp or static ip let config = if opts.static_ip { - Config::StaticV4(embassy_net::StaticConfigV4 { + Config::ipv4_static(embassy_net::StaticConfigV4 { address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), dns_servers: Vec::new(), gateway: Some(Ipv4Address::new(192, 168, 69, 1)), }) } else { - Config::Dhcp(Default::default()) + Config::dhcpv4(Default::default()) }; // Generate random seed diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index 4379d0439..df09986ac 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs @@ -53,13 +53,13 @@ async fn main_task(spawner: Spawner) { // Choose between dhcp or static ip let config = if opts.static_ip { - Config::StaticV4(embassy_net::StaticConfigV4 { + Config::ipv4_static(embassy_net::StaticConfigV4 { address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), dns_servers: Vec::new(), gateway: Some(Ipv4Address::new(192, 168, 69, 1)), }) } else { - Config::Dhcp(Default::default()) + Config::dhcpv4(Default::default()) }; // Generate random seed diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index 0856b4842..953d99a45 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs @@ -94,8 +94,8 @@ async fn main(spawner: Spawner) { let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index ebdf0d8a0..fde6a7576 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -62,8 +62,8 @@ async fn main(spawner: Spawner) -> ! { 0, ); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 811f74c88..78c8282a6 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -81,8 +81,8 @@ async fn main(spawner: Spawner) -> ! { 0, ); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 5360a213a..12d37f7a4 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -63,8 +63,8 @@ async fn main(spawner: Spawner) -> ! { 0, ); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 42781cfdc..6078fc3fe 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -64,8 +64,8 @@ async fn main(spawner: Spawner) -> ! { 0, ); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index d96d2f350..32eba4277 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -91,8 +91,8 @@ async fn main(spawner: Spawner) { let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), From 2455fd4dbe4e874a9a200d3026f66d437449b04d Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Wed, 7 Jun 2023 12:08:53 +0200 Subject: [PATCH 37/98] net: Add documentation to new Config system --- embassy-net/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index cf7ebad3f..7e8f765f9 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -128,13 +128,16 @@ impl Default for DhcpConfig { /// Network stack configuration. pub struct Config { + /// IPv4 configuration #[cfg(feature = "proto-ipv4")] pub ipv4: ConfigV4, + /// IPv6 configuration #[cfg(feature = "proto-ipv6")] pub ipv6: ConfigV6, } impl Config { + /// IPv4 configuration with static addressing. #[cfg(feature = "proto-ipv4")] pub fn ipv4_static(config: StaticConfigV4) -> Self { Self { @@ -144,6 +147,7 @@ impl Config { } } + /// IPv6 configuration with static addressing. #[cfg(feature = "proto-ipv6")] pub fn ipv6_static(config: StaticConfigV6) -> Self { Self { @@ -153,6 +157,12 @@ impl Config { } } + /// IPv6 configuration with dynamic addressing. + /// + /// # Example + /// ```rust + /// let _cfg = Config::dhcpv4(Default::default()); + /// ``` #[cfg(feature = "dhcpv4")] pub fn dhcpv4(config: DhcpConfig) -> Self { Self { From ce1d72c609ae1e04410e68458ec3d6c36c7dae27 Mon Sep 17 00:00:00 2001 From: goueslati Date: Thu, 8 Jun 2023 16:26:47 +0100 Subject: [PATCH 38/98] wip --- embassy-stm32/src/tl_mbox/ble.rs | 39 ++- embassy-stm32/src/tl_mbox/cmd.rs | 42 ++- embassy-stm32/src/tl_mbox/consts.rs | 4 +- embassy-stm32/src/tl_mbox/evt.rs | 106 +++++-- embassy-stm32/src/tl_mbox/hci.rs | 60 ++++ embassy-stm32/src/tl_mbox/mm.rs | 58 ++-- embassy-stm32/src/tl_mbox/mod.rs | 365 ++++++++++++---------- embassy-stm32/src/tl_mbox/shci.rs | 35 +-- embassy-stm32/src/tl_mbox/sys.rs | 67 ++-- examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | 55 +--- 10 files changed, 485 insertions(+), 346 deletions(-) create mode 100644 embassy-stm32/src/tl_mbox/hci.rs diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32/src/tl_mbox/ble.rs index 062377999..45bf81ef2 100644 --- a/embassy-stm32/src/tl_mbox/ble.rs +++ b/embassy-stm32/src/tl_mbox/ble.rs @@ -1,35 +1,36 @@ use embassy_futures::block_on; -use super::cmd::CmdSerial; +use super::cmd::{CmdPacket, CmdSerial}; use super::consts::TlPacketType; use super::evt::EvtBox; +use super::ipcc::Ipcc; use super::unsafe_linked_list::LinkedListNode; use super::{ - channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_CHANNEL, + channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, HEAPLESS_EVT_QUEUE, TL_BLE_TABLE, TL_REF_TABLE, }; -use crate::tl_mbox::cmd::CmdPacket; -use crate::tl_mbox::ipcc::Ipcc; pub struct Ble; impl Ble { - pub fn enable() { + pub(super) fn new() -> Self { unsafe { LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), - pcs_buffer: CS_BUFFER.as_mut_ptr().cast(), + pcs_buffer: CS_BUFFER.as_ptr().cast(), pevt_queue: EVT_QUEUE.as_ptr().cast(), phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), }); } Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); + + Ble } - pub fn evt_handler() { + pub(super) fn evt_handler() { unsafe { let mut node_ptr = core::ptr::null_mut(); let node_ptr_ptr: *mut _ = &mut node_ptr; @@ -40,25 +41,41 @@ impl Ble { let event = node_ptr.cast(); let event = EvtBox::new(event); - block_on(TL_CHANNEL.send(event)); + block_on(HEAPLESS_EVT_QUEUE.send(event)); } } Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); } + pub(super) fn acl_data_handler(&self) { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); + + // TODO: ACL data ack to the user + } + pub fn send_cmd(buf: &[u8]) { unsafe { let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; - let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmd_serial; + let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); - let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; - cmd_packet.cmd_serial.ty = TlPacketType::BleCmd as u8; + let mut cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; + cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; } Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); } + + #[allow(dead_code)] // Not used currently but reserved + pub(super) fn send_acl_data() { + let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; + + cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; + + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL); + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, true); + } } diff --git a/embassy-stm32/src/tl_mbox/cmd.rs b/embassy-stm32/src/tl_mbox/cmd.rs index 3507c3231..781aa669d 100644 --- a/embassy-stm32/src/tl_mbox/cmd.rs +++ b/embassy-stm32/src/tl_mbox/cmd.rs @@ -1,7 +1,8 @@ -use super::PacketHeader; +use crate::tl_mbox::evt::{EvtPacket, EvtSerial}; +use crate::tl_mbox::{PacketHeader, TL_EVT_HEADER_SIZE}; -#[repr(C, packed)] #[derive(Copy, Clone)] +#[repr(C, packed)] pub struct Cmd { pub cmd_code: u16, pub payload_len: u8, @@ -18,22 +19,49 @@ impl Default for Cmd { } } -#[repr(C, packed)] #[derive(Copy, Clone, Default)] +#[repr(C, packed)] pub struct CmdSerial { pub ty: u8, pub cmd: Cmd, } -#[repr(C, packed)] #[derive(Copy, Clone, Default)] +#[repr(C, packed)] pub struct CmdPacket { pub header: PacketHeader, - pub cmd_serial: CmdSerial, + pub cmdserial: CmdSerial, +} + +impl CmdPacket { + /// Writes an underlying CmdPacket into the provided buffer. + /// Returns a number of bytes that were written. + /// Returns an error if event kind is unknown or if provided buffer size is not enough. + #[allow(clippy::result_unit_err)] + pub fn write(&self, buf: &mut [u8]) -> Result { + unsafe { + let cmd_ptr: *const CmdPacket = self; + let self_as_evt_ptr: *const EvtPacket = cmd_ptr.cast(); + let evt_serial: *const EvtSerial = &(*self_as_evt_ptr).evt_serial; + + let acl_data: *const AclDataPacket = cmd_ptr.cast(); + let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + let acl_serial_buf: *const u8 = acl_serial.cast(); + + let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; + if len > buf.len() { + return Err(()); + } + + core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); + + Ok(len) + } + } } -#[repr(C, packed)] #[derive(Copy, Clone)] +#[repr(C, packed)] pub struct AclDataSerial { pub ty: u8, pub handle: u16, @@ -41,8 +69,8 @@ pub struct AclDataSerial { pub acl_data: [u8; 1], } -#[repr(C, packed)] #[derive(Copy, Clone)] +#[repr(C, packed)] pub struct AclDataPacket { pub header: PacketHeader, pub acl_data_serial: AclDataSerial, diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32/src/tl_mbox/consts.rs index e16a26cd0..caf26c06b 100644 --- a/embassy-stm32/src/tl_mbox/consts.rs +++ b/embassy-stm32/src/tl_mbox/consts.rs @@ -1,4 +1,6 @@ -#[derive(PartialEq)] +use core::convert::TryFrom; + +#[derive(Debug)] #[repr(C)] pub enum TlPacketType { BleCmd = 0x01, diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32/src/tl_mbox/evt.rs index 47a8b72fd..77ce7b4ca 100644 --- a/embassy-stm32/src/tl_mbox/evt.rs +++ b/embassy-stm32/src/tl_mbox/evt.rs @@ -2,11 +2,13 @@ use core::mem::MaybeUninit; use super::cmd::{AclDataPacket, AclDataSerial}; use super::consts::TlPacketType; +use super::mm::MemoryManager; use super::{PacketHeader, TL_EVT_HEADER_SIZE}; -use crate::tl_mbox::mm::MemoryManager; -/// the payload of [`Evt`] for a command status event -#[derive(Copy, Clone)] +/** + * The payload of `Evt` for a command status event + */ +#[derive(Debug, Copy, Clone)] #[repr(C, packed)] pub struct CsEvt { pub status: u8, @@ -14,16 +16,39 @@ pub struct CsEvt { pub cmd_code: u16, } -/// the payload of [`Evt`] for a command complete event -#[derive(Clone, Copy, Default)] +/** + * The payload of `Evt` for a command complete event + */ +#[derive(Debug, Copy, Clone, Default)] #[repr(C, packed)] pub struct CcEvt { pub num_cmd: u8, - pub cmd_code: u8, + pub cmd_code: u16, pub payload: [u8; 1], } -#[derive(Clone, Copy, Default)] +impl CcEvt { + pub fn write(&self, buf: &mut [u8]) { + unsafe { + let len = core::mem::size_of::(); + assert!(buf.len() >= len); + + let self_ptr: *const CcEvt = self; + let self_buf_ptr: *const u8 = self_ptr.cast(); + + core::ptr::copy(self_buf_ptr, buf.as_mut_ptr(), len); + } + } +} + +#[derive(Debug, Copy, Clone, Default)] +#[repr(C, packed)] +pub struct AsynchEvt { + sub_evt_code: u16, + payload: [u8; 1], +} + +#[derive(Debug, Copy, Clone, Default)] #[repr(C, packed)] pub struct Evt { pub evt_code: u8, @@ -31,7 +56,7 @@ pub struct Evt { pub payload: [u8; 1], } -#[derive(Clone, Copy, Default)] +#[derive(Debug, Copy, Clone, Default)] #[repr(C, packed)] pub struct EvtSerial { pub kind: u8, @@ -46,14 +71,26 @@ pub struct EvtSerial { /// Be careful that the asynchronous events reported by the CPU2 on the system channel do /// include the header and shall use `EvtPacket` format. Only the command response format on the /// system channel is different. -#[derive(Clone, Copy, Default)] +#[derive(Copy, Clone, Default)] #[repr(C, packed)] pub struct EvtPacket { pub header: PacketHeader, pub evt_serial: EvtSerial, } -/// Smart pointer to the [`EvtPacket`] that will dispose of it automatically on drop +impl EvtPacket { + pub fn kind(&self) -> u8 { + self.evt_serial.kind + } + + pub fn evt(&self) -> &Evt { + &self.evt_serial.evt + } +} + +/// smart pointer to the [`EvtPacket`] that will dispose of [`EvtPacket`] buffer automatically +/// on [`Drop`] +#[derive(Debug)] pub struct EvtBox { ptr: *mut EvtPacket, } @@ -64,7 +101,7 @@ impl EvtBox { Self { ptr } } - /// Copies the event data from inner pointer and returns and event structure + /// copies event data from inner pointer and returns an event structure pub fn evt(&self) -> EvtPacket { let mut evt = MaybeUninit::uninit(); unsafe { @@ -73,28 +110,11 @@ impl EvtBox { } } - /// Returns the size of a buffer required to hold this event - pub fn size(&self) -> Result { - unsafe { - let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; - - if evt_kind == TlPacketType::AclData { - let acl_data: *const AclDataPacket = self.ptr.cast(); - let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; - - Ok((*acl_serial).length as usize + 5) - } else { - let evt_data: *const EvtPacket = self.ptr.cast(); - let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; - - Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) - } - } - } - - /// writes an underlying [`EvtPacket`] into the provided buffer. Returns the number of bytes that were - /// written. Returns an error if event kind is unkown or if provided buffer size is not enough - pub fn copy_into_slice(&self, buf: &mut [u8]) -> Result { + /// writes an underlying [`EvtPacket`] into the provided buffer. + /// Returns the number of bytes that were written. + /// Returns an error if event kind is unknown or if provided buffer size is not enough. + #[allow(clippy::result_unit_err)] + pub fn write(&self, buf: &mut [u8]) -> Result { unsafe { let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; @@ -127,6 +147,26 @@ impl EvtBox { } } } + + /// returns the size of a buffer required to hold this event + #[allow(clippy::result_unit_err)] + pub fn size(&self) -> Result { + unsafe { + let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; + + let evt_data: *const EvtPacket = self.ptr.cast(); + let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; + + let acl_data: *const AclDataPacket = self.ptr.cast(); + let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + + if let TlPacketType::AclData = evt_kind { + Ok((*acl_serial).length as usize + 5) + } else { + Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) + } + } + } } impl Drop for EvtBox { diff --git a/embassy-stm32/src/tl_mbox/hci.rs b/embassy-stm32/src/tl_mbox/hci.rs new file mode 100644 index 000000000..5bb4ba666 --- /dev/null +++ b/embassy-stm32/src/tl_mbox/hci.rs @@ -0,0 +1,60 @@ +use super::ble::Ble; +use super::consts::TlPacketType; +use super::evt::CcEvt; +use super::shci::{shci_ble_init, ShciBleInitCmdParam}; +use super::{TlMbox, STATE}; + +pub struct RadioCoprocessor<'d> { + mbox: TlMbox<'d>, + config: ShciBleInitCmdParam, + rx_buffer: [u8; 500], +} + +impl<'d> RadioCoprocessor<'d> { + pub fn new(mbox: TlMbox<'d>, config: ShciBleInitCmdParam) -> Self { + Self { + mbox, + config, + rx_buffer: [0u8; 500], + } + } + + pub fn write(&mut self, params: &[u8]) -> Result<(), ()> { + let cmd_code = params[0]; + let cmd = TlPacketType::try_from(cmd_code)?; + + match cmd { + TlPacketType::BleCmd => Ble::send_cmd(params), + _ => todo!(), + } + + Ok(()) + } + + pub async fn read(&mut self) -> &[u8] { + self.rx_buffer = [0u8; 500]; + + loop { + STATE.wait().await; + + if let Some(evt) = self.mbox.dequeue_event() { + let event = evt.evt(); + evt.write(&mut self.rx_buffer).unwrap(); + + if event.kind() == 18 { + shci_ble_init(self.config); + self.rx_buffer[0] = 0x04; // replace event code with one that is supported by HCI + } + + if let Some(cc) = self.mbox.pop_last_cc_evt() { + + + continue; + } + + let payload_len = self.rx_buffer[2]; + return &self.rx_buffer[..3 + payload_len as usize]; + } + } + } +} diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs index e28a6aa0c..a40438499 100644 --- a/embassy-stm32/src/tl_mbox/mm.rs +++ b/embassy-stm32/src/tl_mbox/mm.rs @@ -1,56 +1,57 @@ +//! Memory manager routines + +use core::mem::MaybeUninit; + use super::evt::EvtPacket; +use super::ipcc::Ipcc; use super::unsafe_linked_list::LinkedListNode; use super::{ - channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, + channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, }; -use crate::tl_mbox::ipcc::Ipcc; -pub struct MemoryManager; +pub(super) struct MemoryManager; impl MemoryManager { - pub fn enable() { + pub fn new() -> Self { unsafe { - LinkedListNode::init_head(FREE_BUFF_QUEUE.as_mut_ptr()); + LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); - TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { + TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), - ble_pool: EVT_POOL.as_ptr().cast(), - ble_pool_size: POOL_SIZE as u32, - pevt_free_buffer_queue: FREE_BUFF_QUEUE.as_mut_ptr(), + blepool: EVT_POOL.as_ptr().cast(), + blepoolsize: POOL_SIZE as u32, + pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(), traces_evt_pool: core::ptr::null(), - traces_pool_size: 0, + tracespoolsize: 0, }); } - } - pub fn evt_handler() { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); - Self::send_free_buf(); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + MemoryManager } pub fn evt_drop(evt: *mut EvtPacket) { unsafe { let list_node = evt.cast(); - LinkedListNode::remove_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); - } + LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); - let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - // postpone event buffer freeing to IPCC interrupt handler - if channel_is_busy { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); - } else { - Self::send_free_buf(); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + // postpone event buffer freeing to IPCC interrupt handler + if channel_is_busy { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); + } else { + Self::send_free_buf(); + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + } } } - fn send_free_buf() { + /// gives free event buffers back to CPU2 from local buffer queue + pub fn send_free_buf() { unsafe { let mut node_ptr = core::ptr::null_mut(); let node_ptr_ptr: *mut _ = &mut node_ptr; @@ -64,4 +65,11 @@ impl MemoryManager { } } } + + /// free buffer channel interrupt handler + pub fn free_buf_handler() { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); + Self::send_free_buf(); + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + } } diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs index efbbf2d1d..21a954417 100644 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ b/embassy-stm32/src/tl_mbox/mod.rs @@ -1,79 +1,50 @@ use core::mem::MaybeUninit; -use atomic_polyfill::{compiler_fence, Ordering}; use bit_field::BitField; use embassy_cortex_m::interrupt::Interrupt; +use embassy_futures::block_on; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; +use embassy_sync::signal::Signal; -use self::ble::Ble; use self::cmd::{AclDataPacket, CmdPacket}; -use self::evt::{CsEvt, EvtBox}; -use self::mm::MemoryManager; -use self::shci::{shci_ble_init, ShciBleInitCmdParam}; -use self::sys::Sys; +use self::evt::{CcEvt, EvtBox}; +use self::ipcc::{Config, Ipcc}; use self::unsafe_linked_list::LinkedListNode; use crate::interrupt; use crate::peripherals::IPCC; -pub use crate::tl_mbox::ipcc::Config; -use crate::tl_mbox::ipcc::Ipcc; -mod ble; -mod channels; -mod cmd; -mod consts; -mod evt; -mod ipcc; -mod mm; -mod shci; -mod sys; -mod unsafe_linked_list; - -pub type PacketHeader = LinkedListNode; - -const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::(); -const TL_EVT_HEADER_SIZE: usize = 3; -const TL_CS_EVT_SIZE: usize = core::mem::size_of::(); - -const CFG_TL_BLE_EVT_QUEUE_LENGTH: usize = 5; -const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; -const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE; - -const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); - -const fn divc(x: usize, y: usize) -> usize { - (x + y - 1) / y -} - -#[repr(C, packed)] -#[derive(Copy, Clone)] -pub struct SafeBootInfoTable { - version: u32, -} - -#[repr(C, packed)] -#[derive(Copy, Clone)] -pub struct FusInfoTable { - version: u32, - memory_size: u32, - fus_info: u32, -} +pub mod ble; +pub mod channels; +pub mod cmd; +pub mod consts; +pub mod evt; +pub mod hci; +pub mod ipcc; +pub mod mm; +pub mod shci; +pub mod sys; +pub mod unsafe_linked_list; /// Interrupt handler. pub struct ReceiveInterruptHandler {} impl interrupt::Handler for ReceiveInterruptHandler { unsafe fn on_interrupt() { - // info!("ipcc rx interrupt"); + debug!("ipcc rx interrupt"); if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { + debug!("sys evt"); sys::Sys::evt_handler(); } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { + debug!("ble evt"); ble::Ble::evt_handler(); } else { todo!() } + + STATE.signal(()); } } @@ -81,37 +52,62 @@ pub struct TransmitInterruptHandler {} impl interrupt::Handler for TransmitInterruptHandler { unsafe fn on_interrupt() { - // info!("ipcc tx interrupt"); + debug!("ipcc tx interrupt"); if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { + debug!("sys cmd rsp"); // TODO: handle this case - let _ = sys::Sys::cmd_evt_handler(); + let cc = sys::Sys::cmd_evt_handler(); + let a = unsafe { core::slice::from_raw_parts(&cc as *const _ as *const u8, core::mem::size_of::()) }; + debug!("{:#04x}", a); + + LAST_CC_EVT.signal(cc); } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { - mm::MemoryManager::evt_handler(); + debug!("mm"); + mm::MemoryManager::free_buf_handler(); } else { todo!() } + + STATE.signal(()); } } -/// # Version -/// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version -/// - 4 -> 7 = branch - 0: Mass Market - x: ... -/// - 8 -> 15 = Subversion -/// - 16 -> 23 = Version minor -/// - 24 -> 31 = Version major -/// # Memory Size -/// - 0 -> 7 = Flash ( Number of 4k sector) -/// - 8 -> 15 = Reserved ( Shall be set to 0 - may be used as flash extension ) -/// - 16 -> 23 = SRAM2b ( Number of 1k sector) -/// - 24 -> 31 = SRAM2a ( Number of 1k sector) +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct SafeBootInfoTable { + version: u32, +} + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct RssInfoTable { + version: u32, + memory_size: u32, + rss_info: u32, +} + +/** + * Version + * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version + * [4:7] = branch - 0: Mass Market - x: ... + * [8:15] = Subversion + * [16:23] = Version minor + * [24:31] = Version major + * + * Memory Size + * [0:7] = Flash ( Number of 4k sector) + * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension ) + * [16:23] = SRAM2b ( Number of 1k sector) + * [24:31] = SRAM2a ( Number of 1k sector) + */ +#[derive(Debug, Copy, Clone)] #[repr(C, packed)] -#[derive(Copy, Clone)] pub struct WirelessFwInfoTable { version: u32, memory_size: u32, - info_stack: u32, - reserved: u32, + thread_info: u32, + ble_info: u32, } impl WirelessFwInfoTable { @@ -122,42 +118,43 @@ impl WirelessFwInfoTable { pub fn version_minor(&self) -> u8 { let version = self.version; - (version.get_bits(16..23) & 0xff) as u8 + (version.clone().get_bits(16..23) & 0xff) as u8 } pub fn subversion(&self) -> u8 { let version = self.version; - (version.get_bits(8..15) & 0xff) as u8 + (version.clone().get_bits(8..15) & 0xff) as u8 } - /// size of FLASH, expressed in number of 4K sectors + /// Size of FLASH, expressed in number of 4K sectors. pub fn flash_size(&self) -> u8 { let memory_size = self.memory_size; - (memory_size.get_bits(0..7) & 0xff) as u8 + (memory_size.clone().get_bits(0..7) & 0xff) as u8 } - /// size for SRAM2a, expressed in number of 1K sectors + /// Size of SRAM2a, expressed in number of 1K sectors. pub fn sram2a_size(&self) -> u8 { let memory_size = self.memory_size; - (memory_size.get_bits(24..31) & 0xff) as u8 + (memory_size.clone().get_bits(24..31) & 0xff) as u8 } - /// size of SRAM2b, expressed in number of 1K sectors + /// Size of SRAM2b, expressed in number of 1K sectors. pub fn sram2b_size(&self) -> u8 { let memory_size = self.memory_size; - (memory_size.get_bits(16..23) & 0xff) as u8 + (memory_size.clone().get_bits(16..23) & 0xff) as u8 } } -#[repr(C, packed)] -#[derive(Copy, Clone)] +#[derive(Debug, Clone)] +#[repr(C, align(4))] pub struct DeviceInfoTable { pub safe_boot_info_table: SafeBootInfoTable, - pub fus_info_table: FusInfoTable, + pub rss_info_table: RssInfoTable, pub wireless_fw_info_table: WirelessFwInfoTable, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct BleTable { pcmd_buffer: *mut CmdPacket, pcs_buffer: *const u8, @@ -165,81 +162,86 @@ struct BleTable { phci_acl_data_buffer: *mut AclDataPacket, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct ThreadTable { - no_stack_buffer: *const u8, - cli_cmd_rsp_buffer: *const u8, - ot_cmd_rsp_buffer: *const u8, + nostack_buffer: *const u8, + clicmdrsp_buffer: *const u8, + otcmdrsp_buffer: *const u8, } -#[repr(C, packed)] +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct LldTestsTable { + clicmdrsp_buffer: *const u8, + m0cmd_buffer: *const u8, +} + +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct BleLldTable { + cmdrsp_buffer: *const u8, + m0cmd_buffer: *const u8, +} + +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct ZigbeeTable { + notif_m0_to_m4_buffer: *const u8, + appli_cmd_m4_to_m0_bufer: *const u8, + request_m0_to_m4_buffer: *const u8, +} + +#[derive(Debug)] +#[repr(C, align(4))] struct SysTable { pcmd_buffer: *mut CmdPacket, sys_queue: *const LinkedListNode, } -#[allow(dead_code)] // Not used currently but reserved -#[repr(C, packed)] -struct LldTestTable { - cli_cmd_rsp_buffer: *const u8, - m0_cmd_buffer: *const u8, -} - -#[allow(dead_code)] // Not used currently but reserved -#[repr(C, packed)] -struct BleLldTable { - cmd_rsp_buffer: *const u8, - m0_cmd_buffer: *const u8, -} - -#[allow(dead_code)] // Not used currently but reserved -#[repr(C, packed)] -struct ZigbeeTable { - notif_m0_to_m4_buffer: *const u8, - appli_cmd_m4_to_m0_buffer: *const u8, - request_m0_to_m4_buffer: *const u8, -} - -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct MemManagerTable { spare_ble_buffer: *const u8, spare_sys_buffer: *const u8, - ble_pool: *const u8, - ble_pool_size: u32, + blepool: *const u8, + blepoolsize: u32, pevt_free_buffer_queue: *mut LinkedListNode, traces_evt_pool: *const u8, - traces_pool_size: u32, + tracespoolsize: u32, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct TracesTable { traces_queue: *const u8, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct Mac802_15_4Table { - pcmd_rsp_buffer: *const u8, - pnotack_buffer: *const u8, + p_cmdrsp_buffer: *const u8, + p_notack_buffer: *const u8, evt_queue: *const u8, } -/// reference table. Contains pointers to all other tables -#[repr(C, packed)] -#[derive(Copy, Clone)] +/// Reference table. Contains pointers to all other tables. +#[derive(Debug, Copy, Clone)] +#[repr(C)] pub struct RefTable { - pub device_info_table: *const DeviceInfoTable, + device_info_table: *const DeviceInfoTable, ble_table: *const BleTable, thread_table: *const ThreadTable, sys_table: *const SysTable, mem_manager_table: *const MemManagerTable, traces_table: *const TracesTable, mac_802_15_4_table: *const Mac802_15_4Table, - zigbee_table: *const ZigbeeTable, - lld_tests_table: *const LldTestTable, - ble_lld_table: *const BleLldTable, } #[link_section = "TL_REF_TABLE"] @@ -254,12 +256,6 @@ static mut TL_BLE_TABLE: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM1"] static mut TL_THREAD_TABLE: MaybeUninit = MaybeUninit::uninit(); -#[link_section = "MB_MEM1"] -static mut TL_LLD_TESTS_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_BLE_LLD_TABLE: MaybeUninit = MaybeUninit::uninit(); - #[link_section = "MB_MEM1"] static mut TL_SYS_TABLE: MaybeUninit = MaybeUninit::uninit(); @@ -272,15 +268,21 @@ static mut TL_TRACES_TABLE: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM1"] static mut TL_MAC_802_15_4_TABLE: MaybeUninit = MaybeUninit::uninit(); -#[link_section = "MB_MEM1"] -static mut TL_ZIGBEE_TABLE: MaybeUninit = MaybeUninit::uninit(); +#[link_section = "MB_MEM2"] +static mut FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); + +// Not in shared RAM +static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); #[allow(dead_code)] // Not used currently but reserved -#[link_section = "MB_MEM1"] -static mut FREE_BUFF_QUEUE: MaybeUninit = MaybeUninit::uninit(); +#[link_section = "MB_MEM2"] +static mut TRACES_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); -// not in shared RAM -static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); +type PacketHeader = LinkedListNode; + +const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::(); +const TL_EVT_HEADER_SIZE: usize = 3; +const TL_CS_EVT_SIZE: usize = core::mem::size_of::(); #[link_section = "MB_MEM2"] static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = @@ -293,7 +295,30 @@ static mut EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); static mut SYSTEM_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM2"] -static mut SYS_CMD_BUF: MaybeUninit = MaybeUninit::uninit(); +pub static mut SYS_CMD_BUF: MaybeUninit = MaybeUninit::uninit(); + +/** + * Queue length of BLE Event + * This parameter defines the number of asynchronous events that can be stored in the HCI layer before + * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer + * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large + * enough to store all asynchronous events received in between. + * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events + * between the HCI command and its event. + * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small, + * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting + * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate + * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout). + */ +const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5; +const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; +const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE; + +const fn divc(x: usize, y: usize) -> usize { + ((x) + (y) - 1) / (y) +} + +const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); #[link_section = "MB_MEM2"] static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); @@ -310,18 +335,27 @@ static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HE static mut BLE_CMD_BUFFER: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM2"] -// "magic" numbers from ST ---v---v +// fuck these "magic" numbers from ST ---v---v static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); -// TODO: get a better size, this is a placeholder -pub(crate) static TL_CHANNEL: Channel = Channel::new(); +static HEAPLESS_EVT_QUEUE: Channel = Channel::new(); + +static STATE: Signal = Signal::new(); + +/// current event that is produced during IPCC IRQ handler execution +/// on SYS channel +/// last received Command Complete event +static LAST_CC_EVT: Signal = Signal::new(); pub struct TlMbox<'d> { + sys: sys::Sys, + ble: ble::Ble, + _mm: mm::MemoryManager, + _ipcc: PeripheralRef<'d, IPCC>, } impl<'d> TlMbox<'d> { - /// initializes low-level transport between CPU1 and BLE stack on CPU2 pub fn new( ipcc: impl Peripheral

+ 'd, _irqs: impl interrupt::Binding @@ -331,25 +365,16 @@ impl<'d> TlMbox<'d> { into_ref!(ipcc); unsafe { - compiler_fence(Ordering::AcqRel); - TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { - device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), + device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), ble_table: TL_BLE_TABLE.as_ptr(), thread_table: TL_THREAD_TABLE.as_ptr(), sys_table: TL_SYS_TABLE.as_ptr(), mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), traces_table: TL_TRACES_TABLE.as_ptr(), mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), - zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), - lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), - ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), }); - // info!("TL_REF_TABLE addr: {:x}", TL_REF_TABLE.as_ptr() as usize); - - compiler_fence(Ordering::AcqRel); - TL_SYS_TABLE = MaybeUninit::zeroed(); TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); TL_BLE_TABLE = MaybeUninit::zeroed(); @@ -357,9 +382,6 @@ impl<'d> TlMbox<'d> { TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); TL_TRACES_TABLE = MaybeUninit::zeroed(); TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); - TL_ZIGBEE_TABLE = MaybeUninit::zeroed(); - TL_LLD_TESTS_TABLE = MaybeUninit::zeroed(); - TL_BLE_LLD_TABLE = MaybeUninit::zeroed(); EVT_POOL = MaybeUninit::zeroed(); SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); @@ -368,15 +390,13 @@ impl<'d> TlMbox<'d> { CS_BUFFER = MaybeUninit::zeroed(); BLE_CMD_BUFFER = MaybeUninit::zeroed(); HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); - - compiler_fence(Ordering::AcqRel); } Ipcc::enable(config); - Sys::enable(); - Ble::enable(); - MemoryManager::enable(); + let sys = sys::Sys::new(); + let ble = ble::Ble::new(); + let mm = mm::MemoryManager::new(); // enable interrupts crate::interrupt::IPCC_C1_RX::unpend(); @@ -385,13 +405,19 @@ impl<'d> TlMbox<'d> { unsafe { crate::interrupt::IPCC_C1_RX::enable() }; unsafe { crate::interrupt::IPCC_C1_TX::enable() }; - Self { _ipcc: ipcc } + Self { + sys, + ble, + _mm: mm, + _ipcc: ipcc, + } } + /// Returns CPU2 wireless firmware information (if present). pub fn wireless_fw_info(&self) -> Option { let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table }; - // zero version indicates that CPU2 wasn't active and didn't fill the information table + // Zero version indicates that CPU2 wasn't active and didn't fill the information table if info.version != 0 { Some(*info) } else { @@ -399,19 +425,22 @@ impl<'d> TlMbox<'d> { } } - pub fn shci_ble_init(&self, param: ShciBleInitCmdParam) { - shci_ble_init(param); + /// picks single [`EvtBox`] from internal event queue. + /// + /// Internal event queu is populated in IPCC_RX_IRQ handler + pub fn dequeue_event(&mut self) -> Option { + HEAPLESS_EVT_QUEUE.try_recv().ok() } - pub fn send_ble_cmd(&self, buf: &[u8]) { - ble::Ble::send_cmd(buf); - } + /// retrieves last Command Complete event and removes it from mailbox + pub fn pop_last_cc_evt(&mut self) -> Option { + if LAST_CC_EVT.signaled() { + let cc = Some(block_on(LAST_CC_EVT.wait())); + LAST_CC_EVT.reset(); - // pub fn send_sys_cmd(&self, buf: &[u8]) { - // sys::Sys::send_cmd(buf); - // } - - pub async fn read(&self) -> EvtBox { - TL_CHANNEL.recv().await + cc + } else { + None + } } } diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32/src/tl_mbox/shci.rs index 6b5b2dd19..b19baa702 100644 --- a/embassy-stm32/src/tl_mbox/shci.rs +++ b/embassy-stm32/src/tl_mbox/shci.rs @@ -1,16 +1,10 @@ -//! HCI commands for system channel - use super::cmd::CmdPacket; use super::consts::TlPacketType; -use super::{channels, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; -use crate::tl_mbox::ipcc::Ipcc; +use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; -pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; -#[allow(dead_code)] -const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] #[repr(C, packed)] pub struct ShciBleInitCmdParam { /// NOT USED CURRENTLY @@ -63,39 +57,44 @@ impl Default for ShciBleInitCmdParam { } } -#[derive(Clone, Copy, Default)] +#[derive(Debug, Clone, Copy, Default)] #[repr(C, packed)] pub struct ShciHeader { metadata: [u32; 3], } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] #[repr(C, packed)] pub struct ShciBleInitCmdPacket { header: ShciHeader, param: ShciBleInitCmdParam, } +pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; +#[allow(dead_code)] // Not used currently but reserved +const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; + pub fn shci_ble_init(param: ShciBleInitCmdParam) { + debug!("shci init"); + let mut packet = ShciBleInitCmdPacket { header: ShciHeader::default(), param, }; - let packet_ptr: *mut ShciBleInitCmdPacket = &mut packet; + let packet_ptr: *mut _ = &mut packet; unsafe { let cmd_ptr: *mut CmdPacket = packet_ptr.cast(); - (*cmd_ptr).cmd_serial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; - (*cmd_ptr).cmd_serial.cmd.payload_len = core::mem::size_of::() as u8; + (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; + (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::() as u8; - let cmd_buf = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; - core::ptr::write(cmd_buf, *cmd_ptr); + let mut p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; + core::ptr::write(p_cmd_buffer, *cmd_ptr); - cmd_buf.cmd_serial.ty = TlPacketType::SysCmd as u8; + p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); + sys::send_cmd(); } } diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32/src/tl_mbox/sys.rs index 9685fb920..c87aa440c 100644 --- a/embassy-stm32/src/tl_mbox/sys.rs +++ b/embassy-stm32/src/tl_mbox/sys.rs @@ -1,45 +1,27 @@ use embassy_futures::block_on; use super::cmd::{CmdPacket, CmdSerial}; -use super::consts::TlPacketType; use super::evt::{CcEvt, EvtBox, EvtSerial}; +use super::ipcc::Ipcc; use super::unsafe_linked_list::LinkedListNode; -use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_CHANNEL, TL_REF_TABLE, TL_SYS_TABLE}; -use crate::tl_mbox::ipcc::Ipcc; +use super::{channels, SysTable, HEAPLESS_EVT_QUEUE, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; pub struct Sys; impl Sys { - pub fn enable() { + pub fn new() -> Self { unsafe { LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), - }); + }) } Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); - } - pub fn evt_handler() { - unsafe { - let mut node_ptr = core::ptr::null_mut(); - let node_ptr_ptr: *mut _ = &mut node_ptr; - - while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); - - let event = node_ptr.cast(); - let event = EvtBox::new(event); - - // TODO: not really happy about this - block_on(TL_CHANNEL.send(event)); - } - } - - Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); + Sys } pub fn cmd_evt_handler() -> CcEvt { @@ -55,29 +37,40 @@ impl Sys { // 4. CcEvt type is the actual SHCI response // 5. profit unsafe { - let cmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; - let cmd_serial: *const CmdSerial = &(*cmd).cmd_serial; + let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; + + let a = unsafe { + core::slice::from_raw_parts(&pcmd as *const _ as *const u8, core::mem::size_of::()) + }; + debug!("shci response {:#04x}", a); + + let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial; let evt_serial: *const EvtSerial = cmd_serial.cast(); - let cc = (*evt_serial).evt.payload.as_ptr().cast(); + let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); *cc } } - #[allow(dead_code)] - pub fn send_cmd(buf: &[u8]) { + pub fn evt_handler() { unsafe { - // TODO: check this - let cmd_buffer = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; - let cmd_serial: *mut CmdSerial = &mut cmd_buffer.cmd_serial; - let cmd_serial_buf = cmd_serial.cast(); + let mut node_ptr = core::ptr::null_mut(); + let node_ptr_ptr: *mut _ = &mut node_ptr; - core::ptr::copy(buf.as_ptr(), cmd_serial_buf, buf.len()); + while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { + LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); - let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; - cmd_packet.cmd_serial.ty = TlPacketType::SysCmd as u8; + let event = node_ptr.cast(); + let event = EvtBox::new(event); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); + block_on(HEAPLESS_EVT_QUEUE.send(event)); + } } + + Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); } } + +pub fn send_cmd() { + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); +} diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 1724d946f..0525d3f37 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs @@ -4,7 +4,9 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::tl_mbox::{Config, TlMbox}; +use embassy_stm32::tl_mbox::hci::RadioCoprocessor; +use embassy_stm32::tl_mbox::ipcc::Config; +use embassy_stm32::tl_mbox::TlMbox; use embassy_stm32::{bind_interrupts, tl_mbox}; use {defmt_rtt as _, panic_probe as _}; @@ -45,53 +47,14 @@ async fn main(_spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::new(p.IPCC, Irqs, config); - info!("waiting for coprocessor to boot"); - let event_box = mbox.read().await; + let mut rc = RadioCoprocessor::new(mbox, Default::default()); + rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]).unwrap(); - let mut payload = [0u8; 6]; - event_box.copy_into_slice(&mut payload).unwrap(); + let response = rc.read().await; + info!("coprocessor ready {}", response); - let event_packet = event_box.evt(); - let kind = event_packet.evt_serial.kind; - - // means recieved SYS event, which indicates in this case that the coprocessor is ready - if kind == 0x12 { - let code = event_packet.evt_serial.evt.evt_code; - let payload_len = event_packet.evt_serial.evt.payload_len; - - info!( - "==> kind: {:#04x}, code: {:#04x}, payload_length: {}, payload: {:#04x}", - kind, - code, - payload_len, - payload[3..] - ); - } - - // initialize ble stack, does not return a response - mbox.shci_ble_init(Default::default()); - - info!("resetting BLE"); - mbox.send_ble_cmd(&[0x01, 0x03, 0x0c, 0x00, 0x00]); - - let event_box = mbox.read().await; - - let mut payload = [0u8; 7]; - event_box.copy_into_slice(&mut payload).unwrap(); - - let event_packet = event_box.evt(); - let kind = event_packet.evt_serial.kind; - - let code = event_packet.evt_serial.evt.evt_code; - let payload_len = event_packet.evt_serial.evt.payload_len; - - info!( - "==> kind: {:#04x}, code: {:#04x}, payload_length: {}, payload: {:#04x}", - kind, - code, - payload_len, - payload[3..] - ); + let response = rc.read().await; + info!("coprocessor ready {}", response); info!("Test OK"); cortex_m::asm::bkpt(); From 921780e6bfb9bcb2cd087b8aa8b094d792c99fa2 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 8 Jun 2023 16:08:40 +0200 Subject: [PATCH 39/98] Make interrupt module more standard. - Move typelevel interrupts to a special-purpose mod: `embassy_xx::interrupt::typelevel`. - Reexport the PAC interrupt enum in `embassy_xx::interrupt`. This has a few advantages: - The `embassy_xx::interrupt` module is now more "standard". - It works with `cortex-m` functions for manipulating interrupts, for example. - It works with RTIC. - the interrupt enum allows holding value that can be "any interrupt at runtime", this can't be done with typelevel irqs. - When "const-generics on enums" is stable, we can remove the typelevel interrupts without disruptive changes to `embassy_xx::interrupt`. --- embassy-cortex-m/src/interrupt.rs | 211 +++++++++++++----- embassy-lora/src/iv.rs | 12 +- embassy-macros/src/lib.rs | 13 -- .../src/macros/cortex_m_interrupt.rs | 66 ------ .../src/macros/cortex_m_interrupt_declare.rs | 21 -- embassy-macros/src/macros/mod.rs | 2 - embassy-nrf/src/buffered_uarte.rs | 11 +- embassy-nrf/src/chips/nrf52805.rs | 56 +++-- embassy-nrf/src/chips/nrf52810.rs | 62 +++-- embassy-nrf/src/chips/nrf52811.rs | 62 +++-- embassy-nrf/src/chips/nrf52820.rs | 60 +++-- embassy-nrf/src/chips/nrf52832.rs | 82 ++++--- embassy-nrf/src/chips/nrf52833.rs | 90 ++++---- embassy-nrf/src/chips/nrf52840.rs | 94 ++++---- embassy-nrf/src/chips/nrf5340_app.rs | 90 ++++---- embassy-nrf/src/chips/nrf5340_net.rs | 48 ++-- embassy-nrf/src/chips/nrf9160.rs | 70 +++--- embassy-nrf/src/gpiote.rs | 14 +- embassy-nrf/src/i2s.rs | 14 +- embassy-nrf/src/lib.rs | 29 +-- embassy-nrf/src/pdm.rs | 13 +- embassy-nrf/src/pwm.rs | 7 +- embassy-nrf/src/qdec.rs | 12 +- embassy-nrf/src/qspi.rs | 12 +- embassy-nrf/src/rng.rs | 10 +- embassy-nrf/src/saadc.rs | 10 +- embassy-nrf/src/spim.rs | 16 +- embassy-nrf/src/spis.rs | 16 +- embassy-nrf/src/temp.rs | 10 +- embassy-nrf/src/time_driver.rs | 6 +- embassy-nrf/src/timer.rs | 5 +- embassy-nrf/src/twim.rs | 12 +- embassy-nrf/src/twis.rs | 12 +- embassy-nrf/src/uarte.rs | 22 +- embassy-nrf/src/usb/mod.rs | 12 +- embassy-nrf/src/usb/vbus_detect.rs | 12 +- embassy-rp/src/adc.rs | 16 +- embassy-rp/src/dma.rs | 8 +- embassy-rp/src/gpio.rs | 8 +- embassy-rp/src/i2c.rs | 13 +- embassy-rp/src/interrupt.rs | 65 ------ embassy-rp/src/lib.rs | 64 +++++- embassy-rp/src/multicore.rs | 4 +- embassy-rp/src/pio.rs | 14 +- embassy-rp/src/timer.rs | 10 +- embassy-rp/src/uart/buffered.rs | 6 +- embassy-rp/src/uart/mod.rs | 10 +- embassy-rp/src/usb.rs | 11 +- embassy-stm32/build.rs | 8 +- embassy-stm32/src/dcmi.rs | 24 +- embassy-stm32/src/dma/bdma.rs | 6 +- embassy-stm32/src/dma/dma.rs | 6 +- embassy-stm32/src/dma/gpdma.rs | 4 +- embassy-stm32/src/eth/v1/mod.rs | 10 +- embassy-stm32/src/eth/v2/mod.rs | 10 +- embassy-stm32/src/exti.rs | 4 +- embassy-stm32/src/flash/asynch.rs | 10 +- embassy-stm32/src/i2c/mod.rs | 6 +- embassy-stm32/src/i2c/v1.rs | 4 +- embassy-stm32/src/i2c/v2.rs | 6 +- embassy-stm32/src/lib.rs | 51 ++--- embassy-stm32/src/sdmmc/mod.rs | 16 +- embassy-stm32/src/time_driver.rs | 2 +- embassy-stm32/src/timer/mod.rs | 6 +- embassy-stm32/src/tl_mbox/mod.rs | 18 +- embassy-stm32/src/usart/buffered.rs | 10 +- embassy-stm32/src/usart/mod.rs | 18 +- embassy-stm32/src/usb/mod.rs | 6 +- embassy-stm32/src/usb/usb.rs | 6 +- embassy-stm32/src/usb_otg/mod.rs | 10 +- embassy-stm32/src/usb_otg/usb.rs | 8 +- examples/stm32f7/build.rs | 3 +- 72 files changed, 845 insertions(+), 930 deletions(-) delete mode 100644 embassy-macros/src/macros/cortex_m_interrupt.rs delete mode 100644 embassy-macros/src/macros/cortex_m_interrupt_declare.rs delete mode 100644 embassy-rp/src/interrupt.rs diff --git a/embassy-cortex-m/src/interrupt.rs b/embassy-cortex-m/src/interrupt.rs index 0e790eaaf..8e45c36c7 100644 --- a/embassy-cortex-m/src/interrupt.rs +++ b/embassy-cortex-m/src/interrupt.rs @@ -2,120 +2,207 @@ use core::mem; use core::sync::atomic::{compiler_fence, Ordering}; +use cortex_m::interrupt::InterruptNumber; use cortex_m::peripheral::NVIC; -/// Do not use. Used for macros and HALs only. Not covered by semver guarantees. -#[doc(hidden)] -pub mod _export { - pub use atomic_polyfill as atomic; - pub use embassy_macros::{cortex_m_interrupt as interrupt, cortex_m_interrupt_declare as declare}; -} +/// Generate a standard `mod interrupt` for a HAL. +#[macro_export] +macro_rules! interrupt_mod { + ($($irqs:ident),* $(,)?) => { + pub use cortex_m_rt::interrupt; -/// Interrupt handler trait. -/// -/// Drivers that need to handle interrupts implement this trait. -/// The user must ensure `on_interrupt()` is called every time the interrupt fires. -/// Drivers must use use [`Binding`] to assert at compile time that the user has done so. -pub trait Handler { - /// Interrupt handler function. - /// - /// Must be called every time the `I` interrupt fires, synchronously from - /// the interrupt handler context. - /// - /// # Safety - /// - /// This function must ONLY be called from the interrupt handler for `I`. - unsafe fn on_interrupt(); -} + /// Interrupt definitions. + pub mod interrupt { + pub use embassy_cortex_m::interrupt::{InterruptExt, Priority}; + pub use crate::pac::interrupt::*; + pub use crate::pac::Interrupt; -/// Compile-time assertion that an interrupt has been bound to a handler. -/// -/// For the vast majority of cases, you should use the `bind_interrupts!` -/// macro instead of writing `unsafe impl`s of this trait. -/// -/// # Safety -/// -/// By implementing this trait, you are asserting that you have arranged for `H::on_interrupt()` -/// to be called every time the `I` interrupt fires. -/// -/// This allows drivers to check bindings at compile-time. -pub unsafe trait Binding> {} + /// Type-level interrupt infrastructure. + /// + /// This module contains one *type* per interrupt. This is used for checking at compile time that + /// the interrupts are correctly bound to HAL drivers. + /// + /// As an end user, you shouldn't need to use this module directly. Use the [`crate::bind_interrupts!`] macro + /// to bind interrupts, and the [`crate::interrupt`] module to manually register interrupt handlers and manipulate + /// interrupts directly (pending/unpending, enabling/disabling, setting the priority, etc...) + pub mod typelevel { + use super::InterruptExt; -#[derive(Clone, Copy)] -pub(crate) struct NrWrap(pub(crate) u16); -unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { - fn number(self) -> u16 { - self.0 - } + mod sealed { + pub trait Interrupt {} + } + + /// Type-level interrupt. + /// + /// This trait is implemented for all typelevel interrupt types in this module. + pub trait Interrupt: sealed::Interrupt { + + /// Interrupt enum variant. + /// + /// This allows going from typelevel interrupts (one type per interrupt) to + /// non-typelevel interrupts (a single `Interrupt` enum type, with one variant per interrupt). + const IRQ: super::Interrupt; + + /// Enable the interrupt. + #[inline] + unsafe fn enable() { + Self::IRQ.enable() + } + + /// Disable the interrupt. + #[inline] + fn disable() { + Self::IRQ.disable() + } + + /// Check if interrupt is enabled. + #[inline] + fn is_enabled() -> bool { + Self::IRQ.is_enabled() + } + + /// Check if interrupt is pending. + #[inline] + fn is_pending() -> bool { + Self::IRQ.is_pending() + } + + /// Set interrupt pending. + #[inline] + fn pend() { + Self::IRQ.pend() + } + + /// Unset interrupt pending. + #[inline] + fn unpend() { + Self::IRQ.unpend() + } + + /// Get the priority of the interrupt. + #[inline] + fn get_priority() -> crate::interrupt::Priority { + Self::IRQ.get_priority() + } + + /// Set the interrupt priority. + #[inline] + fn set_priority(prio: crate::interrupt::Priority) { + Self::IRQ.set_priority(prio) + } + } + + $( + #[allow(non_camel_case_types)] + #[doc=stringify!($irqs)] + #[doc=" typelevel interrupt."] + pub enum $irqs {} + impl sealed::Interrupt for $irqs{} + impl Interrupt for $irqs { + const IRQ: super::Interrupt = super::Interrupt::$irqs; + } + )* + + /// Interrupt handler trait. + /// + /// Drivers that need to handle interrupts implement this trait. + /// The user must ensure `on_interrupt()` is called every time the interrupt fires. + /// Drivers must use use [`Binding`] to assert at compile time that the user has done so. + pub trait Handler { + /// Interrupt handler function. + /// + /// Must be called every time the `I` interrupt fires, synchronously from + /// the interrupt handler context. + /// + /// # Safety + /// + /// This function must ONLY be called from the interrupt handler for `I`. + unsafe fn on_interrupt(); + } + + /// Compile-time assertion that an interrupt has been bound to a handler. + /// + /// For the vast majority of cases, you should use the `bind_interrupts!` + /// macro instead of writing `unsafe impl`s of this trait. + /// + /// # Safety + /// + /// By implementing this trait, you are asserting that you have arranged for `H::on_interrupt()` + /// to be called every time the `I` interrupt fires. + /// + /// This allows drivers to check bindings at compile-time. + pub unsafe trait Binding> {} + } + } + }; } /// Represents an interrupt type that can be configured by embassy to handle /// interrupts. -pub unsafe trait Interrupt { - /// Return the NVIC interrupt number for this interrupt. - fn number() -> u16; - +pub unsafe trait InterruptExt: InterruptNumber + Copy { /// Enable the interrupt. #[inline] - unsafe fn enable() { + unsafe fn enable(self) { compiler_fence(Ordering::SeqCst); - NVIC::unmask(NrWrap(Self::number())) + NVIC::unmask(self) } /// Disable the interrupt. #[inline] - fn disable() { - NVIC::mask(NrWrap(Self::number())); + fn disable(self) { + NVIC::mask(self); compiler_fence(Ordering::SeqCst); } /// Check if interrupt is being handled. #[inline] #[cfg(not(armv6m))] - fn is_active() -> bool { - NVIC::is_active(NrWrap(Self::number())) + fn is_active(self) -> bool { + NVIC::is_active(self) } /// Check if interrupt is enabled. #[inline] - fn is_enabled() -> bool { - NVIC::is_enabled(NrWrap(Self::number())) + fn is_enabled(self) -> bool { + NVIC::is_enabled(self) } /// Check if interrupt is pending. #[inline] - fn is_pending() -> bool { - NVIC::is_pending(NrWrap(Self::number())) + fn is_pending(self) -> bool { + NVIC::is_pending(self) } /// Set interrupt pending. #[inline] - fn pend() { - NVIC::pend(NrWrap(Self::number())) + fn pend(self) { + NVIC::pend(self) } /// Unset interrupt pending. #[inline] - fn unpend() { - NVIC::unpend(NrWrap(Self::number())) + fn unpend(self) { + NVIC::unpend(self) } /// Get the priority of the interrupt. #[inline] - fn get_priority() -> Priority { - Priority::from(NVIC::get_priority(NrWrap(Self::number()))) + fn get_priority(self) -> Priority { + Priority::from(NVIC::get_priority(self)) } /// Set the interrupt priority. #[inline] - fn set_priority(prio: Priority) { + fn set_priority(self, prio: Priority) { critical_section::with(|_| unsafe { let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); - nvic.set_priority(NrWrap(Self::number()), prio.into()) + nvic.set_priority(self, prio.into()) }) } } +unsafe impl InterruptExt for T {} + impl From for Priority { fn from(priority: u8) -> Self { unsafe { mem::transmute(priority & PRIO_MASK) } diff --git a/embassy-lora/src/iv.rs b/embassy-lora/src/iv.rs index 8d521040f..2e0b68d1a 100644 --- a/embassy-lora/src/iv.rs +++ b/embassy-lora/src/iv.rs @@ -1,7 +1,7 @@ #[cfg(feature = "stm32wl")] use embassy_stm32::interrupt; #[cfg(feature = "stm32wl")] -use embassy_stm32::interrupt::*; +use embassy_stm32::interrupt::InterruptExt; #[cfg(feature = "stm32wl")] use embassy_stm32::pac; #[cfg(feature = "stm32wl")] @@ -20,9 +20,9 @@ use lora_phy::mod_traits::InterfaceVariant; pub struct InterruptHandler {} #[cfg(feature = "stm32wl")] -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { - interrupt::SUBGHZ_RADIO::disable(); + interrupt::SUBGHZ_RADIO.disable(); IRQ_SIGNAL.signal(()); } } @@ -45,11 +45,11 @@ where { /// Create an InterfaceVariant instance for an stm32wl/sx1262 combination pub fn new( - _irq: impl interrupt::Binding, + _irq: impl interrupt::typelevel::Binding, rf_switch_rx: Option, rf_switch_tx: Option, ) -> Result { - interrupt::SUBGHZ_RADIO::disable(); + interrupt::SUBGHZ_RADIO.disable(); Ok(Self { board_type: BoardType::Stm32wlSx1262, // updated when associated with a specific LoRa board rf_switch_rx, @@ -95,7 +95,7 @@ where } async fn await_irq(&mut self) -> Result<(), RadioError> { - unsafe { interrupt::SUBGHZ_RADIO::enable() }; + unsafe { interrupt::SUBGHZ_RADIO.enable() }; IRQ_SIGNAL.wait().await; Ok(()) } diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index d7ca1f69c..ba4f13b77 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -156,16 +156,3 @@ pub fn main_wasm(args: TokenStream, item: TokenStream) -> TokenStream { let f = syn::parse_macro_input!(item as syn::ItemFn); main::run(args, f, main::wasm()).unwrap_or_else(|x| x).into() } - -#[proc_macro_attribute] -pub fn cortex_m_interrupt(args: TokenStream, item: TokenStream) -> TokenStream { - let args = syn::parse_macro_input!(args as syn::AttributeArgs); - let f = syn::parse_macro_input!(item as syn::ItemFn); - cortex_m_interrupt::run(args, f).unwrap_or_else(|x| x).into() -} - -#[proc_macro] -pub fn cortex_m_interrupt_declare(item: TokenStream) -> TokenStream { - let name = syn::parse_macro_input!(item as syn::Ident); - cortex_m_interrupt_declare::run(name).unwrap_or_else(|x| x).into() -} diff --git a/embassy-macros/src/macros/cortex_m_interrupt.rs b/embassy-macros/src/macros/cortex_m_interrupt.rs deleted file mode 100644 index 13af8ca07..000000000 --- a/embassy-macros/src/macros/cortex_m_interrupt.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::iter; - -use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::{ReturnType, Type, Visibility}; - -use crate::util::ctxt::Ctxt; - -#[derive(Debug, FromMeta)] -struct Args {} - -pub fn run(args: syn::AttributeArgs, mut f: syn::ItemFn) -> Result { - let _args = Args::from_list(&args).map_err(|e| e.write_errors())?; - - let ident = f.sig.ident.clone(); - let ident_s = ident.to_string(); - - // XXX should we blacklist other attributes? - - let valid_signature = f.sig.constness.is_none() - && f.vis == Visibility::Inherited - && f.sig.abi.is_none() - && f.sig.inputs.is_empty() - && f.sig.generics.params.is_empty() - && f.sig.generics.where_clause.is_none() - && f.sig.variadic.is_none() - && match f.sig.output { - ReturnType::Default => true, - ReturnType::Type(_, ref ty) => match **ty { - Type::Tuple(ref tuple) => tuple.elems.is_empty(), - Type::Never(..) => true, - _ => false, - }, - }; - - let ctxt = Ctxt::new(); - - if !valid_signature { - ctxt.error_spanned_by( - &f.sig, - "`#[interrupt]` handlers must have signature `[unsafe] fn() [-> !]`", - ); - } - - ctxt.check()?; - - f.block.stmts = iter::once( - syn::parse2(quote! {{ - // Check that this interrupt actually exists - let __irq_exists_check: interrupt::#ident; - }}) - .unwrap(), - ) - .chain(f.block.stmts) - .collect(); - - let result = quote!( - #[doc(hidden)] - #[export_name = #ident_s] - #[allow(non_snake_case)] - #f - ); - - Ok(result) -} diff --git a/embassy-macros/src/macros/cortex_m_interrupt_declare.rs b/embassy-macros/src/macros/cortex_m_interrupt_declare.rs deleted file mode 100644 index b317482f5..000000000 --- a/embassy-macros/src/macros/cortex_m_interrupt_declare.rs +++ /dev/null @@ -1,21 +0,0 @@ -use proc_macro2::TokenStream; -use quote::{format_ident, quote}; - -pub fn run(name: syn::Ident) -> Result { - let name = format_ident!("{}", name); - let doc = format!("{} interrupt.", name); - - let result = quote! { - #[doc = #doc] - #[allow(non_camel_case_types)] - pub enum #name{} - unsafe impl ::embassy_cortex_m::interrupt::Interrupt for #name { - fn number() -> u16 { - use cortex_m::interrupt::InterruptNumber; - let irq = InterruptEnum::#name; - irq.number() as u16 - } - } - }; - Ok(result) -} diff --git a/embassy-macros/src/macros/mod.rs b/embassy-macros/src/macros/mod.rs index a5e7a50e6..572094ca6 100644 --- a/embassy-macros/src/macros/mod.rs +++ b/embassy-macros/src/macros/mod.rs @@ -1,4 +1,2 @@ -pub mod cortex_m_interrupt; -pub mod cortex_m_interrupt_declare; pub mod main; pub mod task; diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index b4fe2d874..9bc1c1e7a 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -15,7 +15,6 @@ use core::slice; use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::atomic_ring_buffer::RingBuffer; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -24,13 +23,13 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari use crate::gpio::sealed::Pin; use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; -use crate::interrupt::{self}; +use crate::interrupt::typelevel::Interrupt; use crate::ppi::{ self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, }; use crate::timer::{Instance as TimerInstance, Timer}; use crate::uarte::{apply_workaround_for_enable_anomaly, Config, Instance as UarteInstance}; -use crate::{pac, Peripheral}; +use crate::{interrupt, pac, Peripheral}; mod sealed { use super::*; @@ -77,7 +76,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { //trace!("irq: start"); let r = U::regs(); @@ -202,7 +201,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { ppi_ch1: impl Peripheral

+ 'd, ppi_ch2: impl Peripheral

+ 'd, ppi_group: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rxd: impl Peripheral

+ 'd, txd: impl Peripheral

+ 'd, config: Config, @@ -237,7 +236,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { ppi_ch1: impl Peripheral

+ 'd, ppi_ch2: impl Peripheral

+ 'd, ppi_group: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rxd: impl Peripheral

+ 'd, txd: impl Peripheral

+ 'd, cts: impl Peripheral

+ 'd, diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs index e406c081b..8fbd760dc 100644 --- a/embassy-nrf/src/chips/nrf52805.rs +++ b/embassy-nrf/src/chips/nrf52805.rs @@ -208,33 +208,29 @@ impl_ppi_channel!(PPI_CH31, 31 => static); impl_saadc_input!(P0_04, ANALOG_INPUT2); impl_saadc_input!(P0_05, ANALOG_INPUT3); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(TWIM0_TWIS0_TWI0); - declare!(SPIM0_SPIS0_SPI0); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2); - declare!(SWI3); - declare!(SWI4); - declare!(SWI5); -} +embassy_cortex_m::interrupt_mod!( + POWER_CLOCK, + RADIO, + UARTE0_UART0, + TWIM0_TWIS0_TWI0, + SPIM0_SPIS0_SPI0, + GPIOTE, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + TEMP, + RNG, + ECB, + CCM_AAR, + WDT, + RTC1, + QDEC, + SWI0_EGU0, + SWI1_EGU1, + SWI2, + SWI3, + SWI4, + SWI5, +); diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index 153795e54..bbf8f7ccf 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -234,36 +234,32 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5); impl_saadc_input!(P0_30, ANALOG_INPUT6); impl_saadc_input!(P0_31, ANALOG_INPUT7); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(TWIM0_TWIS0_TWI0); - declare!(SPIM0_SPIS0_SPI0); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2); - declare!(SWI3); - declare!(SWI4); - declare!(SWI5); - declare!(PWM0); - declare!(PDM); -} +embassy_cortex_m::interrupt_mod!( + POWER_CLOCK, + RADIO, + UARTE0_UART0, + TWIM0_TWIS0_TWI0, + SPIM0_SPIS0_SPI0, + GPIOTE, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + TEMP, + RNG, + ECB, + CCM_AAR, + WDT, + RTC1, + QDEC, + COMP, + SWI0_EGU0, + SWI1_EGU1, + SWI2, + SWI3, + SWI4, + SWI5, + PWM0, + PDM, +); diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index a7a7cf58c..31a8dd6af 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -236,36 +236,32 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5); impl_saadc_input!(P0_30, ANALOG_INPUT6); impl_saadc_input!(P0_31, ANALOG_INPUT7); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); - declare!(SPIM1_SPIS1_SPI1); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2); - declare!(SWI3); - declare!(SWI4); - declare!(SWI5); - declare!(PWM0); - declare!(PDM); -} +embassy_cortex_m::interrupt_mod!( + POWER_CLOCK, + RADIO, + UARTE0_UART0, + TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0, + SPIM1_SPIS1_SPI1, + GPIOTE, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + TEMP, + RNG, + ECB, + CCM_AAR, + WDT, + RTC1, + QDEC, + COMP, + SWI0_EGU0, + SWI1_EGU1, + SWI2, + SWI3, + SWI4, + SWI5, + PWM0, + PDM, +); diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs index 14a1b8cc9..6a6f4fcf2 100644 --- a/embassy-nrf/src/chips/nrf52820.rs +++ b/embassy-nrf/src/chips/nrf52820.rs @@ -224,35 +224,31 @@ impl_ppi_channel!(PPI_CH29, 29 => static); impl_ppi_channel!(PPI_CH30, 30 => static); impl_ppi_channel!(PPI_CH31, 31 => static); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); - declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); - declare!(GPIOTE); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2_EGU2); - declare!(SWI3_EGU3); - declare!(SWI4_EGU4); - declare!(SWI5_EGU5); - declare!(TIMER3); - declare!(USBD); -} +embassy_cortex_m::interrupt_mod!( + POWER_CLOCK, + RADIO, + UARTE0_UART0, + SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0, + SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1, + GPIOTE, + TIMER0, + TIMER1, + TIMER2, + RTC0, + TEMP, + RNG, + ECB, + CCM_AAR, + WDT, + RTC1, + QDEC, + COMP, + SWI0_EGU0, + SWI1_EGU1, + SWI2_EGU2, + SWI3_EGU3, + SWI4_EGU4, + SWI5_EGU5, + TIMER3, + USBD, +); diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index 83ecd0deb..e43b3d5b2 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -263,46 +263,42 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); - declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); - declare!(NFCT); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP_LPCOMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2_EGU2); - declare!(SWI3_EGU3); - declare!(SWI4_EGU4); - declare!(SWI5_EGU5); - declare!(TIMER3); - declare!(TIMER4); - declare!(PWM0); - declare!(PDM); - declare!(MWU); - declare!(PWM1); - declare!(PWM2); - declare!(SPIM2_SPIS2_SPI2); - declare!(RTC2); - declare!(FPU); - declare!(I2S); -} +embassy_cortex_m::interrupt_mod!( + POWER_CLOCK, + RADIO, + UARTE0_UART0, + SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0, + SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1, + NFCT, + GPIOTE, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + TEMP, + RNG, + ECB, + CCM_AAR, + WDT, + RTC1, + QDEC, + COMP_LPCOMP, + SWI0_EGU0, + SWI1_EGU1, + SWI2_EGU2, + SWI3_EGU3, + SWI4_EGU4, + SWI5_EGU5, + TIMER3, + TIMER4, + PWM0, + PDM, + MWU, + PWM1, + PWM2, + SPIM2_SPIS2_SPI2, + RTC2, + FPU, + I2S, +); diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index 5e5db04de..d95e3497c 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -306,50 +306,46 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); - declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); - declare!(NFCT); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP_LPCOMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2_EGU2); - declare!(SWI3_EGU3); - declare!(SWI4_EGU4); - declare!(SWI5_EGU5); - declare!(TIMER3); - declare!(TIMER4); - declare!(PWM0); - declare!(PDM); - declare!(MWU); - declare!(PWM1); - declare!(PWM2); - declare!(SPIM2_SPIS2_SPI2); - declare!(RTC2); - declare!(FPU); - declare!(USBD); - declare!(UARTE1); - declare!(PWM3); - declare!(SPIM3); - declare!(I2S); -} +embassy_cortex_m::interrupt_mod!( + POWER_CLOCK, + RADIO, + UARTE0_UART0, + SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0, + SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1, + NFCT, + GPIOTE, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + TEMP, + RNG, + ECB, + CCM_AAR, + WDT, + RTC1, + QDEC, + COMP_LPCOMP, + SWI0_EGU0, + SWI1_EGU1, + SWI2_EGU2, + SWI3_EGU3, + SWI4_EGU4, + SWI5_EGU5, + TIMER3, + TIMER4, + PWM0, + PDM, + MWU, + PWM1, + PWM2, + SPIM2_SPIS2_SPI2, + RTC2, + FPU, + USBD, + UARTE1, + PWM3, + SPIM3, + I2S, +); diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index f6d33f85c..0094b1220 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -311,52 +311,48 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); - declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); - declare!(NFCT); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP_LPCOMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2_EGU2); - declare!(SWI3_EGU3); - declare!(SWI4_EGU4); - declare!(SWI5_EGU5); - declare!(TIMER3); - declare!(TIMER4); - declare!(PWM0); - declare!(PDM); - declare!(MWU); - declare!(PWM1); - declare!(PWM2); - declare!(SPIM2_SPIS2_SPI2); - declare!(RTC2); - declare!(FPU); - declare!(USBD); - declare!(UARTE1); - declare!(QSPI); - declare!(CRYPTOCELL); - declare!(PWM3); - declare!(SPIM3); - declare!(I2S); -} +embassy_cortex_m::interrupt_mod!( + POWER_CLOCK, + RADIO, + UARTE0_UART0, + SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0, + SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1, + NFCT, + GPIOTE, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + TEMP, + RNG, + ECB, + CCM_AAR, + WDT, + RTC1, + QDEC, + COMP_LPCOMP, + SWI0_EGU0, + SWI1_EGU1, + SWI2_EGU2, + SWI3_EGU3, + SWI4_EGU4, + SWI5_EGU5, + TIMER3, + TIMER4, + PWM0, + PDM, + MWU, + PWM1, + PWM2, + SPIM2_SPIS2_SPI2, + RTC2, + FPU, + USBD, + UARTE1, + QSPI, + CRYPTOCELL, + PWM3, + SPIM3, + I2S, +); diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs index 34f96800f..c10520051 100644 --- a/embassy-nrf/src/chips/nrf5340_app.rs +++ b/embassy-nrf/src/chips/nrf5340_app.rs @@ -504,50 +504,46 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5); impl_saadc_input!(P0_19, ANALOG_INPUT6); impl_saadc_input!(P0_20, ANALOG_INPUT7); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(FPU); - declare!(CACHE); - declare!(SPU); - declare!(CLOCK_POWER); - declare!(SERIAL0); - declare!(SERIAL1); - declare!(SPIM4); - declare!(SERIAL2); - declare!(SERIAL3); - declare!(GPIOTE0); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(RTC1); - declare!(WDT0); - declare!(WDT1); - declare!(COMP_LPCOMP); - declare!(EGU0); - declare!(EGU1); - declare!(EGU2); - declare!(EGU3); - declare!(EGU4); - declare!(EGU5); - declare!(PWM0); - declare!(PWM1); - declare!(PWM2); - declare!(PWM3); - declare!(PDM0); - declare!(I2S0); - declare!(IPC); - declare!(QSPI); - declare!(NFCT); - declare!(GPIOTE1); - declare!(QDEC0); - declare!(QDEC1); - declare!(USBD); - declare!(USBREGULATOR); - declare!(KMU); - declare!(CRYPTOCELL); -} +embassy_cortex_m::interrupt_mod!( + FPU, + CACHE, + SPU, + CLOCK_POWER, + SERIAL0, + SERIAL1, + SPIM4, + SERIAL2, + SERIAL3, + GPIOTE0, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + RTC1, + WDT0, + WDT1, + COMP_LPCOMP, + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, + PWM0, + PWM1, + PWM2, + PWM3, + PDM0, + I2S0, + IPC, + QSPI, + NFCT, + GPIOTE1, + QDEC0, + QDEC1, + USBD, + USBREGULATOR, + KMU, + CRYPTOCELL, +); diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs index 1e59528cb..a6fb1d4cc 100644 --- a/embassy-nrf/src/chips/nrf5340_net.rs +++ b/embassy-nrf/src/chips/nrf5340_net.rs @@ -340,29 +340,25 @@ impl_ppi_channel!(PPI_CH29, 29 => configurable); impl_ppi_channel!(PPI_CH30, 30 => configurable); impl_ppi_channel!(PPI_CH31, 31 => configurable); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(CLOCK_POWER); - declare!(RADIO); - declare!(RNG); - declare!(GPIOTE); - declare!(WDT); - declare!(TIMER0); - declare!(ECB); - declare!(AAR_CCM); - declare!(TEMP); - declare!(RTC0); - declare!(IPC); - declare!(SERIAL0); - declare!(EGU0); - declare!(RTC1); - declare!(TIMER1); - declare!(TIMER2); - declare!(SWI0); - declare!(SWI1); - declare!(SWI2); - declare!(SWI3); -} +embassy_cortex_m::interrupt_mod!( + CLOCK_POWER, + RADIO, + RNG, + GPIOTE, + WDT, + TIMER0, + ECB, + AAR_CCM, + TEMP, + RTC0, + IPC, + SERIAL0, + EGU0, + RTC1, + TIMER1, + TIMER2, + SWI0, + SWI1, + SWI2, + SWI3, +); diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs index d2b45114f..b6ae78bbe 100644 --- a/embassy-nrf/src/chips/nrf9160.rs +++ b/embassy-nrf/src/chips/nrf9160.rs @@ -366,40 +366,36 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5); impl_saadc_input!(P0_19, ANALOG_INPUT6); impl_saadc_input!(P0_20, ANALOG_INPUT7); -pub mod irqs { - use embassy_cortex_m::interrupt::_export::declare; - - use crate::pac::Interrupt as InterruptEnum; - - declare!(SPU); - declare!(CLOCK_POWER); - declare!(UARTE0_SPIM0_SPIS0_TWIM0_TWIS0); - declare!(UARTE1_SPIM1_SPIS1_TWIM1_TWIS1); - declare!(UARTE2_SPIM2_SPIS2_TWIM2_TWIS2); - declare!(UARTE3_SPIM3_SPIS3_TWIM3_TWIS3); - declare!(GPIOTE0); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(RTC1); - declare!(WDT); - declare!(EGU0); - declare!(EGU1); - declare!(EGU2); - declare!(EGU3); - declare!(EGU4); - declare!(EGU5); - declare!(PWM0); - declare!(PWM1); - declare!(PWM2); - declare!(PDM); - declare!(PWM3); - declare!(I2S); - declare!(IPC); - declare!(FPU); - declare!(GPIOTE1); - declare!(KMU); - declare!(CRYPTOCELL); -} +embassy_cortex_m::interrupt_mod!( + SPU, + CLOCK_POWER, + UARTE0_SPIM0_SPIS0_TWIM0_TWIS0, + UARTE1_SPIM1_SPIS1_TWIM1_TWIS1, + UARTE2_SPIM2_SPIS2_TWIM2_TWIS2, + UARTE3_SPIM3_SPIS3_TWIM3_TWIS3, + GPIOTE0, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + RTC1, + WDT, + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, + PWM0, + PWM1, + PWM2, + PDM, + PWM3, + I2S, + IPC, + FPU, + GPIOTE1, + KMU, + CRYPTOCELL, +); diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 2ec5220a7..1d7725bd3 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -9,7 +9,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin}; -use crate::interrupt::Interrupt; +use crate::interrupt::InterruptExt; use crate::ppi::{Event, Task}; use crate::{interrupt, pac, peripherals}; @@ -75,15 +75,15 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) { // Enable interrupts #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))] - type Irq = interrupt::GPIOTE0; + let irq = interrupt::GPIOTE0; #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))] - type Irq = interrupt::GPIOTE1; + let irq = interrupt::GPIOTE1; #[cfg(any(feature = "_nrf52", feature = "nrf5340-net"))] - type Irq = interrupt::GPIOTE; + let irq = interrupt::GPIOTE; - Irq::unpend(); - Irq::set_priority(irq_prio); - unsafe { Irq::enable() }; + irq.unpend(); + irq.set_priority(irq_prio); + unsafe { irq.enable() }; let g = regs(); g.events_port.write(|w| w); diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs index 13db77d3b..fea38c4c0 100644 --- a/embassy-nrf/src/i2s.rs +++ b/embassy-nrf/src/i2s.rs @@ -13,10 +13,10 @@ use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use crate::gpio::{AnyPin, Pin as GpioPin}; -use crate::interrupt::{self, Interrupt}; +use crate::interrupt::typelevel::Interrupt; use crate::pac::i2s::RegisterBlock; use crate::util::{slice_in_ram_or, slice_ptr_parts}; -use crate::{Peripheral, EASY_DMA_SIZE}; +use crate::{interrupt, Peripheral, EASY_DMA_SIZE}; /// Type alias for `MultiBuffering` with 2 buffers. pub type DoubleBuffering = MultiBuffering; @@ -367,7 +367,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let device = Device::::new(); let s = T::state(); @@ -408,7 +408,7 @@ impl<'d, T: Instance> I2S<'d, T> { /// Create a new I2S in master mode pub fn new_master( i2s: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, mck: impl Peripheral

+ 'd, sck: impl Peripheral

+ 'd, lrck: impl Peripheral

+ 'd, @@ -431,7 +431,7 @@ impl<'d, T: Instance> I2S<'d, T> { /// Create a new I2S in slave mode pub fn new_slave( i2s: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, sck: impl Peripheral

+ 'd, lrck: impl Peripheral

+ 'd, config: Config, @@ -1173,7 +1173,7 @@ pub(crate) mod sealed { /// I2S peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_i2s { @@ -1188,7 +1188,7 @@ macro_rules! impl_i2s { } } impl crate::i2s::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 6b57c2545..a73d22a63 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -93,21 +93,16 @@ pub mod wdt; #[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")] mod chip; -pub mod interrupt { - //! Interrupt definitions and macros to bind them. - pub use cortex_m::interrupt::{CriticalSection, Mutex}; - pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, Priority}; +pub use crate::chip::interrupt; - pub use crate::chip::irqs::*; - - /// Macro to bind interrupts to handlers. - /// - /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) - /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to - /// prove at compile-time that the right interrupts have been bound. - // developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. - #[macro_export] - macro_rules! bind_interrupts { +/// Macro to bind interrupts to handlers. +/// +/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) +/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to +/// prove at compile-time that the right interrupts have been bound. +// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. +#[macro_export] +macro_rules! bind_interrupts { ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { $vis struct $name; @@ -116,17 +111,16 @@ pub mod interrupt { #[no_mangle] unsafe extern "C" fn $irq() { $( - <$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt(); + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); )* } $( - unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {} + unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {} )* )* }; } -} // Reexports @@ -136,7 +130,6 @@ pub use chip::pac; pub(crate) use chip::pac; pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE}; pub use embassy_cortex_m::executor; -pub use embassy_cortex_m::interrupt::_export::interrupt; pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; pub mod config { diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 9df685a26..0e30f7002 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -6,7 +6,6 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use futures::future::poll_fn; @@ -14,15 +13,15 @@ use futures::future::poll_fn; use crate::chip::EASY_DMA_SIZE; use crate::gpio::sealed::Pin; use crate::gpio::{AnyPin, Pin as GpioPin}; -use crate::interrupt::{self}; -use crate::Peripheral; +use crate::interrupt::typelevel::Interrupt; +use crate::{interrupt, Peripheral}; /// Interrupt handler. pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { T::regs().intenclr.write(|w| w.end().clear()); T::state().waker.wake(); @@ -53,7 +52,7 @@ impl<'d, T: Instance> Pdm<'d, T> { /// Create PDM driver pub fn new( pdm: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, clk: impl Peripheral

+ 'd, din: impl Peripheral

+ 'd, config: Config, @@ -274,7 +273,7 @@ pub(crate) mod sealed { /// PDM peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_pdm { @@ -289,7 +288,7 @@ macro_rules! impl_pdm { } } impl crate::pdm::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 708f23104..363a255d5 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -8,10 +8,9 @@ use embassy_hal_common::{into_ref, PeripheralRef}; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Pin as GpioPin, PselBits}; -use crate::interrupt::Interrupt; use crate::ppi::{Event, Task}; use crate::util::slice_in_ram_or; -use crate::{pac, Peripheral}; +use crate::{interrupt, pac, Peripheral}; /// SimplePwm is the traditional pwm interface you're probably used to, allowing /// to simply set a duty cycle across up to four channels. @@ -843,7 +842,7 @@ pub(crate) mod sealed { /// PWM peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_pwm { @@ -854,7 +853,7 @@ macro_rules! impl_pwm { } } impl crate::pwm::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs index 5761d04e1..8bac87d37 100644 --- a/embassy-nrf/src/qdec.rs +++ b/embassy-nrf/src/qdec.rs @@ -10,7 +10,7 @@ use embassy_hal_common::{into_ref, PeripheralRef}; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Pin as GpioPin}; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::{interrupt, Peripheral}; /// Quadrature decoder driver. @@ -50,7 +50,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { T::regs().intenclr.write(|w| w.reportrdy().clear()); T::state().waker.wake(); @@ -61,7 +61,7 @@ impl<'d, T: Instance> Qdec<'d, T> { /// Create a new QDEC. pub fn new( qdec: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, a: impl Peripheral

+ 'd, b: impl Peripheral

+ 'd, config: Config, @@ -73,7 +73,7 @@ impl<'d, T: Instance> Qdec<'d, T> { /// Create a new QDEC, with a pin for LED output. pub fn new_with_led( qdec: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, a: impl Peripheral

+ 'd, b: impl Peripheral

+ 'd, led: impl Peripheral

+ 'd, @@ -271,7 +271,7 @@ pub(crate) mod sealed { /// qdec peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_qdec { @@ -286,7 +286,7 @@ macro_rules! impl_qdec { } } impl crate::qdec::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index 3f48568b3..baefc7967 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs @@ -12,12 +12,12 @@ use embassy_hal_common::{into_ref, PeripheralRef}; use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; use crate::gpio::{self, Pin as GpioPin}; -use crate::interrupt::{self, Interrupt}; +use crate::interrupt::typelevel::Interrupt; pub use crate::pac::qspi::ifconfig0::{ ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode, }; pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode; -use crate::Peripheral; +use crate::{interrupt, Peripheral}; /// Deep power-down config. pub struct DeepPowerDownConfig { @@ -120,7 +120,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); let s = T::state(); @@ -143,7 +143,7 @@ impl<'d, T: Instance> Qspi<'d, T> { /// Create a new QSPI driver. pub fn new( qspi: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, sck: impl Peripheral

+ 'd, csn: impl Peripheral

+ 'd, io0: impl Peripheral

+ 'd, @@ -644,7 +644,7 @@ pub(crate) mod sealed { /// QSPI peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_qspi { @@ -659,7 +659,7 @@ macro_rules! impl_qspi { } } impl crate::qspi::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index 7e9b35481..923b8b467 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs @@ -12,7 +12,7 @@ use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -20,7 +20,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let s = T::state(); let r = T::regs(); @@ -89,7 +89,7 @@ impl<'d, T: Instance> Rng<'d, T> { /// The synchronous API is safe. pub fn new( rng: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, ) -> Self { into_ref!(rng); @@ -255,7 +255,7 @@ pub(crate) mod sealed { /// RNG peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_rng { @@ -270,7 +270,7 @@ macro_rules! impl_rng { } } impl crate::rng::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index 39764e380..cf3fb9993 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -6,7 +6,6 @@ use core::future::poll_fn; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -18,6 +17,7 @@ use saadc::oversample::OVERSAMPLE_A; use saadc::resolution::VAL_A; use self::sealed::Input as _; +use crate::interrupt::InterruptExt; use crate::ppi::{ConfigurableChannel, Event, Ppi, Task}; use crate::timer::{Frequency, Instance as TimerInstance, Timer}; use crate::{interrupt, pac, peripherals, Peripheral}; @@ -33,7 +33,7 @@ pub struct InterruptHandler { _private: (), } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = unsafe { &*SAADC::ptr() }; @@ -144,7 +144,7 @@ impl<'d, const N: usize> Saadc<'d, N> { /// Create a new SAADC driver. pub fn new( saadc: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding + 'd, + _irq: impl interrupt::typelevel::Binding + 'd, config: Config, channel_configs: [ChannelConfig; N], ) -> Self { @@ -189,8 +189,8 @@ impl<'d, const N: usize> Saadc<'d, N> { // Disable all events interrupts r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); - interrupt::SAADC::unpend(); - unsafe { interrupt::SAADC::enable() }; + interrupt::SAADC.unpend(); + unsafe { interrupt::SAADC.enable() }; Self { _p: saadc } } diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index bb9cda323..66bbd1a8f 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -15,9 +15,9 @@ pub use pac::spim0::frequency::FREQUENCY_A as Frequency; use crate::chip::FORCE_COPY_BUFFER_SIZE; use crate::gpio::sealed::Pin as _; use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; -use crate::interrupt::{self, Interrupt}; +use crate::interrupt::typelevel::Interrupt; use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; -use crate::{pac, Peripheral}; +use crate::{interrupt, pac, Peripheral}; /// SPIM error #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -63,7 +63,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); let s = T::state(); @@ -84,7 +84,7 @@ impl<'d, T: Instance> Spim<'d, T> { /// Create a new SPIM driver. pub fn new( spim: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, sck: impl Peripheral

+ 'd, miso: impl Peripheral

+ 'd, mosi: impl Peripheral

+ 'd, @@ -103,7 +103,7 @@ impl<'d, T: Instance> Spim<'d, T> { /// Create a new SPIM driver, capable of TX only (MOSI only). pub fn new_txonly( spim: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, sck: impl Peripheral

+ 'd, mosi: impl Peripheral

+ 'd, config: Config, @@ -115,7 +115,7 @@ impl<'d, T: Instance> Spim<'d, T> { /// Create a new SPIM driver, capable of RX only (MISO only). pub fn new_rxonly( spim: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, sck: impl Peripheral

+ 'd, miso: impl Peripheral

+ 'd, config: Config, @@ -408,7 +408,7 @@ pub(crate) mod sealed { /// SPIM peripheral instance pub trait Instance: Peripheral

+ sealed::Instance + 'static { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_spim { @@ -423,7 +423,7 @@ macro_rules! impl_spim { } } impl crate::spim::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs index a1d6803ed..aa438415a 100644 --- a/embassy-nrf/src/spis.rs +++ b/embassy-nrf/src/spis.rs @@ -13,9 +13,9 @@ pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MO use crate::chip::FORCE_COPY_BUFFER_SIZE; use crate::gpio::sealed::Pin as _; use crate::gpio::{self, AnyPin, Pin as GpioPin}; -use crate::interrupt::{self, Interrupt}; +use crate::interrupt::typelevel::Interrupt; use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; -use crate::{pac, Peripheral}; +use crate::{interrupt, pac, Peripheral}; /// SPIS error #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -68,7 +68,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); let s = T::state(); @@ -94,7 +94,7 @@ impl<'d, T: Instance> Spis<'d, T> { /// Create a new SPIS driver. pub fn new( spis: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, cs: impl Peripheral

+ 'd, sck: impl Peripheral

+ 'd, miso: impl Peripheral

+ 'd, @@ -115,7 +115,7 @@ impl<'d, T: Instance> Spis<'d, T> { /// Create a new SPIS driver, capable of TX only (MISO only). pub fn new_txonly( spis: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, cs: impl Peripheral

+ 'd, sck: impl Peripheral

+ 'd, miso: impl Peripheral

+ 'd, @@ -128,7 +128,7 @@ impl<'d, T: Instance> Spis<'d, T> { /// Create a new SPIS driver, capable of RX only (MOSI only). pub fn new_rxonly( spis: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, cs: impl Peripheral

+ 'd, sck: impl Peripheral

+ 'd, mosi: impl Peripheral

+ 'd, @@ -480,7 +480,7 @@ pub(crate) mod sealed { /// SPIS peripheral instance pub trait Instance: Peripheral

+ sealed::Instance + 'static { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_spis { @@ -495,7 +495,7 @@ macro_rules! impl_spis { } } impl crate::spis::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs index 8a127efc5..491e92c04 100644 --- a/embassy-nrf/src/temp.rs +++ b/embassy-nrf/src/temp.rs @@ -8,7 +8,7 @@ use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use fixed::types::I30F2; -use crate::interrupt::Interrupt; +use crate::interrupt::InterruptExt; use crate::peripherals::TEMP; use crate::{interrupt, pac, Peripheral}; @@ -17,7 +17,7 @@ pub struct InterruptHandler { _private: (), } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = unsafe { &*pac::TEMP::PTR }; r.intenclr.write(|w| w.datardy().clear()); @@ -36,13 +36,13 @@ impl<'d> Temp<'d> { /// Create a new temperature sensor driver. pub fn new( _peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding + 'd, + _irq: impl interrupt::typelevel::Binding + 'd, ) -> Self { into_ref!(_peri); // Enable interrupt that signals temperature values - interrupt::TEMP::unpend(); - unsafe { interrupt::TEMP::enable() }; + interrupt::TEMP.unpend(); + unsafe { interrupt::TEMP.enable() }; Self { _peri } } diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs index 4feff8a75..f993d7b2e 100644 --- a/embassy-nrf/src/time_driver.rs +++ b/embassy-nrf/src/time_driver.rs @@ -7,7 +7,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; use embassy_time::driver::{AlarmHandle, Driver}; -use crate::interrupt::Interrupt; +use crate::interrupt::InterruptExt; use crate::{interrupt, pac}; fn rtc() -> &'static pac::rtc0::RegisterBlock { @@ -142,8 +142,8 @@ impl RtcDriver { // Wait for clear while r.counter.read().bits() != 0 {} - interrupt::RTC1::set_priority(irq_prio); - unsafe { interrupt::RTC1::enable() }; + interrupt::RTC1.set_priority(irq_prio); + unsafe { interrupt::RTC1.enable() }; } fn on_interrupt(&self) { diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index 2a0e16a50..dc3757856 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -8,7 +8,6 @@ use embassy_hal_common::{into_ref, PeripheralRef}; -use crate::interrupt::Interrupt; use crate::ppi::{Event, Task}; use crate::{pac, Peripheral}; @@ -29,7 +28,7 @@ pub(crate) mod sealed { /// Basic Timer instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: crate::interrupt::typelevel::Interrupt; } /// Extended timer instance. @@ -44,7 +43,7 @@ macro_rules! impl_timer { } } impl crate::timer::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; ($type:ident, $pac_type:ident, $irq:ident) => { diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs index dea398a67..2ad0d19b1 100644 --- a/embassy-nrf/src/twim.rs +++ b/embassy-nrf/src/twim.rs @@ -16,9 +16,9 @@ use embassy_time::{Duration, Instant}; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::gpio::Pin as GpioPin; -use crate::interrupt::{self, Interrupt}; +use crate::interrupt::typelevel::Interrupt; use crate::util::{slice_in_ram, slice_in_ram_or}; -use crate::{gpio, pac, Peripheral}; +use crate::{gpio, interrupt, pac, Peripheral}; /// TWI frequency #[derive(Clone, Copy)] @@ -98,7 +98,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); let s = T::state(); @@ -123,7 +123,7 @@ impl<'d, T: Instance> Twim<'d, T> { /// Create a new TWI driver. pub fn new( twim: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, sda: impl Peripheral

+ 'd, scl: impl Peripheral

+ 'd, config: Config, @@ -750,7 +750,7 @@ pub(crate) mod sealed { /// TWIM peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_twim { @@ -765,7 +765,7 @@ macro_rules! impl_twim { } } impl crate::twim::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs index 752a8c046..a115d5616 100644 --- a/embassy-nrf/src/twis.rs +++ b/embassy-nrf/src/twis.rs @@ -15,9 +15,9 @@ use embassy_time::{Duration, Instant}; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::gpio::Pin as GpioPin; -use crate::interrupt::{self, Interrupt}; +use crate::interrupt::typelevel::Interrupt; use crate::util::slice_in_ram_or; -use crate::{gpio, pac, Peripheral}; +use crate::{gpio, interrupt, pac, Peripheral}; /// TWIS config. #[non_exhaustive] @@ -114,7 +114,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); let s = T::state(); @@ -143,7 +143,7 @@ impl<'d, T: Instance> Twis<'d, T> { /// Create a new TWIS driver. pub fn new( twis: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, sda: impl Peripheral

+ 'd, scl: impl Peripheral

+ 'd, config: Config, @@ -778,7 +778,7 @@ pub(crate) mod sealed { /// TWIS peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_twis { @@ -793,7 +793,7 @@ macro_rules! impl_twis { } } impl crate::twis::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 6c6941ee8..85a951ae0 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -27,11 +27,11 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::gpio::sealed::Pin as _; use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; -use crate::interrupt::{self, Interrupt}; +use crate::interrupt::typelevel::Interrupt; use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; use crate::timer::{Frequency, Instance as TimerInstance, Timer}; use crate::util::slice_in_ram_or; -use crate::{pac, Peripheral}; +use crate::{interrupt, pac, Peripheral}; /// UARTE config. #[derive(Clone)] @@ -68,7 +68,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); let s = T::state(); @@ -108,7 +108,7 @@ impl<'d, T: Instance> Uarte<'d, T> { /// Create a new UARTE without hardware flow control pub fn new( uarte: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rxd: impl Peripheral

+ 'd, txd: impl Peripheral

+ 'd, config: Config, @@ -120,7 +120,7 @@ impl<'d, T: Instance> Uarte<'d, T> { /// Create a new UARTE with hardware flow control (RTS/CTS) pub fn new_with_rtscts( uarte: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rxd: impl Peripheral

+ 'd, txd: impl Peripheral

+ 'd, cts: impl Peripheral

+ 'd, @@ -313,7 +313,7 @@ impl<'d, T: Instance> UarteTx<'d, T> { /// Create a new tx-only UARTE without hardware flow control pub fn new( uarte: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, txd: impl Peripheral

+ 'd, config: Config, ) -> Self { @@ -324,7 +324,7 @@ impl<'d, T: Instance> UarteTx<'d, T> { /// Create a new tx-only UARTE with hardware flow control (RTS/CTS) pub fn new_with_rtscts( uarte: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, txd: impl Peripheral

+ 'd, cts: impl Peripheral

+ 'd, config: Config, @@ -509,7 +509,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { /// Create a new rx-only UARTE without hardware flow control pub fn new( uarte: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rxd: impl Peripheral

+ 'd, config: Config, ) -> Self { @@ -520,7 +520,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { /// Create a new rx-only UARTE with hardware flow control (RTS/CTS) pub fn new_with_rtscts( uarte: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rxd: impl Peripheral

+ 'd, rts: impl Peripheral

+ 'd, config: Config, @@ -889,7 +889,7 @@ pub(crate) mod sealed { /// UARTE peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_uarte { @@ -908,7 +908,7 @@ macro_rules! impl_uarte { } } impl crate::uarte::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/usb/mod.rs b/embassy-nrf/src/usb/mod.rs index 3c62b4452..76cf40ac7 100644 --- a/embassy-nrf/src/usb/mod.rs +++ b/embassy-nrf/src/usb/mod.rs @@ -18,9 +18,9 @@ use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo use pac::usbd::RegisterBlock; use self::vbus_detect::VbusDetect; -use crate::interrupt::{self, Interrupt}; +use crate::interrupt::typelevel::Interrupt; use crate::util::slice_in_ram; -use crate::{pac, Peripheral}; +use crate::{interrupt, pac, Peripheral}; const NEW_AW: AtomicWaker = AtomicWaker::new(); static BUS_WAKER: AtomicWaker = NEW_AW; @@ -34,7 +34,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let regs = T::regs(); @@ -98,7 +98,7 @@ impl<'d, T: Instance, V: VbusDetect> Driver<'d, T, V> { /// Create a new USB driver. pub fn new( usb: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, vbus_detect: V, ) -> Self { into_ref!(usb); @@ -804,7 +804,7 @@ pub(crate) mod sealed { /// USB peripheral instance. pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { /// Interrupt for this peripheral. - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } macro_rules! impl_usb { @@ -815,7 +815,7 @@ macro_rules! impl_usb { } } impl crate::usb::Instance for peripherals::$type { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-nrf/src/usb/vbus_detect.rs b/embassy-nrf/src/usb/vbus_detect.rs index a6a959905..a05e5aa52 100644 --- a/embassy-nrf/src/usb/vbus_detect.rs +++ b/embassy-nrf/src/usb/vbus_detect.rs @@ -7,8 +7,8 @@ use core::task::Poll; use embassy_sync::waitqueue::AtomicWaker; use super::BUS_WAKER; -use crate::interrupt::{self, Interrupt}; -use crate::pac; +use crate::interrupt::typelevel::Interrupt; +use crate::{interrupt, pac}; /// Trait for detecting USB VBUS power. /// @@ -29,9 +29,9 @@ pub trait VbusDetect { } #[cfg(not(feature = "_nrf5340"))] -type UsbRegIrq = interrupt::POWER_CLOCK; +type UsbRegIrq = interrupt::typelevel::POWER_CLOCK; #[cfg(feature = "_nrf5340")] -type UsbRegIrq = interrupt::USBREGULATOR; +type UsbRegIrq = interrupt::typelevel::USBREGULATOR; #[cfg(not(feature = "_nrf5340"))] type UsbRegPeri = pac::POWER; @@ -43,7 +43,7 @@ pub struct InterruptHandler { _private: (), } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let regs = unsafe { &*UsbRegPeri::ptr() }; @@ -77,7 +77,7 @@ static POWER_WAKER: AtomicWaker = AtomicWaker::new(); impl HardwareVbusDetect { /// Create a new `VbusDetectNative`. - pub fn new(_irq: impl interrupt::Binding + 'static) -> Self { + pub fn new(_irq: impl interrupt::typelevel::Binding + 'static) -> Self { let regs = unsafe { &*UsbRegPeri::ptr() }; UsbRegIrq::unpend(); diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 86a353670..f29c4dfe1 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -3,14 +3,14 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::{Binding, Interrupt}; use embassy_sync::waitqueue::AtomicWaker; use embedded_hal_02::adc::{Channel, OneShot}; use crate::gpio::Pin; -use crate::interrupt::{self, ADC_IRQ_FIFO}; +use crate::interrupt::typelevel::Binding; +use crate::interrupt::InterruptExt; use crate::peripherals::ADC; -use crate::{pac, peripherals, Peripheral}; +use crate::{interrupt, pac, peripherals, Peripheral}; static WAKER: AtomicWaker = AtomicWaker::new(); #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -47,7 +47,7 @@ impl<'d> Adc<'d> { pub fn new( _inner: impl Peripheral

+ 'd, - _irq: impl Binding, + _irq: impl Binding, _config: Config, ) -> Self { unsafe { @@ -62,10 +62,8 @@ impl<'d> Adc<'d> { } // Setup IRQ - unsafe { - ADC_IRQ_FIFO::unpend(); - ADC_IRQ_FIFO::enable(); - }; + interrupt::ADC_IRQ_FIFO.unpend(); + unsafe { interrupt::ADC_IRQ_FIFO.enable() }; Self { phantom: PhantomData } } @@ -164,7 +162,7 @@ pub struct InterruptHandler { _empty: (), } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = Adc::regs(); r.inte().write(|w| w.set_fifo(false)); diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 1cbb4651a..042ca99a9 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -4,11 +4,11 @@ use core::pin::Pin; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use pac::dma::vals::DataSize; +use crate::interrupt::InterruptExt; use crate::pac::dma::vals; use crate::{interrupt, pac, peripherals}; @@ -29,12 +29,12 @@ unsafe fn DMA_IRQ_0() { } pub(crate) unsafe fn init() { - interrupt::DMA_IRQ_0::disable(); - interrupt::DMA_IRQ_0::set_priority(interrupt::Priority::P3); + interrupt::DMA_IRQ_0.disable(); + interrupt::DMA_IRQ_0.set_priority(interrupt::Priority::P3); pac::DMA.inte0().write(|w| w.set_inte0(0xFFFF)); - interrupt::DMA_IRQ_0::enable(); + interrupt::DMA_IRQ_0.enable(); } pub unsafe fn read<'a, C: Channel, W: Word>( diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 91cef8609..ebd932f50 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -3,10 +3,10 @@ use core::future::Future; use core::pin::Pin as FuturePin; use core::task::{Context, Poll}; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; +use crate::interrupt::InterruptExt; use crate::pac::common::{Reg, RW}; use crate::pac::SIO; use crate::{interrupt, pac, peripherals, Peripheral, RegExt}; @@ -137,9 +137,9 @@ pub enum InterruptTrigger { } pub(crate) unsafe fn init() { - interrupt::IO_IRQ_BANK0::disable(); - interrupt::IO_IRQ_BANK0::set_priority(interrupt::Priority::P3); - interrupt::IO_IRQ_BANK0::enable(); + interrupt::IO_IRQ_BANK0.disable(); + interrupt::IO_IRQ_BANK0.set_priority(interrupt::Priority::P3); + interrupt::IO_IRQ_BANK0.enable(); } #[interrupt] diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 124f1c00a..ce9a082a2 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -2,14 +2,14 @@ use core::future; use core::marker::PhantomData; use core::task::Poll; -use embassy_cortex_m::interrupt::{self, Binding, Interrupt}; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use pac::i2c; use crate::gpio::sealed::Pin; use crate::gpio::AnyPin; -use crate::{pac, peripherals, Peripheral}; +use crate::interrupt::typelevel::{Binding, Interrupt}; +use crate::{interrupt, pac, peripherals, Peripheral}; /// I2C error abort reason #[derive(Debug)] @@ -312,7 +312,7 @@ pub struct InterruptHandler { _uart: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { // Mask interrupts and wake any task waiting for this interrupt unsafe fn on_interrupt() { let i2c = T::regs(); @@ -760,14 +760,15 @@ fn i2c_reserved_addr(addr: u16) -> bool { } mod sealed { - use embassy_cortex_m::interrupt::Interrupt; use embassy_sync::waitqueue::AtomicWaker; + use crate::interrupt; + pub trait Instance { const TX_DREQ: u8; const RX_DREQ: u8; - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; fn regs() -> crate::pac::i2c::I2c; fn reset() -> crate::pac::resets::regs::Peripherals; @@ -803,7 +804,7 @@ macro_rules! impl_instance { const TX_DREQ: u8 = $tx_dreq; const RX_DREQ: u8 = $rx_dreq; - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; #[inline] fn regs() -> pac::i2c::I2c { diff --git a/embassy-rp/src/interrupt.rs b/embassy-rp/src/interrupt.rs deleted file mode 100644 index c9298644d..000000000 --- a/embassy-rp/src/interrupt.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Interrupt definitions and macros to bind them. -pub use cortex_m::interrupt::{CriticalSection, Mutex}; -use embassy_cortex_m::interrupt::_export::declare; -pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, Priority}; - -use crate::pac::Interrupt as InterruptEnum; -declare!(TIMER_IRQ_0); -declare!(TIMER_IRQ_1); -declare!(TIMER_IRQ_2); -declare!(TIMER_IRQ_3); -declare!(PWM_IRQ_WRAP); -declare!(USBCTRL_IRQ); -declare!(XIP_IRQ); -declare!(PIO0_IRQ_0); -declare!(PIO0_IRQ_1); -declare!(PIO1_IRQ_0); -declare!(PIO1_IRQ_1); -declare!(DMA_IRQ_0); -declare!(DMA_IRQ_1); -declare!(IO_IRQ_BANK0); -declare!(IO_IRQ_QSPI); -declare!(SIO_IRQ_PROC0); -declare!(SIO_IRQ_PROC1); -declare!(CLOCKS_IRQ); -declare!(SPI0_IRQ); -declare!(SPI1_IRQ); -declare!(UART0_IRQ); -declare!(UART1_IRQ); -declare!(ADC_IRQ_FIFO); -declare!(I2C0_IRQ); -declare!(I2C1_IRQ); -declare!(RTC_IRQ); -declare!(SWI_IRQ_0); -declare!(SWI_IRQ_1); -declare!(SWI_IRQ_2); -declare!(SWI_IRQ_3); -declare!(SWI_IRQ_4); -declare!(SWI_IRQ_5); - -/// Macro to bind interrupts to handlers. -/// -/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) -/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to -/// prove at compile-time that the right interrupts have been bound. -// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. -#[macro_export] -macro_rules! bind_interrupts { - ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { - $vis struct $name; - - $( - #[allow(non_snake_case)] - #[no_mangle] - unsafe extern "C" fn $irq() { - $( - <$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt(); - )* - } - - $( - unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {} - )* - )* - }; -} diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 4e4542d70..70a410ef9 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -16,7 +16,6 @@ pub mod flash; mod float; pub mod gpio; pub mod i2c; -pub mod interrupt; pub mod multicore; pub mod pwm; mod reset; @@ -38,13 +37,74 @@ pub mod relocate; // Reexports pub use embassy_cortex_m::executor; -pub use embassy_cortex_m::interrupt::_export::interrupt; pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; #[cfg(feature = "unstable-pac")] pub use rp_pac as pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use rp_pac as pac; +embassy_cortex_m::interrupt_mod!( + TIMER_IRQ_0, + TIMER_IRQ_1, + TIMER_IRQ_2, + TIMER_IRQ_3, + PWM_IRQ_WRAP, + USBCTRL_IRQ, + XIP_IRQ, + PIO0_IRQ_0, + PIO0_IRQ_1, + PIO1_IRQ_0, + PIO1_IRQ_1, + DMA_IRQ_0, + DMA_IRQ_1, + IO_IRQ_BANK0, + IO_IRQ_QSPI, + SIO_IRQ_PROC0, + SIO_IRQ_PROC1, + CLOCKS_IRQ, + SPI0_IRQ, + SPI1_IRQ, + UART0_IRQ, + UART1_IRQ, + ADC_IRQ_FIFO, + I2C0_IRQ, + I2C1_IRQ, + RTC_IRQ, + SWI_IRQ_0, + SWI_IRQ_1, + SWI_IRQ_2, + SWI_IRQ_3, + SWI_IRQ_4, + SWI_IRQ_5, +); + +/// Macro to bind interrupts to handlers. +/// +/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) +/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to +/// prove at compile-time that the right interrupts have been bound. +// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. +#[macro_export] +macro_rules! bind_interrupts { + ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { + $vis struct $name; + + $( + #[allow(non_snake_case)] + #[no_mangle] + unsafe extern "C" fn $irq() { + $( + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); + )* + } + + $( + unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {} + )* + )* + }; +} + embassy_hal_common::peripherals! { PIN_0, PIN_1, diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index 807fda57b..e1246ce8f 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -50,7 +50,7 @@ use core::mem::ManuallyDrop; use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; -use crate::interrupt::Interrupt; +use crate::interrupt::InterruptExt; use crate::peripherals::CORE1; use crate::{gpio, interrupt, pac}; @@ -156,7 +156,7 @@ where IS_CORE1_INIT.store(true, Ordering::Release); // Enable fifo interrupt on CORE1 for `pause` functionality. - unsafe { interrupt::SIO_IRQ_PROC1::enable() }; + unsafe { interrupt::SIO_IRQ_PROC1.enable() }; entry() } diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 93e5bd34b..f0a5c17a9 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -5,7 +5,6 @@ use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; use atomic_polyfill::{AtomicU32, AtomicU8}; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use fixed::types::extra::U8; @@ -17,6 +16,7 @@ use pio::{SideSet, Wrap}; use crate::dma::{Channel, Transfer, Word}; use crate::gpio::sealed::Pin as SealedPin; use crate::gpio::{self, AnyPin, Drive, Level, Pull, SlewRate}; +use crate::interrupt::InterruptExt; use crate::pac::dma::vals::TreqSel; use crate::relocate::RelocatedProgram; use crate::{interrupt, pac, peripherals, pio_instr_util, RegExt}; @@ -110,15 +110,15 @@ unsafe fn PIO1_IRQ_0() { } pub(crate) unsafe fn init() { - interrupt::PIO0_IRQ_0::disable(); - interrupt::PIO0_IRQ_0::set_priority(interrupt::Priority::P3); + interrupt::PIO0_IRQ_0.disable(); + interrupt::PIO0_IRQ_0.set_priority(interrupt::Priority::P3); pac::PIO0.irqs(0).inte().write(|m| m.0 = 0); - interrupt::PIO0_IRQ_0::enable(); + interrupt::PIO0_IRQ_0.enable(); - interrupt::PIO1_IRQ_0::disable(); - interrupt::PIO1_IRQ_0::set_priority(interrupt::Priority::P3); + interrupt::PIO1_IRQ_0.disable(); + interrupt::PIO1_IRQ_0.set_priority(interrupt::Priority::P3); pac::PIO1.irqs(0).inte().write(|m| m.0 = 0); - interrupt::PIO1_IRQ_0::enable(); + interrupt::PIO1_IRQ_0.enable(); } /// Future that waits for TX-FIFO to become writable diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs index 68793950f..37f86c930 100644 --- a/embassy-rp/src/timer.rs +++ b/embassy-rp/src/timer.rs @@ -6,7 +6,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; use embassy_time::driver::{AlarmHandle, Driver}; -use crate::interrupt::Interrupt; +use crate::interrupt::InterruptExt; use crate::{interrupt, pac}; struct AlarmState { @@ -145,10 +145,10 @@ pub unsafe fn init() { w.set_alarm(2, true); w.set_alarm(3, true); }); - interrupt::TIMER_IRQ_0::enable(); - interrupt::TIMER_IRQ_1::enable(); - interrupt::TIMER_IRQ_2::enable(); - interrupt::TIMER_IRQ_3::enable(); + interrupt::TIMER_IRQ_0.enable(); + interrupt::TIMER_IRQ_1.enable(); + interrupt::TIMER_IRQ_2.enable(); + interrupt::TIMER_IRQ_3.enable(); } #[interrupt] diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index bb808c467..6660d5dc9 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs @@ -3,14 +3,14 @@ use core::slice; use core::task::Poll; use atomic_polyfill::{AtomicU8, Ordering}; -use embassy_cortex_m::interrupt::{self, Binding, Interrupt}; use embassy_hal_common::atomic_ring_buffer::RingBuffer; use embassy_sync::waitqueue::AtomicWaker; use embassy_time::{Duration, Timer}; use super::*; use crate::clocks::clk_peri_freq; -use crate::RegExt; +use crate::interrupt::typelevel::{Binding, Interrupt}; +use crate::{interrupt, RegExt}; pub struct State { tx_waker: AtomicWaker, @@ -485,7 +485,7 @@ pub struct BufferedInterruptHandler { _uart: PhantomData, } -impl interrupt::Handler for BufferedInterruptHandler { +impl interrupt::typelevel::Handler for BufferedInterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); if r.uartdmacr().read().rxdmae() { diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index a83d94e49..5e3ae8a25 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -3,7 +3,6 @@ use core::marker::PhantomData; use core::task::Poll; use atomic_polyfill::{AtomicU16, Ordering}; -use embassy_cortex_m::interrupt::{self, Binding, Interrupt}; use embassy_futures::select::{select, Either}; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -14,8 +13,9 @@ use crate::clocks::clk_peri_freq; use crate::dma::{AnyChannel, Channel}; use crate::gpio::sealed::Pin; use crate::gpio::AnyPin; +use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::pac::io::vals::{Inover, Outover}; -use crate::{pac, peripherals, Peripheral, RegExt}; +use crate::{interrupt, pac, peripherals, Peripheral, RegExt}; #[cfg(feature = "nightly")] mod buffered; @@ -332,7 +332,7 @@ pub struct InterruptHandler { _uart: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let uart = T::regs(); if !uart.uartdmacr().read().rxdmae() { @@ -930,7 +930,7 @@ mod sealed { const TX_DREQ: u8; const RX_DREQ: u8; - type Interrupt: crate::interrupt::Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; fn regs() -> pac::uart::Uart; @@ -968,7 +968,7 @@ macro_rules! impl_instance { const TX_DREQ: u8 = $tx_dreq; const RX_DREQ: u8 = $rx_dreq; - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> pac::uart::Uart { pac::$inst diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index cc88226df..9fb0dfb70 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -4,15 +4,14 @@ use core::slice; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::{self, Binding}; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver as driver; use embassy_usb_driver::{ Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, }; -use crate::interrupt::Interrupt; -use crate::{pac, peripherals, Peripheral, RegExt}; +use crate::interrupt::typelevel::{Binding, Interrupt}; +use crate::{interrupt, pac, peripherals, Peripheral, RegExt}; pub(crate) mod sealed { pub trait Instance { @@ -22,7 +21,7 @@ pub(crate) mod sealed { } pub trait Instance: sealed::Instance + 'static { - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } impl crate::usb::sealed::Instance for peripherals::USB { @@ -35,7 +34,7 @@ impl crate::usb::sealed::Instance for peripherals::USB { } impl crate::usb::Instance for peripherals::USB { - type Interrupt = crate::interrupt::USBCTRL_IRQ; + type Interrupt = crate::interrupt::typelevel::USBCTRL_IRQ; } const EP_COUNT: usize = 16; @@ -249,7 +248,7 @@ pub struct InterruptHandler { _uart: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let regs = T::regs(); //let x = regs.istr().read().0; diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 730c78f5e..267fec387 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -160,13 +160,11 @@ fn main() { } g.extend(quote! { - pub mod interrupt { - use crate::pac::Interrupt as InterruptEnum; - use embassy_cortex_m::interrupt::_export::declare; + embassy_cortex_m::interrupt_mod!( #( - declare!(#irqs); + #irqs, )* - } + ); }); // ======== diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index c13915a1b..41305d273 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -8,7 +8,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::dma::Transfer; use crate::gpio::sealed::AFType; use crate::gpio::Speed; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -16,7 +16,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let ris = crate::pac::DCMI.ris().read(); if ris.err_ris() { @@ -119,7 +119,7 @@ where pub fn new_8bit( peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, d0: impl Peripheral

> + 'd, d1: impl Peripheral

> + 'd, d2: impl Peripheral

> + 'd, @@ -143,7 +143,7 @@ where pub fn new_10bit( peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, d0: impl Peripheral

> + 'd, d1: impl Peripheral

> + 'd, d2: impl Peripheral

> + 'd, @@ -169,7 +169,7 @@ where pub fn new_12bit( peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, d0: impl Peripheral

> + 'd, d1: impl Peripheral

> + 'd, d2: impl Peripheral

> + 'd, @@ -197,7 +197,7 @@ where pub fn new_14bit( peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, d0: impl Peripheral

> + 'd, d1: impl Peripheral

> + 'd, d2: impl Peripheral

> + 'd, @@ -227,7 +227,7 @@ where pub fn new_es_8bit( peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, d0: impl Peripheral

> + 'd, d1: impl Peripheral

> + 'd, d2: impl Peripheral

> + 'd, @@ -249,7 +249,7 @@ where pub fn new_es_10bit( peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, d0: impl Peripheral

> + 'd, d1: impl Peripheral

> + 'd, d2: impl Peripheral

> + 'd, @@ -273,7 +273,7 @@ where pub fn new_es_12bit( peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, d0: impl Peripheral

> + 'd, d1: impl Peripheral

> + 'd, d2: impl Peripheral

> + 'd, @@ -299,7 +299,7 @@ where pub fn new_es_14bit( peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, d0: impl Peripheral

> + 'd, d1: impl Peripheral

> + 'd, d2: impl Peripheral

> + 'd, @@ -570,7 +570,7 @@ mod sealed { } pub trait Instance: sealed::Instance + 'static { - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } pin_trait!(D0Pin, Instance); @@ -602,7 +602,7 @@ macro_rules! impl_peripheral { } impl Instance for crate::peripherals::$inst { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; } diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 7a1ecda35..83ab4b18f 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -14,7 +14,7 @@ use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError}; use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::BDMA_CHANNEL_COUNT; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::pac; use crate::pac::bdma::{regs, vals}; @@ -70,8 +70,8 @@ static STATE: State = State::new(); pub(crate) unsafe fn init(irq_priority: Priority) { foreach_interrupt! { ($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => { - crate::interrupt::$irq::set_priority(irq_priority); - crate::interrupt::$irq::enable(); + crate::interrupt::typelevel::$irq::set_priority(irq_priority); + crate::interrupt::typelevel::$irq::enable(); }; } crate::_generated::init_bdma(); diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 3b602b991..17313b310 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -13,7 +13,7 @@ use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError}; use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::DMA_CHANNEL_COUNT; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::pac::dma::{regs, vals}; use crate::{interrupt, pac}; @@ -149,8 +149,8 @@ static STATE: State = State::new(); pub(crate) unsafe fn init(irq_priority: Priority) { foreach_interrupt! { ($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => { - interrupt::$irq::set_priority(irq_priority); - interrupt::$irq::enable(); + interrupt::typelevel::$irq::set_priority(irq_priority); + interrupt::typelevel::$irq::enable(); }; } crate::_generated::init_dma(); diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index 7f8b82b46..07fef360f 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -56,8 +56,8 @@ static STATE: State = State::new(); pub(crate) unsafe fn init(irq_priority: Priority) { foreach_interrupt! { ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { - crate::interrupt::$irq::set_priority(irq_priority); - crate::interrupt::$irq::enable(); + crate::interrupt::typelevel::$irq::set_priority(irq_priority); + crate::interrupt::typelevel::$irq::enable(); }; } crate::_generated::init_gpdma(); diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index a5f1a268d..540cdd027 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -5,7 +5,6 @@ mod tx_desc; use core::sync::atomic::{fence, Ordering}; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, PeripheralRef}; use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf}; @@ -14,6 +13,7 @@ pub(crate) use self::tx_desc::{TDes, TDesRing}; use super::*; use crate::gpio::sealed::{AFType, Pin as __GpioPin}; use crate::gpio::AnyPin; +use crate::interrupt::InterruptExt; #[cfg(eth_v1a)] use crate::pac::AFIO; #[cfg(any(eth_v1b, eth_v1c))] @@ -24,7 +24,7 @@ use crate::{interrupt, Peripheral}; /// Interrupt handler. pub struct InterruptHandler {} -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { WAKER.wake(); @@ -100,7 +100,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { pub fn new( queue: &'d mut PacketQueue, peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding + 'd, + _irq: impl interrupt::typelevel::Binding + 'd, ref_clk: impl Peripheral

> + 'd, mdio: impl Peripheral

> + 'd, mdc: impl Peripheral

> + 'd, @@ -267,8 +267,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { P::phy_reset(&mut this); P::phy_init(&mut this); - interrupt::ETH::unpend(); - interrupt::ETH::enable(); + interrupt::ETH.unpend(); + interrupt::ETH.enable(); this } diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 9efa436ac..3e45eafd5 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -2,20 +2,20 @@ mod descriptors; use core::sync::atomic::{fence, Ordering}; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, PeripheralRef}; pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; use super::*; use crate::gpio::sealed::{AFType, Pin as _}; use crate::gpio::{AnyPin, Speed}; +use crate::interrupt::InterruptExt; use crate::pac::ETH; use crate::{interrupt, Peripheral}; /// Interrupt handler. pub struct InterruptHandler {} -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { WAKER.wake(); @@ -64,7 +64,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { pub fn new( queue: &'d mut PacketQueue, peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding + 'd, + _irq: impl interrupt::typelevel::Binding + 'd, ref_clk: impl Peripheral

> + 'd, mdio: impl Peripheral

> + 'd, mdc: impl Peripheral

> + 'd, @@ -238,8 +238,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { P::phy_reset(&mut this); P::phy_init(&mut this); - interrupt::ETH::unpend(); - interrupt::ETH::enable(); + interrupt::ETH.unpend(); + interrupt::ETH.enable(); this } diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index c2fa31b20..a2ed07093 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -354,13 +354,13 @@ impl_exti!(EXTI15, 15); macro_rules! enable_irq { ($e:ident) => { - crate::interrupt::$e::enable(); + crate::interrupt::typelevel::$e::enable(); }; } /// safety: must be called only once pub(crate) unsafe fn init() { - use crate::interrupt::Interrupt; + use crate::interrupt::typelevel::Interrupt; foreach_exti_irq!(enable_irq); diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 872614d4e..70a5ded62 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -1,7 +1,6 @@ use core::marker::PhantomData; use atomic_polyfill::{fence, Ordering}; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::into_ref; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; @@ -11,6 +10,7 @@ use super::{ blocking_read, ensure_sector_aligned, family, get_sector, Async, Error, Flash, FlashLayout, FLASH_BASE, FLASH_SIZE, WRITE_SIZE, }; +use crate::interrupt::InterruptExt; use crate::peripherals::FLASH; use crate::{interrupt, Peripheral}; @@ -19,12 +19,12 @@ pub(super) static REGION_ACCESS: Mutex = Mutex::new impl<'d> Flash<'d, Async> { pub fn new( p: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding + 'd, + _irq: impl interrupt::typelevel::Binding + 'd, ) -> Self { into_ref!(p); - crate::interrupt::FLASH::unpend(); - unsafe { crate::interrupt::FLASH::enable() }; + crate::interrupt::FLASH.unpend(); + unsafe { crate::interrupt::FLASH.enable() }; Self { inner: p, @@ -49,7 +49,7 @@ impl<'d> Flash<'d, Async> { /// Interrupt handler pub struct InterruptHandler; -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { family::on_interrupt(); } diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index f898fcc8b..b35678ed9 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -1,6 +1,6 @@ #![macro_use] -use crate::interrupt::Interrupt; +use crate::interrupt; #[cfg_attr(i2c_v1, path = "v1.rs")] #[cfg_attr(i2c_v2, path = "v2.rs")] @@ -35,7 +35,7 @@ pub(crate) mod sealed { } pub trait Instance: sealed::Instance + 'static { - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } pin_trait!(SclPin, Instance); @@ -57,7 +57,7 @@ foreach_interrupt!( } impl Instance for peripherals::$inst { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; ); diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index b9be2e587..e04038886 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -16,7 +16,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() {} } @@ -57,7 +57,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { _peri: impl Peripheral

+ 'd, scl: impl Peripheral

> + 'd, sda: impl Peripheral

> + 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: impl Peripheral

+ 'd, rx_dma: impl Peripheral

+ 'd, freq: Hertz, diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 10f57f700..1aaf2b46b 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -3,7 +3,6 @@ use core::future::poll_fn; use core::marker::PhantomData; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_embedded_hal::SetConfig; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -13,6 +12,7 @@ use crate::dma::{NoDma, Transfer}; use crate::gpio::sealed::AFType; use crate::gpio::Pull; use crate::i2c::{Error, Instance, SclPin, SdaPin}; +use crate::interrupt::typelevel::Interrupt; use crate::pac::i2c; use crate::time::Hertz; use crate::{interrupt, Peripheral}; @@ -22,7 +22,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let regs = T::regs(); let isr = regs.isr().read(); @@ -78,7 +78,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { peri: impl Peripheral

+ 'd, scl: impl Peripheral

> + 'd, sda: impl Peripheral

> + 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: impl Peripheral

+ 'd, rx_dma: impl Peripheral

+ 'd, freq: Hertz, diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 75d8af3dd..b42864567 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -72,46 +72,39 @@ pub(crate) mod _generated { include!(concat!(env!("OUT_DIR"), "/_generated.rs")); } -pub mod interrupt { - //! Interrupt definitions and macros to bind them. - pub use cortex_m::interrupt::{CriticalSection, Mutex}; - pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, Priority}; +pub use crate::_generated::interrupt; - pub use crate::_generated::interrupt::*; +/// Macro to bind interrupts to handlers. +/// +/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) +/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to +/// prove at compile-time that the right interrupts have been bound. +// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. +#[macro_export] +macro_rules! bind_interrupts { + ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { + $vis struct $name; - /// Macro to bind interrupts to handlers. - /// - /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) - /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to - /// prove at compile-time that the right interrupts have been bound. - // developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. - #[macro_export] - macro_rules! bind_interrupts { - ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { - $vis struct $name; + $( + #[allow(non_snake_case)] + #[no_mangle] + unsafe extern "C" fn $irq() { + $( + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); + )* + } $( - #[allow(non_snake_case)] - #[no_mangle] - unsafe extern "C" fn $irq() { - $( - <$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt(); - )* - } - - $( - unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {} - )* + unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {} )* - }; - } + )* + }; } // Reexports pub use _generated::{peripherals, Peripherals}; pub use embassy_cortex_m::executor; use embassy_cortex_m::interrupt::Priority; -pub use embassy_cortex_m::interrupt::_export::interrupt; pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; #[cfg(feature = "unstable-pac")] pub use stm32_metapac as pac; diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 3cc17aa68..28eb49ab6 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -14,7 +14,7 @@ use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, use crate::dma::NoDma; use crate::gpio::sealed::{AFType, Pin}; use crate::gpio::{AnyPin, Pull, Speed}; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::pac::sdmmc::Sdmmc as RegBlock; use crate::rcc::RccPeripheral; use crate::time::Hertz; @@ -42,7 +42,7 @@ impl InterruptHandler { } } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { Self::data_interrupts(false); T::state().wake(); @@ -276,7 +276,7 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma = NoDma> { impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> { pub fn new_1bit( sdmmc: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, dma: impl Peripheral

+ 'd, clk: impl Peripheral

> + 'd, cmd: impl Peripheral

> + 'd, @@ -310,7 +310,7 @@ impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> { pub fn new_4bit( sdmmc: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, dma: impl Peripheral

+ 'd, clk: impl Peripheral

> + 'd, cmd: impl Peripheral

> + 'd, @@ -356,7 +356,7 @@ impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> { impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { pub fn new_1bit( sdmmc: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, clk: impl Peripheral

> + 'd, cmd: impl Peripheral

> + 'd, d0: impl Peripheral

> + 'd, @@ -389,7 +389,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { pub fn new_4bit( sdmmc: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, clk: impl Peripheral

> + 'd, cmd: impl Peripheral

> + 'd, d0: impl Peripheral

> + 'd, @@ -1401,7 +1401,7 @@ pub(crate) mod sealed { use super::*; pub trait Instance { - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; fn regs() -> RegBlock; fn state() -> &'static AtomicWaker; @@ -1490,7 +1490,7 @@ cfg_if::cfg_if! { foreach_peripheral!( (sdmmc, $inst:ident) => { impl sealed::Instance for peripherals::$inst { - type Interrupt = crate::interrupt::$inst; + type Interrupt = crate::interrupt::typelevel::$inst; fn regs() -> RegBlock { crate::pac::$inst diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index bab700993..8f282bafb 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -11,7 +11,7 @@ use embassy_time::driver::{AlarmHandle, Driver}; use embassy_time::TICK_HZ; use stm32_metapac::timer::regs; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::pac::timer::vals; use crate::rcc::sealed::RccPeripheral; use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance}; diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 772c67686..14db97024 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -1,6 +1,6 @@ use stm32_metapac::timer::vals; -use crate::interrupt::Interrupt; +use crate::interrupt; use crate::rcc::sealed::RccPeripheral as __RccPeri; use crate::rcc::RccPeripheral; use crate::time::Hertz; @@ -13,7 +13,7 @@ pub mod low_level { pub(crate) mod sealed { use super::*; pub trait Basic16bitInstance: RccPeripheral { - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; fn regs() -> crate::pac::timer::TimBasic; @@ -57,7 +57,7 @@ pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {} macro_rules! impl_basic_16bit_timer { ($inst:ident, $irq:ident) => { impl sealed::Basic16bitInstance for crate::peripherals::$inst { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> crate::pac::timer::TimBasic { crate::pac::timer::TimBasic(crate::pac::$inst.0) diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs index efbbf2d1d..d39c78b2c 100644 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ b/embassy-stm32/src/tl_mbox/mod.rs @@ -2,7 +2,6 @@ use core::mem::MaybeUninit; use atomic_polyfill::{compiler_fence, Ordering}; use bit_field::BitField; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; @@ -15,6 +14,7 @@ use self::shci::{shci_ble_init, ShciBleInitCmdParam}; use self::sys::Sys; use self::unsafe_linked_list::LinkedListNode; use crate::interrupt; +use crate::interrupt::InterruptExt; use crate::peripherals::IPCC; pub use crate::tl_mbox::ipcc::Config; use crate::tl_mbox::ipcc::Ipcc; @@ -63,7 +63,7 @@ pub struct FusInfoTable { /// Interrupt handler. pub struct ReceiveInterruptHandler {} -impl interrupt::Handler for ReceiveInterruptHandler { +impl interrupt::typelevel::Handler for ReceiveInterruptHandler { unsafe fn on_interrupt() { // info!("ipcc rx interrupt"); @@ -79,7 +79,7 @@ impl interrupt::Handler for ReceiveInterruptHandler { pub struct TransmitInterruptHandler {} -impl interrupt::Handler for TransmitInterruptHandler { +impl interrupt::typelevel::Handler for TransmitInterruptHandler { unsafe fn on_interrupt() { // info!("ipcc tx interrupt"); @@ -324,8 +324,8 @@ impl<'d> TlMbox<'d> { /// initializes low-level transport between CPU1 and BLE stack on CPU2 pub fn new( ipcc: impl Peripheral

+ 'd, - _irqs: impl interrupt::Binding - + interrupt::Binding, + _irqs: impl interrupt::typelevel::Binding + + interrupt::typelevel::Binding, config: Config, ) -> Self { into_ref!(ipcc); @@ -379,11 +379,11 @@ impl<'d> TlMbox<'d> { MemoryManager::enable(); // enable interrupts - crate::interrupt::IPCC_C1_RX::unpend(); - crate::interrupt::IPCC_C1_TX::unpend(); + crate::interrupt::IPCC_C1_RX.unpend(); + crate::interrupt::IPCC_C1_TX.unpend(); - unsafe { crate::interrupt::IPCC_C1_RX::enable() }; - unsafe { crate::interrupt::IPCC_C1_TX::enable() }; + unsafe { crate::interrupt::IPCC_C1_RX.enable() }; + unsafe { crate::interrupt::IPCC_C1_TX.enable() }; Self { _ipcc: ipcc } } diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 252e945da..613da5674 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -2,18 +2,18 @@ use core::future::poll_fn; use core::slice; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::atomic_ring_buffer::RingBuffer; use embassy_sync::waitqueue::AtomicWaker; use super::*; +use crate::interrupt::typelevel::Interrupt; /// Interrupt handler. pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); let state = T::buffered_state(); @@ -115,7 +115,7 @@ pub struct BufferedUartRx<'d, T: BasicInstance> { impl<'d, T: BasicInstance> BufferedUart<'d, T> { pub fn new( peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rx: impl Peripheral

> + 'd, tx: impl Peripheral

> + 'd, tx_buffer: &'d mut [u8], @@ -130,7 +130,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { pub fn new_with_rtscts( peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rx: impl Peripheral

> + 'd, tx: impl Peripheral

> + 'd, rts: impl Peripheral

> + 'd, @@ -159,7 +159,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { #[cfg(not(any(usart_v1, usart_v2)))] pub fn new_with_de( peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rx: impl Peripheral

> + 'd, tx: impl Peripheral

> + 'd, de: impl Peripheral

> + 'd, diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index ef1080153..da3644a81 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -5,13 +5,13 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use futures::future::{select, Either}; use crate::dma::{NoDma, Transfer}; use crate::gpio::sealed::AFType; +use crate::interrupt::typelevel::Interrupt; #[cfg(not(any(usart_v1, usart_v2)))] #[allow(unused_imports)] use crate::pac::usart::regs::Isr as Sr; @@ -31,7 +31,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { let r = T::regs(); let s = T::state(); @@ -281,7 +281,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. pub fn new( peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rx: impl Peripheral

> + 'd, rx_dma: impl Peripheral

+ 'd, config: Config, @@ -294,7 +294,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { pub fn new_with_rts( peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rx: impl Peripheral

> + 'd, rts: impl Peripheral

> + 'd, rx_dma: impl Peripheral

+ 'd, @@ -650,7 +650,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { peri: impl Peripheral

+ 'd, rx: impl Peripheral

> + 'd, tx: impl Peripheral

> + 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: impl Peripheral

+ 'd, rx_dma: impl Peripheral

+ 'd, config: Config, @@ -665,7 +665,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { peri: impl Peripheral

+ 'd, rx: impl Peripheral

> + 'd, tx: impl Peripheral

> + 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, rts: impl Peripheral

> + 'd, cts: impl Peripheral

> + 'd, tx_dma: impl Peripheral

+ 'd, @@ -693,7 +693,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { peri: impl Peripheral

+ 'd, rx: impl Peripheral

> + 'd, tx: impl Peripheral

> + 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, de: impl Peripheral

> + 'd, tx_dma: impl Peripheral

+ 'd, rx_dma: impl Peripheral

+ 'd, @@ -1179,7 +1179,7 @@ pub(crate) mod sealed { pub trait BasicInstance: crate::rcc::RccPeripheral { const KIND: Kind; - type Interrupt: crate::interrupt::Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; fn regs() -> Regs; fn state() -> &'static State; @@ -1211,7 +1211,7 @@ macro_rules! impl_usart { ($inst:ident, $irq:ident, $kind:expr) => { impl sealed::BasicInstance for crate::peripherals::$inst { const KIND: Kind = $kind; - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> Regs { Regs(crate::pac::$inst.0) diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index fbd1fa823..bee287fe6 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -1,4 +1,4 @@ -use crate::interrupt::Interrupt; +use crate::interrupt; use crate::rcc::RccPeripheral; #[cfg(feature = "nightly")] @@ -13,7 +13,7 @@ pub(crate) mod sealed { } pub trait Instance: sealed::Instance + RccPeripheral + 'static { - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } // Internal PHY pins @@ -29,7 +29,7 @@ foreach_interrupt!( } impl Instance for crate::peripherals::$inst { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; ); diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 134107978..7486bd376 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -14,7 +14,7 @@ use embassy_usb_driver::{ use super::{DmPin, DpPin, Instance}; use crate::gpio::sealed::AFType; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::pac::usb::regs; use crate::pac::usb::vals::{EpType, Stat}; use crate::pac::USBRAM; @@ -26,7 +26,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { unsafe { let regs = T::regs(); @@ -255,7 +255,7 @@ pub struct Driver<'d, T: Instance> { impl<'d, T: Instance> Driver<'d, T> { pub fn new( _usb: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, dp: impl Peripheral

> + 'd, dm: impl Peripheral

> + 'd, ) -> Self { diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs index 193e0df0d..317264cbb 100644 --- a/embassy-stm32/src/usb_otg/mod.rs +++ b/embassy-stm32/src/usb_otg/mod.rs @@ -1,7 +1,5 @@ -use embassy_cortex_m::interrupt::Interrupt; - -use crate::peripherals; use crate::rcc::RccPeripheral; +use crate::{interrupt, peripherals}; #[cfg(feature = "nightly")] mod usb; @@ -25,7 +23,7 @@ pub(crate) mod sealed { } pub trait Instance: sealed::Instance + RccPeripheral { - type Interrupt: Interrupt; + type Interrupt: interrupt::typelevel::Interrupt; } // Internal PHY pins @@ -109,7 +107,7 @@ foreach_interrupt!( } impl Instance for peripherals::USB_OTG_FS { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; @@ -161,7 +159,7 @@ foreach_interrupt!( } impl Instance for peripherals::USB_OTG_HS { - type Interrupt = crate::interrupt::$irq; + type Interrupt = crate::interrupt::typelevel::$irq; } }; ); diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index e602bcb70..16cbf1a95 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs @@ -3,7 +3,6 @@ use core::marker::PhantomData; use core::task::Poll; use atomic_polyfill::{AtomicBool, AtomicU16, Ordering}; -use embassy_cortex_m::interrupt::Interrupt; use embassy_hal_common::{into_ref, Peripheral}; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver::{ @@ -15,6 +14,7 @@ use futures::future::poll_fn; use super::*; use crate::gpio::sealed::AFType; use crate::interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::pac::otg::{regs, vals}; use crate::rcc::sealed::RccPeripheral; use crate::time::Hertz; @@ -24,7 +24,7 @@ pub struct InterruptHandler { _phantom: PhantomData, } -impl interrupt::Handler for InterruptHandler { +impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { trace!("irq"); let r = T::regs(); @@ -291,7 +291,7 @@ impl<'d, T: Instance> Driver<'d, T> { /// Endpoint allocation will fail if it is too small. pub fn new_fs( _peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, dp: impl Peripheral

> + 'd, dm: impl Peripheral

> + 'd, ep_out_buffer: &'d mut [u8], @@ -322,7 +322,7 @@ impl<'d, T: Instance> Driver<'d, T> { /// Endpoint allocation will fail if it is too small. pub fn new_hs_ulpi( _peri: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding> + 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, ulpi_clk: impl Peripheral

> + 'd, ulpi_dir: impl Peripheral

> + 'd, ulpi_nxt: impl Peripheral

> + 'd, diff --git a/examples/stm32f7/build.rs b/examples/stm32f7/build.rs index c4e15f19c..2b5d412a9 100644 --- a/examples/stm32f7/build.rs +++ b/examples/stm32f7/build.rs @@ -1,9 +1,8 @@ //! adapted from https://github.com/stm32-rs/stm32f7xx-hal/blob/master/build.rs -use std::env; use std::fs::File; use std::io::prelude::*; -use std::io::{self}; use std::path::PathBuf; +use std::{env, io}; #[derive(Debug)] enum Error { From bce24e800516402a3a3991ebde0432e5167be174 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 8 Jun 2023 18:07:44 +0200 Subject: [PATCH 40/98] asdg --- embassy-stm32/src/dma/gpdma.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index 07fef360f..59ec205bf 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -12,7 +12,7 @@ use embassy_sync::waitqueue::AtomicWaker; use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::GPDMA_CHANNEL_COUNT; -use crate::interrupt::Interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::pac; use crate::pac::gpdma::vals; From 5c2f02c73505cf630c2fbe9b098707a33293d702 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 8 Jun 2023 16:39:05 +0200 Subject: [PATCH 41/98] Reexport NVIC_PRIO_BITS at HAL root. This allows using RTIC with `#[rtic::app(device = embassy_nrf, ...)]` --- embassy-nrf/src/chips/nrf5340_app.rs | 2 ++ embassy-nrf/src/chips/nrf5340_net.rs | 2 ++ embassy-nrf/src/chips/nrf9160.rs | 2 ++ embassy-nrf/src/lib.rs | 5 +++-- embassy-rp/src/lib.rs | 2 ++ embassy-stm32/src/lib.rs | 2 ++ 6 files changed, 13 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs index c10520051..cb879f736 100644 --- a/embassy-nrf/src/chips/nrf5340_app.rs +++ b/embassy-nrf/src/chips/nrf5340_app.rs @@ -5,6 +5,8 @@ pub mod pac { // The nRF5340 has a secure and non-secure (NS) mode. // To avoid cfg spam, we remove _ns or _s suffixes here. + pub use nrf5340_app_pac::NVIC_PRIO_BITS; + #[doc(no_inline)] pub use nrf5340_app_pac::{ interrupt, diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs index a6fb1d4cc..6e2c0bb67 100644 --- a/embassy-nrf/src/chips/nrf5340_net.rs +++ b/embassy-nrf/src/chips/nrf5340_net.rs @@ -5,6 +5,8 @@ pub mod pac { // The nRF5340 has a secure and non-secure (NS) mode. // To avoid cfg spam, we remove _ns or _s suffixes here. + pub use nrf5340_net_pac::NVIC_PRIO_BITS; + #[doc(no_inline)] pub use nrf5340_net_pac::{ interrupt, diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs index b6ae78bbe..9944ac4af 100644 --- a/embassy-nrf/src/chips/nrf9160.rs +++ b/embassy-nrf/src/chips/nrf9160.rs @@ -5,6 +5,8 @@ pub mod pac { // The nRF9160 has a secure and non-secure (NS) mode. // To avoid cfg spam, we remove _ns or _s suffixes here. + pub use nrf9160_pac::NVIC_PRIO_BITS; + #[doc(no_inline)] pub use nrf9160_pac::{ interrupt, diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index a73d22a63..ddabf93a9 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -93,8 +93,6 @@ pub mod wdt; #[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")] mod chip; -pub use crate::chip::interrupt; - /// Macro to bind interrupts to handlers. /// /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) @@ -132,6 +130,9 @@ pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE}; pub use embassy_cortex_m::executor; pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +pub use crate::chip::interrupt; +pub use crate::pac::NVIC_PRIO_BITS; + pub mod config { //! Configuration options used when initializing the HAL. diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 70a410ef9..5e3e59692 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -43,6 +43,8 @@ pub use rp_pac as pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use rp_pac as pac; +pub use crate::pac::NVIC_PRIO_BITS; + embassy_cortex_m::interrupt_mod!( TIMER_IRQ_0, TIMER_IRQ_1, diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index b42864567..565d6817c 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -111,6 +111,8 @@ pub use stm32_metapac as pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use stm32_metapac as pac; +pub use crate::pac::NVIC_PRIO_BITS; + #[non_exhaustive] pub struct Config { pub rcc: rcc::Config, From f498c689e7c3a2314c7a80bf14fc2cb491528aa4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 8 Jun 2023 16:40:02 +0200 Subject: [PATCH 42/98] Add RTIC example. --- ci.sh | 1 + examples/nrf52840-rtic/.cargo/config.toml | 9 +++++ examples/nrf52840-rtic/Cargo.toml | 21 +++++++++++ examples/nrf52840-rtic/build.rs | 35 ++++++++++++++++++ examples/nrf52840-rtic/memory.x | 7 ++++ examples/nrf52840-rtic/src/bin/blinky.rs | 43 +++++++++++++++++++++++ 6 files changed, 116 insertions(+) create mode 100644 examples/nrf52840-rtic/.cargo/config.toml create mode 100644 examples/nrf52840-rtic/Cargo.toml create mode 100644 examples/nrf52840-rtic/build.rs create mode 100644 examples/nrf52840-rtic/memory.x create mode 100644 examples/nrf52840-rtic/src/bin/blinky.rs diff --git a/ci.sh b/ci.sh index 08558a18f..da2414d68 100755 --- a/ci.sh +++ b/ci.sh @@ -104,6 +104,7 @@ cargo batch \ --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-irq/Cargo.toml --target thumbv7em-none-eabi \ --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml --target thumbv7em-none-eabi \ --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840 \ + --- build --release --manifest-path examples/nrf52840-rtic/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840-rtic \ --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf5340 \ --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \ --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \ diff --git a/examples/nrf52840-rtic/.cargo/config.toml b/examples/nrf52840-rtic/.cargo/config.toml new file mode 100644 index 000000000..3872e7189 --- /dev/null +++ b/examples/nrf52840-rtic/.cargo/config.toml @@ -0,0 +1,9 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace nRF82840_xxAA with your chip as listed in `probe-rs-cli chip list` +runner = "probe-rs-cli run --chip nRF52840_xxAA" + +[build] +target = "thumbv7em-none-eabi" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml new file mode 100644 index 000000000..0f9048b0f --- /dev/null +++ b/examples/nrf52840-rtic/Cargo.toml @@ -0,0 +1,21 @@ +[package] +edition = "2021" +name = "embassy-nrf52840-rtic-examples" +version = "0.1.0" +license = "MIT OR Apache-2.0" + +[dependencies] +rtic = { version = "2", features = ["thumbv7-backend"] } + +embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "generic-queue"] } +embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nightly", "unstable-traits", "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } + +defmt = "0.3" +defmt-rtt = "0.4" + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" +panic-probe = { version = "0.3", features = ["print-defmt"] } +futures = { version = "0.3.17", default-features = false, features = ["async-await"] } diff --git a/examples/nrf52840-rtic/build.rs b/examples/nrf52840-rtic/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/nrf52840-rtic/build.rs @@ -0,0 +1,35 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/examples/nrf52840-rtic/memory.x b/examples/nrf52840-rtic/memory.x new file mode 100644 index 000000000..9b04edec0 --- /dev/null +++ b/examples/nrf52840-rtic/memory.x @@ -0,0 +1,7 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + /* These values correspond to the NRF52840 with Softdevices S140 7.0.1 */ + FLASH : ORIGIN = 0x00000000, LENGTH = 1024K + RAM : ORIGIN = 0x20000000, LENGTH = 256K +} diff --git a/examples/nrf52840-rtic/src/bin/blinky.rs b/examples/nrf52840-rtic/src/bin/blinky.rs new file mode 100644 index 000000000..a682c1932 --- /dev/null +++ b/examples/nrf52840-rtic/src/bin/blinky.rs @@ -0,0 +1,43 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use {defmt_rtt as _, panic_probe as _}; + +#[rtic::app(device = embassy_nrf, peripherals = false, dispatchers = [SWI0_EGU0, SWI1_EGU1])] +mod app { + use defmt::info; + use embassy_nrf::gpio::{Level, Output, OutputDrive}; + use embassy_nrf::peripherals; + use embassy_time::{Duration, Timer}; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(_: init::Context) -> (Shared, Local) { + info!("Hello World!"); + + let p = embassy_nrf::init(Default::default()); + blink::spawn(p.P0_13).map_err(|_| ()).unwrap(); + + (Shared {}, Local {}) + } + + #[task(priority = 1)] + async fn blink(_cx: blink::Context, pin: peripherals::P0_13) { + let mut led = Output::new(pin, Level::Low, OutputDrive::Standard); + + loop { + info!("off!"); + led.set_high(); + Timer::after(Duration::from_millis(300)).await; + info!("on!"); + led.set_low(); + Timer::after(Duration::from_millis(300)).await; + } + } +} From 8c93805ab5a13c784e072c8e6e59b354ee902d99 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 8 Jun 2023 18:00:19 +0200 Subject: [PATCH 43/98] Add `rt` feature to HALs, cfg out interrupt handling when not set. --- embassy-cortex-m/src/interrupt.rs | 3 ++- embassy-nrf/Cargo.toml | 3 ++- embassy-nrf/src/gpiote.rs | 3 +++ embassy-nrf/src/time_driver.rs | 1 + embassy-rp/Cargo.toml | 3 ++- embassy-rp/src/dma.rs | 1 + embassy-rp/src/gpio.rs | 1 + embassy-rp/src/lib.rs | 1 + embassy-rp/src/multicore.rs | 2 ++ embassy-rp/src/pio.rs | 2 ++ embassy-rp/src/timer.rs | 4 ++++ embassy-stm32/Cargo.toml | 4 +++- embassy-stm32/build.rs | 1 + embassy-stm32/src/exti.rs | 1 + embassy-stm32/src/lib.rs | 1 + embassy-stm32/src/rng.rs | 2 ++ embassy-stm32/src/time_driver.rs | 6 ++++++ 17 files changed, 35 insertions(+), 4 deletions(-) diff --git a/embassy-cortex-m/src/interrupt.rs b/embassy-cortex-m/src/interrupt.rs index 8e45c36c7..e9fa43e87 100644 --- a/embassy-cortex-m/src/interrupt.rs +++ b/embassy-cortex-m/src/interrupt.rs @@ -9,12 +9,13 @@ use cortex_m::peripheral::NVIC; #[macro_export] macro_rules! interrupt_mod { ($($irqs:ident),* $(,)?) => { + #[cfg(feature = "rt")] pub use cortex_m_rt::interrupt; /// Interrupt definitions. pub mod interrupt { pub use embassy_cortex_m::interrupt::{InterruptExt, Priority}; - pub use crate::pac::interrupt::*; + pub use crate::pac::Interrupt::*; pub use crate::pac::Interrupt; /// Type-level interrupt infrastructure. diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 83900d4d0..5fab11f37 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -16,7 +16,8 @@ flavors = [ ] [features] -default = [ +default = ["rt"] +rt = [ "nrf52805-pac?/rt", "nrf52810-pac?/rt", "nrf52811-pac?/rt", diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 1d7725bd3..21d0d9564 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -91,18 +91,21 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) { } #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))] +#[cfg(feature = "rt")] #[interrupt] fn GPIOTE0() { unsafe { handle_gpiote_interrupt() }; } #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))] +#[cfg(feature = "rt")] #[interrupt] fn GPIOTE1() { unsafe { handle_gpiote_interrupt() }; } #[cfg(any(feature = "_nrf52", feature = "nrf5340-net"))] +#[cfg(feature = "rt")] #[interrupt] fn GPIOTE() { unsafe { handle_gpiote_interrupt() }; diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs index f993d7b2e..f1ab4f8fd 100644 --- a/embassy-nrf/src/time_driver.rs +++ b/embassy-nrf/src/time_driver.rs @@ -295,6 +295,7 @@ impl Driver for RtcDriver { } } +#[cfg(feature = "rt")] #[interrupt] fn RTC1() { DRIVER.on_interrupt() diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index ddada655b..ee06e99ce 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -13,7 +13,8 @@ flavors = [ ] [features] -default = [ "rp-pac/rt" ] +default = [ "rt" ] +rt = [ "rp-pac/rt" ] defmt = ["dep:defmt", "embassy-usb-driver?/defmt", "embassy-hal-common/defmt"] diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 042ca99a9..25819f03e 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -12,6 +12,7 @@ use crate::interrupt::InterruptExt; use crate::pac::dma::vals; use crate::{interrupt, pac, peripherals}; +#[cfg(feature = "rt")] #[interrupt] unsafe fn DMA_IRQ_0() { let ints0 = pac::DMA.ints0().read().ints0(); diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index ebd932f50..66faa2489 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -142,6 +142,7 @@ pub(crate) unsafe fn init() { interrupt::IO_IRQ_BANK0.enable(); } +#[cfg(feature = "rt")] #[interrupt] unsafe fn IO_IRQ_BANK0() { let cpu = SIO.cpuid().read() as usize; diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 5e3e59692..4e4b76141 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -43,6 +43,7 @@ pub use rp_pac as pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use rp_pac as pac; +#[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; embassy_cortex_m::interrupt_mod!( diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index e1246ce8f..2a7e4822a 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -106,6 +106,7 @@ impl Stack { } } +#[cfg(feature = "rt")] #[interrupt] #[link_section = ".data.ram_func"] unsafe fn SIO_IRQ_PROC1() { @@ -297,6 +298,7 @@ fn fifo_read() -> u32 { // Pop a value from inter-core FIFO, `wfe` until available #[inline(always)] +#[allow(unused)] fn fifo_read_wfe() -> u32 { unsafe { let sio = pac::SIO; diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index f0a5c17a9..0fa3bd771 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -85,6 +85,7 @@ const RXNEMPTY_MASK: u32 = 1 << 0; const TXNFULL_MASK: u32 = 1 << 4; const SMIRQ_MASK: u32 = 1 << 8; +#[cfg(feature = "rt")] #[interrupt] unsafe fn PIO0_IRQ_0() { use crate::pac; @@ -97,6 +98,7 @@ unsafe fn PIO0_IRQ_0() { pac::PIO0.irqs(0).inte().write_clear(|m| m.0 = ints); } +#[cfg(feature = "rt")] #[interrupt] unsafe fn PIO1_IRQ_0() { use crate::pac; diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs index 37f86c930..ca8c96c0f 100644 --- a/embassy-rp/src/timer.rs +++ b/embassy-rp/src/timer.rs @@ -151,21 +151,25 @@ pub unsafe fn init() { interrupt::TIMER_IRQ_3.enable(); } +#[cfg(feature = "rt")] #[interrupt] unsafe fn TIMER_IRQ_0() { DRIVER.check_alarm(0) } +#[cfg(feature = "rt")] #[interrupt] unsafe fn TIMER_IRQ_1() { DRIVER.check_alarm(1) } +#[cfg(feature = "rt")] #[interrupt] unsafe fn TIMER_IRQ_2() { DRIVER.check_alarm(2) } +#[cfg(feature = "rt")] #[interrupt] unsafe fn TIMER_IRQ_3() { DRIVER.check_alarm(3) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 4e29bb32f..f1f894c6c 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -79,7 +79,9 @@ quote = "1.0.15" stm32-metapac = { version = "9", default-features = false, features = ["metadata"]} [features] -default = ["stm32-metapac/rt"] +default = ["rt"] +rt = ["stm32-metapac/rt"] + defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-executor/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt"] memory-x = ["stm32-metapac/memory-x"] exti = [] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 267fec387..ba5f91ccf 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -295,6 +295,7 @@ fn main() { let channels = channels.iter().map(|(_, dma, ch)| format_ident!("{}_{}", dma, ch)); g.extend(quote! { + #[cfg(feature = "rt")] #[crate::interrupt] unsafe fn #irq () { #( diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index a2ed07093..0631ae473 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -291,6 +291,7 @@ macro_rules! foreach_exti_irq { macro_rules! impl_irq { ($e:ident) => { + #[cfg(feature = "rt")] #[interrupt] unsafe fn $e() { on_irq() diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 565d6817c..f8857fdd2 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -111,6 +111,7 @@ pub use stm32_metapac as pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use stm32_metapac as pac; +#[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; #[non_exhaustive] diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 1e16b8478..c657bf70e 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -149,6 +149,7 @@ foreach_peripheral!( }; ); +#[cfg(feature = "rt")] macro_rules! irq { ($irq:ident) => { mod rng_irq { @@ -166,6 +167,7 @@ macro_rules! irq { }; } +#[cfg(feature = "rt")] foreach_interrupt!( (RNG) => { irq!(RNG); diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 8f282bafb..e82501a45 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -40,6 +40,7 @@ type T = peripherals::TIM15; foreach_interrupt! { (TIM2, timer, $block:ident, UP, $irq:ident) => { #[cfg(time_driver_tim2)] + #[cfg(feature = "rt")] #[interrupt] fn $irq() { DRIVER.on_interrupt() @@ -47,6 +48,7 @@ foreach_interrupt! { }; (TIM3, timer, $block:ident, UP, $irq:ident) => { #[cfg(time_driver_tim3)] + #[cfg(feature = "rt")] #[interrupt] fn $irq() { DRIVER.on_interrupt() @@ -54,6 +56,7 @@ foreach_interrupt! { }; (TIM4, timer, $block:ident, UP, $irq:ident) => { #[cfg(time_driver_tim4)] + #[cfg(feature = "rt")] #[interrupt] fn $irq() { DRIVER.on_interrupt() @@ -61,6 +64,7 @@ foreach_interrupt! { }; (TIM5, timer, $block:ident, UP, $irq:ident) => { #[cfg(time_driver_tim5)] + #[cfg(feature = "rt")] #[interrupt] fn $irq() { DRIVER.on_interrupt() @@ -68,6 +72,7 @@ foreach_interrupt! { }; (TIM12, timer, $block:ident, UP, $irq:ident) => { #[cfg(time_driver_tim12)] + #[cfg(feature = "rt")] #[interrupt] fn $irq() { DRIVER.on_interrupt() @@ -75,6 +80,7 @@ foreach_interrupt! { }; (TIM15, timer, $block:ident, UP, $irq:ident) => { #[cfg(time_driver_tim15)] + #[cfg(feature = "rt")] #[interrupt] fn $irq() { DRIVER.on_interrupt() From 4716166041e78a4227331de2cab601b5e3252273 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 8 Jun 2023 19:37:11 +0200 Subject: [PATCH 44/98] tests/rp: update cyw43-perf for embassy-net changes. --- tests/rp/src/bin/cyw43-perf.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs index 568f1b826..dd67914aa 100644 --- a/tests/rp/src/bin/cyw43-perf.rs +++ b/tests/rp/src/bin/cyw43-perf.rs @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) { .set_power_management(cyw43::PowerManagementMode::PowerSave) .await; - let config = Config::Dhcp(Default::default()); + let config = Config::dhcpv4(Default::default()); //let config = embassy_net::Config::Static(embassy_net::Config { // address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), // dns_servers: Vec::new(), @@ -93,7 +93,7 @@ async fn main(spawner: Spawner) { } info!("Waiting for DHCP up..."); - while stack.config().is_none() { + while stack.config_v4().is_none() { Timer::after(Duration::from_millis(100)).await; } info!("IP addressing up!"); From 3dde01597a7861817ee52fef6ea4b5732a77debc Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 8 Jun 2023 21:12:34 +0200 Subject: [PATCH 45/98] tests/rp: make cyw43-perf less strict. --- tests/rp/src/bin/cyw43-perf.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs index dd67914aa..7a94ea191 100644 --- a/tests/rp/src/bin/cyw43-perf.rs +++ b/tests/rp/src/bin/cyw43-perf.rs @@ -115,9 +115,9 @@ const WIFI_NETWORK: &str = "EmbassyTest"; const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; const TEST_DURATION: usize = 10; -const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 500; -const TEST_EXPECTED_UPLOAD_KBPS: usize = 500; -const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 400; +const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 300; +const TEST_EXPECTED_UPLOAD_KBPS: usize = 300; +const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 300; const RX_BUFFER_SIZE: usize = 4096; const TX_BUFFER_SIZE: usize = 4096; const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2); From 8ddeaddc674871db2125a7462c5b18eef938f497 Mon Sep 17 00:00:00 2001 From: Carl St-Laurent Date: Thu, 8 Jun 2023 20:46:48 -0400 Subject: [PATCH 46/98] Rename to follow ref manual and CubeIDE --- embassy-stm32/src/rcc/g4.rs | 20 ++++++++++---------- examples/stm32g4/src/bin/pll.rs | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 3ba9e7eb0..2b52416b2 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -17,7 +17,7 @@ pub const LSI_FREQ: Hertz = Hertz(32_000); pub enum ClockSrc { HSE(Hertz), HSI16, - PLL(PllSrc, PllM, PllN, PllClkDiv), + PLLCLK(PllSrc, PllM, PllN, PllR), } /// AHB prescaler @@ -61,27 +61,27 @@ impl Into for PllSrc { } #[derive(Clone, Copy)] -pub enum PllClkDiv { +pub enum PllR { Div2, Div4, Div6, Div8, } -impl PllClkDiv { +impl PllR { pub fn to_div(self) -> u32 { let val: u8 = self.into(); (val as u32 + 1) * 2 } } -impl From for u8 { - fn from(val: PllClkDiv) -> u8 { +impl From for u8 { + fn from(val: PllR) -> u8 { match val { - PllClkDiv::Div2 => 0b00, - PllClkDiv::Div4 => 0b01, - PllClkDiv::Div6 => 0b10, - PllClkDiv::Div8 => 0b11, + PllR::Div2 => 0b00, + PllR::Div4 => 0b01, + PllR::Div6 => 0b10, + PllR::Div8 => 0b11, } } } @@ -260,7 +260,7 @@ pub(crate) unsafe fn init(config: Config) { (freq.0, Sw::HSE) } - ClockSrc::PLL(src, prediv, mul, div) => { + ClockSrc::PLLCLK(src, prediv, mul, div) => { let src_freq = match src { PllSrc::HSI16 => { // Enable HSI16 as clock source for PLL diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs index bde30c284..8cee41e9b 100644 --- a/examples/stm32g4/src/bin/pll.rs +++ b/examples/stm32g4/src/bin/pll.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{ClockSrc, PllClkDiv, PllM, PllN, PllSrc}; +use embassy_stm32::rcc::{ClockSrc, PllM, PllN, PllR, PllSrc}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); // Configure PLL to max frequency of 170 MHz - config.rcc.mux = ClockSrc::PLL(PllSrc::HSI16, PllM::Div4, PllN::Mul85, PllClkDiv::Div2); + config.rcc.mux = ClockSrc::PLLCLK(PllSrc::HSI16, PllM::Div4, PllN::Mul85, PllR::Div2); let _p = embassy_stm32::init(config); info!("Hello World!"); From 3465452a93719cdb46a2af4b6d893da3aacc0a15 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 9 Jun 2023 03:33:39 +0200 Subject: [PATCH 47/98] fmt: remove unused defmt::timestamp! --- cyw43/src/fmt.rs | 3 --- embassy-cortex-m/src/fmt.rs | 3 --- embassy-futures/src/fmt.rs | 3 --- embassy-sync/src/fmt.rs | 3 --- 4 files changed, 12 deletions(-) diff --git a/cyw43/src/fmt.rs b/cyw43/src/fmt.rs index 5730447b3..9534c101c 100644 --- a/cyw43/src/fmt.rs +++ b/cyw43/src/fmt.rs @@ -197,9 +197,6 @@ macro_rules! unwrap { } } -#[cfg(feature = "defmt-timestamp-uptime")] -defmt::timestamp! {"{=u64:us}", crate::time::Instant::now().as_micros() } - #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct NoneError; diff --git a/embassy-cortex-m/src/fmt.rs b/embassy-cortex-m/src/fmt.rs index f8bb0a035..066970813 100644 --- a/embassy-cortex-m/src/fmt.rs +++ b/embassy-cortex-m/src/fmt.rs @@ -195,9 +195,6 @@ macro_rules! unwrap { } } -#[cfg(feature = "defmt-timestamp-uptime")] -defmt::timestamp! {"{=u64:us}", crate::time::Instant::now().as_micros() } - #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct NoneError; diff --git a/embassy-futures/src/fmt.rs b/embassy-futures/src/fmt.rs index f8bb0a035..066970813 100644 --- a/embassy-futures/src/fmt.rs +++ b/embassy-futures/src/fmt.rs @@ -195,9 +195,6 @@ macro_rules! unwrap { } } -#[cfg(feature = "defmt-timestamp-uptime")] -defmt::timestamp! {"{=u64:us}", crate::time::Instant::now().as_micros() } - #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct NoneError; diff --git a/embassy-sync/src/fmt.rs b/embassy-sync/src/fmt.rs index f8bb0a035..066970813 100644 --- a/embassy-sync/src/fmt.rs +++ b/embassy-sync/src/fmt.rs @@ -195,9 +195,6 @@ macro_rules! unwrap { } } -#[cfg(feature = "defmt-timestamp-uptime")] -defmt::timestamp! {"{=u64:us}", crate::time::Instant::now().as_micros() } - #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct NoneError; From d46b2b49c7941afed6578556dd2d6d98d072cbbb Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 9 Jun 2023 03:34:12 +0200 Subject: [PATCH 48/98] cyw43: remove pointless wait_complete. --- cyw43/src/control.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index 6919d569e..c67614dd6 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -381,10 +381,7 @@ impl<'a> Control<'a> { } let ioctl = CancelOnDrop(self.ioctl_state); - - ioctl.0.do_ioctl(kind, cmd, iface, buf).await; - let resp_len = ioctl.0.wait_complete().await; - + let resp_len = ioctl.0.do_ioctl(kind, cmd, iface, buf).await; ioctl.defuse(); resp_len From dc8e34420f434505829cafe0cb844af9c1c0b500 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 9 Jun 2023 16:02:12 +0200 Subject: [PATCH 49/98] Remove executor dep+reexports from HALs. Closes #1547 --- embassy-nrf/Cargo.toml | 3 +-- embassy-nrf/src/lib.rs | 1 - embassy-rp/Cargo.toml | 5 ++--- embassy-rp/src/lib.rs | 1 - embassy-stm32/Cargo.toml | 5 ++--- embassy-stm32/src/lib.rs | 1 - examples/nrf52840/src/bin/multiprio.rs | 2 +- examples/rp/src/bin/multiprio.rs | 2 +- 8 files changed, 7 insertions(+), 13 deletions(-) diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 5fab11f37..2bb14b9ed 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -32,7 +32,7 @@ rt = [ time = ["dep:embassy-time"] -defmt = ["dep:defmt", "embassy-executor/defmt", "embassy-sync/defmt", "embassy-usb-driver?/defmt", "embedded-io?/defmt", "embassy-embedded-hal/defmt"] +defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-usb-driver?/defmt", "embedded-io?/defmt", "embassy-embedded-hal/defmt"] # Enable nightly-only features nightly = ["embedded-hal-1", "embedded-hal-async", "dep:embassy-usb-driver", "embedded-storage-async", "dep:embedded-io", "embassy-embedded-hal/nightly"] @@ -91,7 +91,6 @@ _dppi = [] _gpio-p1 = [] [dependencies] -embassy-executor = { version = "0.2.0", path = "../embassy-executor", optional = true } embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]} diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index ddabf93a9..e2e514bb5 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -127,7 +127,6 @@ pub use chip::pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use chip::pac; pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE}; -pub use embassy_cortex_m::executor; pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; pub use crate::chip::interrupt; diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index ee06e99ce..ff2f9b2fd 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -48,7 +48,7 @@ boot2-w25x10cl = [] run-from-ram = [] # Enable nightly-only features -nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb-driver", "dep:embedded-io"] +nightly = ["embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb-driver", "dep:embedded-io"] # Implement embedded-hal 1.0 alpha traits. # Implement embedded-hal-async traits if `nightly` is set as well. @@ -56,7 +56,6 @@ unstable-traits = ["embedded-hal-1", "embedded-hal-nb"] [dependencies] embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-executor = { version = "0.2.0", path = "../embassy-executor" } embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-2"]} @@ -91,5 +90,5 @@ pio = {version= "0.2.1" } rp2040-boot2 = "0.3" [dev-dependencies] -embassy-executor = { version = "0.2.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] } +embassy-executor = { version = "0.2.0", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] } static_cell = "1.1" diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 4e4b76141..ad8c6f285 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -36,7 +36,6 @@ pub mod pio_instr_util; pub mod relocate; // Reexports -pub use embassy_cortex_m::executor; pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; #[cfg(feature = "unstable-pac")] pub use rp_pac as pac; diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index f1f894c6c..067f96756 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -32,7 +32,6 @@ flavors = [ [dependencies] embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-executor = { version = "0.2.0", path = "../embassy-executor" } embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} @@ -82,7 +81,7 @@ stm32-metapac = { version = "9", default-features = false, features = ["metadata default = ["rt"] rt = ["stm32-metapac/rt"] -defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-executor/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt"] +defmt = ["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"] memory-x = ["stm32-metapac/memory-x"] exti = [] @@ -101,7 +100,7 @@ time-driver-tim12 = ["_time-driver"] time-driver-tim15 = ["_time-driver"] # Enable nightly-only features -nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"] +nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"] # Reexport stm32-metapac at `embassy_stm32::pac`. # This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version. diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index f8857fdd2..e583993e5 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -103,7 +103,6 @@ macro_rules! bind_interrupts { // Reexports pub use _generated::{peripherals, Peripherals}; -pub use embassy_cortex_m::executor; use embassy_cortex_m::interrupt::Priority; pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; #[cfg(feature = "unstable-pac")] diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs index 851e189ea..37eb6565f 100644 --- a/examples/nrf52840/src/bin/multiprio.rs +++ b/examples/nrf52840/src/bin/multiprio.rs @@ -62,7 +62,7 @@ use core::mem; use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::{info, unwrap}; -use embassy_nrf::executor::{Executor, InterruptExecutor}; +use embassy_executor::{Executor, InterruptExecutor}; use embassy_nrf::interrupt; use embassy_nrf::pac::Interrupt; use embassy_time::{Duration, Instant, Timer}; diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs index 2f79ba49e..fea1d5b03 100644 --- a/examples/rp/src/bin/multiprio.rs +++ b/examples/rp/src/bin/multiprio.rs @@ -62,7 +62,7 @@ use core::mem; use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::{info, unwrap}; -use embassy_rp::executor::{Executor, InterruptExecutor}; +use embassy_executor::{Executor, InterruptExecutor}; use embassy_rp::interrupt; use embassy_rp::pac::Interrupt; use embassy_time::{Duration, Instant, Timer, TICK_HZ}; From 98c821ac39c65903057c2d8ed320d1616e9f23ae Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 9 Jun 2023 16:14:13 +0200 Subject: [PATCH 50/98] Remove embassy-cortex-m crate, move stuff to embassy-hal-common. --- .github/ci/doc.sh | 1 - embassy-cortex-m/Cargo.toml | 45 ---- embassy-cortex-m/src/fmt.rs | 225 ------------------ embassy-cortex-m/src/lib.rs | 9 - embassy-hal-common/Cargo.toml | 16 ++ .../build.rs | 0 .../src/interrupt.rs | 2 +- embassy-hal-common/src/lib.rs | 3 + embassy-nrf/Cargo.toml | 3 +- embassy-nrf/src/chips/nrf52805.rs | 2 +- embassy-nrf/src/chips/nrf52810.rs | 2 +- embassy-nrf/src/chips/nrf52811.rs | 2 +- embassy-nrf/src/chips/nrf52820.rs | 2 +- embassy-nrf/src/chips/nrf52832.rs | 2 +- embassy-nrf/src/chips/nrf52833.rs | 2 +- embassy-nrf/src/chips/nrf52840.rs | 2 +- embassy-nrf/src/chips/nrf5340_app.rs | 2 +- embassy-nrf/src/chips/nrf5340_net.rs | 2 +- embassy-nrf/src/chips/nrf9160.rs | 2 +- embassy-nrf/src/lib.rs | 2 +- embassy-rp/Cargo.toml | 3 +- embassy-rp/src/lib.rs | 4 +- embassy-stm32/Cargo.toml | 3 +- embassy-stm32/build.rs | 2 +- embassy-stm32/src/dma/bdma.rs | 2 +- embassy-stm32/src/dma/dma.rs | 2 +- embassy-stm32/src/dma/gpdma.rs | 2 +- embassy-stm32/src/dma/mod.rs | 2 +- embassy-stm32/src/lib.rs | 4 +- examples/rp/Cargo.toml | 2 +- examples/stm32c0/Cargo.toml | 2 +- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f2/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- examples/stm32wb/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- tests/stm32/Cargo.toml | 2 +- 50 files changed, 64 insertions(+), 328 deletions(-) delete mode 100644 embassy-cortex-m/Cargo.toml delete mode 100644 embassy-cortex-m/src/fmt.rs delete mode 100644 embassy-cortex-m/src/lib.rs rename {embassy-cortex-m => embassy-hal-common}/build.rs (100%) rename {embassy-cortex-m => embassy-hal-common}/src/interrupt.rs (99%) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 736249368..72c6465f7 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -14,7 +14,6 @@ docserver-builder -i ./embassy-boot/boot -o crates/embassy-boot/git.zup docserver-builder -i ./embassy-boot/nrf -o crates/embassy-boot-nrf/git.zup docserver-builder -i ./embassy-boot/rp -o crates/embassy-boot-rp/git.zup docserver-builder -i ./embassy-boot/stm32 -o crates/embassy-boot-stm32/git.zup -docserver-builder -i ./embassy-cortex-m -o crates/embassy-cortex-m/git.zup docserver-builder -i ./embassy-embedded-hal -o crates/embassy-embedded-hal/git.zup docserver-builder -i ./embassy-executor -o crates/embassy-executor/git.zup docserver-builder -i ./embassy-futures -o crates/embassy-futures/git.zup diff --git a/embassy-cortex-m/Cargo.toml b/embassy-cortex-m/Cargo.toml deleted file mode 100644 index 70adda7df..000000000 --- a/embassy-cortex-m/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "embassy-cortex-m" -version = "0.1.0" -edition = "2021" -license = "MIT OR Apache-2.0" - -[package.metadata.embassy_docs] -src_base = "https://github.com/embassy-rs/embassy/blob/embassy-cortex-m-v$VERSION/embassy-cortex-m/src/" -src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-cortex-m/src/" -features = ["prio-bits-3"] -flavors = [ - { name = "thumbv6m-none-eabi", target = "thumbv6m-none-eabi", features = [] }, - { name = "thumbv7m-none-eabi", target = "thumbv7m-none-eabi", features = [] }, - { name = "thumbv7em-none-eabi", target = "thumbv7em-none-eabi", features = [] }, - { name = "thumbv7em-none-eabihf", target = "thumbv7em-none-eabihf", features = [] }, - { name = "thumbv8m.main-none-eabihf", target = "thumbv8m.main-none-eabihf", features = [] }, -] - -[features] -default = [] - -# Define the number of NVIC priority bits. -prio-bits-0 = [] -prio-bits-1 = [] -prio-bits-2 = [] -prio-bits-3 = [] -prio-bits-4 = [] -prio-bits-5 = [] -prio-bits-6 = [] -prio-bits-7 = [] -prio-bits-8 = [] - -[dependencies] -defmt = { version = "0.3", optional = true } -log = { version = "0.4.14", optional = true } - -embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-executor = { version = "0.2.0", path = "../embassy-executor"} -embassy-macros = { version = "0.2.0", path = "../embassy-macros"} -embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common"} -atomic-polyfill = "1.0.1" -critical-section = "1.1" -cfg-if = "1.0.0" -cortex-m = "0.7.6" - diff --git a/embassy-cortex-m/src/fmt.rs b/embassy-cortex-m/src/fmt.rs deleted file mode 100644 index 066970813..000000000 --- a/embassy-cortex-m/src/fmt.rs +++ /dev/null @@ -1,225 +0,0 @@ -#![macro_use] -#![allow(unused_macros)] - -#[cfg(all(feature = "defmt", feature = "log"))] -compile_error!("You may not enable both `defmt` and `log` features."); - -macro_rules! assert { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::assert!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::assert!($($x)*); - } - }; -} - -macro_rules! assert_eq { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::assert_eq!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::assert_eq!($($x)*); - } - }; -} - -macro_rules! assert_ne { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::assert_ne!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::assert_ne!($($x)*); - } - }; -} - -macro_rules! debug_assert { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::debug_assert!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::debug_assert!($($x)*); - } - }; -} - -macro_rules! debug_assert_eq { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::debug_assert_eq!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::debug_assert_eq!($($x)*); - } - }; -} - -macro_rules! debug_assert_ne { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::debug_assert_ne!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::debug_assert_ne!($($x)*); - } - }; -} - -macro_rules! todo { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::todo!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::todo!($($x)*); - } - }; -} - -macro_rules! unreachable { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } - }; -} - -macro_rules! panic { - ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::panic!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::panic!($($x)*); - } - }; -} - -macro_rules! trace { - ($s:literal $(, $x:expr)* $(,)?) => { - { - #[cfg(feature = "log")] - ::log::trace!($s $(, $x)*); - #[cfg(feature = "defmt")] - ::defmt::trace!($s $(, $x)*); - #[cfg(not(any(feature = "log", feature="defmt")))] - let _ = ($( & $x ),*); - } - }; -} - -macro_rules! debug { - ($s:literal $(, $x:expr)* $(,)?) => { - { - #[cfg(feature = "log")] - ::log::debug!($s $(, $x)*); - #[cfg(feature = "defmt")] - ::defmt::debug!($s $(, $x)*); - #[cfg(not(any(feature = "log", feature="defmt")))] - let _ = ($( & $x ),*); - } - }; -} - -macro_rules! info { - ($s:literal $(, $x:expr)* $(,)?) => { - { - #[cfg(feature = "log")] - ::log::info!($s $(, $x)*); - #[cfg(feature = "defmt")] - ::defmt::info!($s $(, $x)*); - #[cfg(not(any(feature = "log", feature="defmt")))] - let _ = ($( & $x ),*); - } - }; -} - -macro_rules! warn { - ($s:literal $(, $x:expr)* $(,)?) => { - { - #[cfg(feature = "log")] - ::log::warn!($s $(, $x)*); - #[cfg(feature = "defmt")] - ::defmt::warn!($s $(, $x)*); - #[cfg(not(any(feature = "log", feature="defmt")))] - let _ = ($( & $x ),*); - } - }; -} - -macro_rules! error { - ($s:literal $(, $x:expr)* $(,)?) => { - { - #[cfg(feature = "log")] - ::log::error!($s $(, $x)*); - #[cfg(feature = "defmt")] - ::defmt::error!($s $(, $x)*); - #[cfg(not(any(feature = "log", feature="defmt")))] - let _ = ($( & $x ),*); - } - }; -} - -#[cfg(feature = "defmt")] -macro_rules! unwrap { - ($($x:tt)*) => { - ::defmt::unwrap!($($x)*) - }; -} - -#[cfg(not(feature = "defmt"))] -macro_rules! unwrap { - ($arg:expr) => { - match $crate::fmt::Try::into_result($arg) { - ::core::result::Result::Ok(t) => t, - ::core::result::Result::Err(e) => { - ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); - } - } - }; - ($arg:expr, $($msg:expr),+ $(,)? ) => { - match $crate::fmt::Try::into_result($arg) { - ::core::result::Result::Ok(t) => t, - ::core::result::Result::Err(e) => { - ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); - } - } - } -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct NoneError; - -pub trait Try { - type Ok; - type Error; - fn into_result(self) -> Result; -} - -impl Try for Option { - type Ok = T; - type Error = NoneError; - - #[inline] - fn into_result(self) -> Result { - self.ok_or(NoneError) - } -} - -impl Try for Result { - type Ok = T; - type Error = E; - - #[inline] - fn into_result(self) -> Self { - self - } -} diff --git a/embassy-cortex-m/src/lib.rs b/embassy-cortex-m/src/lib.rs deleted file mode 100644 index 7bc16d3ba..000000000 --- a/embassy-cortex-m/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! Embassy executor and interrupt handling specific to cortex-m devices. -#![no_std] -#![warn(missing_docs)] - -// This mod MUST go first, so that the others see its macros. -pub(crate) mod fmt; - -pub use embassy_executor as executor; -pub mod interrupt; diff --git a/embassy-hal-common/Cargo.toml b/embassy-hal-common/Cargo.toml index e8617c02f..18c758d7b 100644 --- a/embassy-hal-common/Cargo.toml +++ b/embassy-hal-common/Cargo.toml @@ -6,8 +6,24 @@ license = "MIT OR Apache-2.0" [features] +# Define the number of NVIC priority bits. +prio-bits-0 = [] +prio-bits-1 = [] +prio-bits-2 = [] +prio-bits-3 = [] +prio-bits-4 = [] +prio-bits-5 = [] +prio-bits-6 = [] +prio-bits-7 = [] +prio-bits-8 = [] + +cortex-m = ["dep:cortex-m", "dep:critical-section"] + [dependencies] defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } num-traits = { version = "0.2.14", default-features = false } + +cortex-m = { version = "0.7.6", optional = true } +critical-section = { version = "1", optional = true } \ No newline at end of file diff --git a/embassy-cortex-m/build.rs b/embassy-hal-common/build.rs similarity index 100% rename from embassy-cortex-m/build.rs rename to embassy-hal-common/build.rs diff --git a/embassy-cortex-m/src/interrupt.rs b/embassy-hal-common/src/interrupt.rs similarity index 99% rename from embassy-cortex-m/src/interrupt.rs rename to embassy-hal-common/src/interrupt.rs index e9fa43e87..b970aa2cd 100644 --- a/embassy-cortex-m/src/interrupt.rs +++ b/embassy-hal-common/src/interrupt.rs @@ -14,7 +14,7 @@ macro_rules! interrupt_mod { /// Interrupt definitions. pub mod interrupt { - pub use embassy_cortex_m::interrupt::{InterruptExt, Priority}; + pub use $crate::interrupt::{InterruptExt, Priority}; pub use crate::pac::Interrupt::*; pub use crate::pac::Interrupt; diff --git a/embassy-hal-common/src/lib.rs b/embassy-hal-common/src/lib.rs index b2a35cd35..235964aa4 100644 --- a/embassy-hal-common/src/lib.rs +++ b/embassy-hal-common/src/lib.rs @@ -11,3 +11,6 @@ mod peripheral; pub mod ratio; pub mod ring_buffer; pub use peripheral::{Peripheral, PeripheralRef}; + +#[cfg(feature = "cortex-m")] +pub mod interrupt; diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 2bb14b9ed..3e858f854 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -93,8 +93,7 @@ _gpio-p1 = [] [dependencies] embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]} -embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } +embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional=true } diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs index 8fbd760dc..8776000c8 100644 --- a/embassy-nrf/src/chips/nrf52805.rs +++ b/embassy-nrf/src/chips/nrf52805.rs @@ -208,7 +208,7 @@ impl_ppi_channel!(PPI_CH31, 31 => static); impl_saadc_input!(P0_04, ANALOG_INPUT2); impl_saadc_input!(P0_05, ANALOG_INPUT3); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index bbf8f7ccf..5519e8953 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -234,7 +234,7 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5); impl_saadc_input!(P0_30, ANALOG_INPUT6); impl_saadc_input!(P0_31, ANALOG_INPUT7); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index 31a8dd6af..d5367c59a 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -236,7 +236,7 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5); impl_saadc_input!(P0_30, ANALOG_INPUT6); impl_saadc_input!(P0_31, ANALOG_INPUT7); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs index 6a6f4fcf2..785170447 100644 --- a/embassy-nrf/src/chips/nrf52820.rs +++ b/embassy-nrf/src/chips/nrf52820.rs @@ -224,7 +224,7 @@ impl_ppi_channel!(PPI_CH29, 29 => static); impl_ppi_channel!(PPI_CH30, 30 => static); impl_ppi_channel!(PPI_CH31, 31 => static); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index e43b3d5b2..b77564a5c 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -263,7 +263,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index d95e3497c..bff7f4ebb 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -306,7 +306,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index 0094b1220..9b0050823 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -311,7 +311,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs index cb879f736..410ae921c 100644 --- a/embassy-nrf/src/chips/nrf5340_app.rs +++ b/embassy-nrf/src/chips/nrf5340_app.rs @@ -506,7 +506,7 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5); impl_saadc_input!(P0_19, ANALOG_INPUT6); impl_saadc_input!(P0_20, ANALOG_INPUT7); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( FPU, CACHE, SPU, diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs index 6e2c0bb67..6ac783085 100644 --- a/embassy-nrf/src/chips/nrf5340_net.rs +++ b/embassy-nrf/src/chips/nrf5340_net.rs @@ -342,7 +342,7 @@ impl_ppi_channel!(PPI_CH29, 29 => configurable); impl_ppi_channel!(PPI_CH30, 30 => configurable); impl_ppi_channel!(PPI_CH31, 31 => configurable); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( CLOCK_POWER, RADIO, RNG, diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs index 9944ac4af..67ea032ff 100644 --- a/embassy-nrf/src/chips/nrf9160.rs +++ b/embassy-nrf/src/chips/nrf9160.rs @@ -368,7 +368,7 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5); impl_saadc_input!(P0_19, ANALOG_INPUT6); impl_saadc_input!(P0_20, ANALOG_INPUT7); -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( SPU, CLOCK_POWER, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0, diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index e2e514bb5..691545662 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -98,7 +98,7 @@ mod chip; /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to /// prove at compile-time that the right interrupts have been bound. -// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. +// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index ff2f9b2fd..b68f95385 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -58,8 +58,7 @@ unstable-traits = ["embedded-hal-1", "embedded-hal-nb"] embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-2"]} -embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } +embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } atomic-polyfill = "1.0.1" diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index ad8c6f285..d6f73219f 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -45,7 +45,7 @@ pub(crate) use rp_pac as pac; #[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; -embassy_cortex_m::interrupt_mod!( +embassy_hal_common::interrupt_mod!( TIMER_IRQ_0, TIMER_IRQ_1, TIMER_IRQ_2, @@ -85,7 +85,7 @@ embassy_cortex_m::interrupt_mod!( /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to /// prove at compile-time that the right interrupts have been bound. -// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. +// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 067f96756..f876c7146 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -34,8 +34,7 @@ flavors = [ embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} -embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } +embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-4"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index ba5f91ccf..9e597f187 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -160,7 +160,7 @@ fn main() { } g.extend(quote! { - embassy_cortex_m::interrupt_mod!( + embassy_hal_common::interrupt_mod!( #( #irqs, )* diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 83ab4b18f..c0a503e25 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -6,7 +6,6 @@ use core::sync::atomic::{fence, Ordering}; use core::task::{Context, Poll, Waker}; use atomic_polyfill::AtomicUsize; -use embassy_cortex_m::interrupt::Priority; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -15,6 +14,7 @@ use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::BDMA_CHANNEL_COUNT; use crate::interrupt::typelevel::Interrupt; +use crate::interrupt::Priority; use crate::pac; use crate::pac::bdma::{regs, vals}; diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 17313b310..874cb013a 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -5,7 +5,6 @@ use core::sync::atomic::{fence, Ordering}; use core::task::{Context, Poll, Waker}; use atomic_polyfill::AtomicUsize; -use embassy_cortex_m::interrupt::Priority; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -14,6 +13,7 @@ use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::DMA_CHANNEL_COUNT; use crate::interrupt::typelevel::Interrupt; +use crate::interrupt::Priority; use crate::pac::dma::{regs, vals}; use crate::{interrupt, pac}; diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index 59ec205bf..3f0d5e8fa 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -5,7 +5,6 @@ use core::pin::Pin; use core::sync::atomic::{fence, Ordering}; use core::task::{Context, Poll}; -use embassy_cortex_m::interrupt::Priority; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -13,6 +12,7 @@ use super::word::{Word, WordSize}; use super::Dir; use crate::_generated::GPDMA_CHANNEL_COUNT; use crate::interrupt::typelevel::Interrupt; +use crate::interrupt::Priority; use crate::pac; use crate::pac::gpdma::vals; diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 3ac0d1b3d..0858587bd 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -26,11 +26,11 @@ pub mod word; use core::mem; -use embassy_cortex_m::interrupt::Priority; use embassy_hal_common::impl_peripheral; #[cfg(dmamux)] pub use self::dmamux::*; +use crate::interrupt::Priority; #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index e583993e5..f4ec0a80d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -79,7 +79,7 @@ pub use crate::_generated::interrupt; /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to /// prove at compile-time that the right interrupts have been bound. -// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`. +// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { @@ -103,13 +103,13 @@ macro_rules! bind_interrupts { // Reexports pub use _generated::{peripherals, Peripherals}; -use embassy_cortex_m::interrupt::Priority; pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; #[cfg(feature = "unstable-pac")] pub use stm32_metapac as pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use stm32_metapac as pac; +use crate::interrupt::Priority; #[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index e946b481d..48f3a26bb 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index ad11fbd1c..43f432520 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index ff134bb0e..8d2248ed0 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -13,7 +13,7 @@ defmt = "0.3" defmt-rtt = "0.4" panic-probe = "0.3" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] } static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 345e948a6..d34fd439a 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any", "unstable-traits" ] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index e4f97a589..5e3e0d0f7 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 0fe9cb122..29ab2009c 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 3a8efdd06..7ecb64fce 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers", "arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers", "arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 7a650067c..657251c50 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 4d7fc4548..c5245757b 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] } diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 00e2dae4c..f94df2dd3 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index d49a0dde7..ebe511347 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 08b57f988..62ef5e9e4 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 235f1b0b3..2ead714e4 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [features] default = ["nightly"] -nightly = ["embassy-stm32/nightly", "embassy-time/nightly", "embassy-time/unstable-traits", +nightly = ["embassy-stm32/nightly", "embassy-time/nightly", "embassy-time/unstable-traits", "embassy-executor/nightly", "embassy-lora", "lora-phy", "lorawan-device", "lorawan", "embedded-io/async"] [dependencies] diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 8b6508c87..93d48abeb 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 29d091f94..3bb473ef5 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits"] } diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 2ac9c180d..6035c291f 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index be205f880..e2318c3d6 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 8cfac772a..14897b171 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 6191d01e9..260f9afa1 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"] } embassy-embedded-hal = {version = "0.1.0", path = "../../embassy-embedded-hal" } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index fa97fdcc4..180d0ebbe 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" teleprobe-meta = "1.1" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] } embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index f1b0ba121..3f48bf3f1 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -25,7 +25,7 @@ not-gpdma = [] teleprobe-meta = "1" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } From 6653f262d7c2ec17e6aba91b89d3835504320a5a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 9 Jun 2023 16:44:58 +0200 Subject: [PATCH 51/98] examples: use nicer InterrupExt to set irq priority in multprio. --- examples/nrf52840/src/bin/multiprio.rs | 14 +++++--------- examples/rp/src/bin/multiprio.rs | 16 +++++----------- examples/stm32f0/src/bin/multiprio.rs | 14 +++++--------- examples/stm32f3/src/bin/multiprio.rs | 14 +++++--------- examples/stm32f4/src/bin/multiprio.rs | 14 +++++--------- 5 files changed, 25 insertions(+), 47 deletions(-) diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs index 37eb6565f..aab819117 100644 --- a/examples/nrf52840/src/bin/multiprio.rs +++ b/examples/nrf52840/src/bin/multiprio.rs @@ -57,14 +57,11 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::mem; - -use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::{info, unwrap}; use embassy_executor::{Executor, InterruptExecutor}; use embassy_nrf::interrupt; -use embassy_nrf::pac::Interrupt; +use embassy_nrf::interrupt::{InterruptExt, Priority}; use embassy_time::{Duration, Instant, Timer}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; @@ -130,16 +127,15 @@ fn main() -> ! { info!("Hello World!"); let _p = embassy_nrf::init(Default::default()); - let mut nvic: NVIC = unsafe { mem::transmute(()) }; // High-priority executor: SWI1_EGU1, priority level 6 - unsafe { nvic.set_priority(Interrupt::SWI1_EGU1, 6 << 5) }; - let spawner = EXECUTOR_HIGH.start(Interrupt::SWI1_EGU1); + interrupt::SWI1_EGU1.set_priority(Priority::P6); + let spawner = EXECUTOR_HIGH.start(interrupt::SWI1_EGU1); unwrap!(spawner.spawn(run_high())); // Medium-priority executor: SWI0_EGU0, priority level 7 - unsafe { nvic.set_priority(Interrupt::SWI0_EGU0, 7 << 5) }; - let spawner = EXECUTOR_MED.start(Interrupt::SWI0_EGU0); + interrupt::SWI0_EGU0.set_priority(Priority::P7); + let spawner = EXECUTOR_MED.start(interrupt::SWI0_EGU0); unwrap!(spawner.spawn(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs index fea1d5b03..9ace4cd68 100644 --- a/examples/rp/src/bin/multiprio.rs +++ b/examples/rp/src/bin/multiprio.rs @@ -57,14 +57,11 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::mem; - -use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::{info, unwrap}; use embassy_executor::{Executor, InterruptExecutor}; use embassy_rp::interrupt; -use embassy_rp::pac::Interrupt; +use embassy_rp::interrupt::{InterruptExt, Priority}; use embassy_time::{Duration, Instant, Timer, TICK_HZ}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; @@ -130,18 +127,15 @@ fn main() -> ! { info!("Hello World!"); let _p = embassy_rp::init(Default::default()); - let mut nvic: NVIC = unsafe { mem::transmute(()) }; // High-priority executor: SWI_IRQ_1, priority level 2 - unsafe { nvic.set_priority(Interrupt::SWI_IRQ_1, 2 << 6) }; - info!("bla: {}", NVIC::get_priority(Interrupt::SWI_IRQ_1)); - let spawner = EXECUTOR_HIGH.start(Interrupt::SWI_IRQ_1); + interrupt::SWI_IRQ_1.set_priority(Priority::P2); + let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); unwrap!(spawner.spawn(run_high())); // Medium-priority executor: SWI_IRQ_0, priority level 3 - unsafe { nvic.set_priority(Interrupt::SWI_IRQ_0, 3 << 6) }; - info!("bla: {}", NVIC::get_priority(Interrupt::SWI_IRQ_0)); - let spawner = EXECUTOR_MED.start(Interrupt::SWI_IRQ_0); + interrupt::SWI_IRQ_0.set_priority(Priority::P3); + let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); unwrap!(spawner.spawn(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs index 430a805fc..988ffeef1 100644 --- a/examples/stm32f0/src/bin/multiprio.rs +++ b/examples/stm32f0/src/bin/multiprio.rs @@ -57,14 +57,11 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::mem; - -use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::*; use embassy_executor::{Executor, InterruptExecutor}; use embassy_stm32::interrupt; -use embassy_stm32::pac::Interrupt; +use embassy_stm32::interrupt::{InterruptExt, Priority}; use embassy_time::{Duration, Instant, Timer}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; @@ -129,16 +126,15 @@ unsafe fn USART2() { fn main() -> ! { // Initialize and create handle for devicer peripherals let _p = embassy_stm32::init(Default::default()); - let mut nvic: NVIC = unsafe { mem::transmute(()) }; // High-priority executor: USART1, priority level 6 - unsafe { nvic.set_priority(Interrupt::USART1, 6 << 4) }; - let spawner = EXECUTOR_HIGH.start(Interrupt::USART1); + interrupt::USART1.set_priority(Priority::P6); + let spawner = EXECUTOR_HIGH.start(interrupt::USART1); unwrap!(spawner.spawn(run_high())); // Medium-priority executor: USART2, priority level 7 - unsafe { nvic.set_priority(Interrupt::USART2, 7 << 4) }; - let spawner = EXECUTOR_MED.start(Interrupt::USART2); + interrupt::USART2.set_priority(Priority::P7); + let spawner = EXECUTOR_MED.start(interrupt::USART2); unwrap!(spawner.spawn(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs index 5d010f799..80bf59deb 100644 --- a/examples/stm32f3/src/bin/multiprio.rs +++ b/examples/stm32f3/src/bin/multiprio.rs @@ -57,14 +57,11 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::mem; - -use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::*; use embassy_executor::{Executor, InterruptExecutor}; use embassy_stm32::interrupt; -use embassy_stm32::pac::Interrupt; +use embassy_stm32::interrupt::{InterruptExt, Priority}; use embassy_time::{Duration, Instant, Timer}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; @@ -130,16 +127,15 @@ fn main() -> ! { info!("Hello World!"); let _p = embassy_stm32::init(Default::default()); - let mut nvic: NVIC = unsafe { mem::transmute(()) }; // High-priority executor: UART4, priority level 6 - unsafe { nvic.set_priority(Interrupt::UART4, 6 << 4) }; - let spawner = EXECUTOR_HIGH.start(Interrupt::UART4); + interrupt::UART4.set_priority(Priority::P6); + let spawner = EXECUTOR_HIGH.start(interrupt::UART4); unwrap!(spawner.spawn(run_high())); // Medium-priority executor: UART5, priority level 7 - unsafe { nvic.set_priority(Interrupt::UART5, 7 << 4) }; - let spawner = EXECUTOR_MED.start(Interrupt::UART5); + interrupt::UART5.set_priority(Priority::P7); + let spawner = EXECUTOR_MED.start(interrupt::UART5); unwrap!(spawner.spawn(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index 5d010f799..80bf59deb 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs @@ -57,14 +57,11 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::mem; - -use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::*; use embassy_executor::{Executor, InterruptExecutor}; use embassy_stm32::interrupt; -use embassy_stm32::pac::Interrupt; +use embassy_stm32::interrupt::{InterruptExt, Priority}; use embassy_time::{Duration, Instant, Timer}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; @@ -130,16 +127,15 @@ fn main() -> ! { info!("Hello World!"); let _p = embassy_stm32::init(Default::default()); - let mut nvic: NVIC = unsafe { mem::transmute(()) }; // High-priority executor: UART4, priority level 6 - unsafe { nvic.set_priority(Interrupt::UART4, 6 << 4) }; - let spawner = EXECUTOR_HIGH.start(Interrupt::UART4); + interrupt::UART4.set_priority(Priority::P6); + let spawner = EXECUTOR_HIGH.start(interrupt::UART4); unwrap!(spawner.spawn(run_high())); // Medium-priority executor: UART5, priority level 7 - unsafe { nvic.set_priority(Interrupt::UART5, 7 << 4) }; - let spawner = EXECUTOR_MED.start(Interrupt::UART5); + interrupt::UART5.set_priority(Priority::P7); + let spawner = EXECUTOR_MED.start(interrupt::UART5); unwrap!(spawner.spawn(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV From ca8957da435eb91242fa33eb986e80a33bbc4da0 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 12:27:51 +0100 Subject: [PATCH 52/98] stm32/ipcc: move tl_mbox into `embassy-stm32-wpan` --- embassy-stm32-wpan/Cargo.toml | 23 ++ .../tl_mbox => embassy-stm32-wpan/src}/ble.rs | 37 +-- .../src}/channels.rs | 16 +- .../tl_mbox => embassy-stm32-wpan/src}/cmd.rs | 4 +- .../src}/consts.rs | 0 .../tl_mbox => embassy-stm32-wpan/src}/evt.rs | 14 +- embassy-stm32-wpan/src/fmt.rs | 225 +++++++++++++++ .../mod.rs => embassy-stm32-wpan/src/lib.rs | 266 +++--------------- .../tl_mbox => embassy-stm32-wpan/src}/mm.rs | 18 +- embassy-stm32-wpan/src/rc.rs | 50 ++++ .../src}/shci.rs | 4 +- .../tl_mbox => embassy-stm32-wpan/src}/sys.rs | 36 +-- embassy-stm32-wpan/src/tables.rs | 175 ++++++++++++ .../src}/unsafe_linked_list.rs | 9 +- embassy-stm32/src/{tl_mbox => }/ipcc.rs | 60 ++++ embassy-stm32/src/lib.rs | 4 +- embassy-stm32/src/tl_mbox/hci.rs | 60 ---- examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | 20 +- 18 files changed, 652 insertions(+), 369 deletions(-) create mode 100644 embassy-stm32-wpan/Cargo.toml rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/ble.rs (72%) rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/channels.rs (90%) rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/cmd.rs (94%) rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/consts.rs (100%) rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/evt.rs (94%) create mode 100644 embassy-stm32-wpan/src/fmt.rs rename embassy-stm32/src/tl_mbox/mod.rs => embassy-stm32-wpan/src/lib.rs (59%) rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/mm.rs (87%) create mode 100644 embassy-stm32-wpan/src/rc.rs rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/shci.rs (97%) rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/sys.rs (68%) create mode 100644 embassy-stm32-wpan/src/tables.rs rename {embassy-stm32/src/tl_mbox => embassy-stm32-wpan/src}/unsafe_linked_list.rs (92%) rename embassy-stm32/src/{tl_mbox => }/ipcc.rs (75%) delete mode 100644 embassy-stm32/src/tl_mbox/hci.rs diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml new file mode 100644 index 000000000..a6673d472 --- /dev/null +++ b/embassy-stm32-wpan/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "embassy-stm32-wpan" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" + +[dependencies] +embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", features = ["stm32wb55rg"] } +embassy-sync = { version = "0.2.0", path = "../embassy-sync" } +embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } +embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} +embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } +embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } + +defmt = { version = "0.3", optional = true } +cortex-m = "0.7.6" +heapless = "0.7.16" + +bit_field = "0.10.2" + +[features] +defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32-wpan/src/ble.rs similarity index 72% rename from embassy-stm32/src/tl_mbox/ble.rs rename to embassy-stm32-wpan/src/ble.rs index 45bf81ef2..4546bde07 100644 --- a/embassy-stm32/src/tl_mbox/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -1,23 +1,24 @@ -use embassy_futures::block_on; +use core::mem::MaybeUninit; -use super::cmd::{CmdPacket, CmdSerial}; -use super::consts::TlPacketType; -use super::evt::EvtBox; -use super::ipcc::Ipcc; -use super::unsafe_linked_list::LinkedListNode; -use super::{ - channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, HEAPLESS_EVT_QUEUE, TL_BLE_TABLE, - TL_REF_TABLE, +use embassy_stm32::ipcc::Ipcc; + +use crate::cmd::{CmdPacket, CmdSerial}; +use crate::consts::TlPacketType; +use crate::evt::EvtBox; +use crate::tables::BleTable; +use crate::unsafe_linked_list::LinkedListNode; +use crate::{ + channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_CHANNEL, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_REF_TABLE, }; pub struct Ble; impl Ble { - pub(super) fn new() -> Self { + pub(super) fn enable() { unsafe { LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); - TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { + TL_BLE_TABLE = MaybeUninit::new(BleTable { pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), pcs_buffer: CS_BUFFER.as_ptr().cast(), pevt_queue: EVT_QUEUE.as_ptr().cast(), @@ -26,8 +27,6 @@ impl Ble { } Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); - - Ble } pub(super) fn evt_handler() { @@ -41,20 +40,22 @@ impl Ble { let event = node_ptr.cast(); let event = EvtBox::new(event); - block_on(HEAPLESS_EVT_QUEUE.send(event)); + EVT_CHANNEL.try_send(event).unwrap(); } } Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); } - pub(super) fn acl_data_handler(&self) { + pub(super) fn acl_data_handler() { Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); // TODO: ACL data ack to the user } - pub fn send_cmd(buf: &[u8]) { + pub fn ble_send_cmd(buf: &[u8]) { + debug!("writing ble cmd"); + unsafe { let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; @@ -70,8 +71,8 @@ impl Ble { } #[allow(dead_code)] // Not used currently but reserved - pub(super) fn send_acl_data() { - let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; + pub(super) fn ble_send_acl_data() { + let mut cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; diff --git a/embassy-stm32/src/tl_mbox/channels.rs b/embassy-stm32-wpan/src/channels.rs similarity index 90% rename from embassy-stm32/src/tl_mbox/channels.rs rename to embassy-stm32-wpan/src/channels.rs index 25a065ba4..9a2be1cfa 100644 --- a/embassy-stm32/src/tl_mbox/channels.rs +++ b/embassy-stm32-wpan/src/channels.rs @@ -50,36 +50,30 @@ //! pub mod cpu1 { - use crate::tl_mbox::ipcc::IpccChannel; + use embassy_stm32::ipcc::IpccChannel; - // Not used currently but reserved pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; - // Not used currently but reserved pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2; - #[allow(dead_code)] // Not used currently but reserved pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; #[allow(dead_code)] // Not used currently but reserved pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3; #[allow(dead_code)] // Not used currently but reserved pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; - // Not used currently but reserved - pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4; #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4; pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; #[allow(dead_code)] // Not used currently but reserved pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; #[allow(dead_code)] // Not used currently but reserved pub const IPCC_BLE_LLD_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; - #[allow(dead_code)] // Not used currently but reserved pub const IPCC_HCI_ACL_DATA_CHANNEL: IpccChannel = IpccChannel::Channel6; } pub mod cpu2 { - use crate::tl_mbox::ipcc::IpccChannel; + use embassy_stm32::ipcc::IpccChannel; pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1; pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2; - #[allow(dead_code)] // Not used currently but reserved pub const IPCC_THREAD_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; #[allow(dead_code)] // Not used currently but reserved pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; @@ -88,10 +82,8 @@ pub mod cpu2 { #[allow(dead_code)] // Not used currently but reserved pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_BLE_LLD_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; - #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_BLE_LLDÇM0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4; - #[allow(dead_code)] // Not used currently but reserved pub const IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel5; #[allow(dead_code)] // Not used currently but reserved pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; diff --git a/embassy-stm32/src/tl_mbox/cmd.rs b/embassy-stm32-wpan/src/cmd.rs similarity index 94% rename from embassy-stm32/src/tl_mbox/cmd.rs rename to embassy-stm32-wpan/src/cmd.rs index 781aa669d..1f7dae7f7 100644 --- a/embassy-stm32/src/tl_mbox/cmd.rs +++ b/embassy-stm32-wpan/src/cmd.rs @@ -1,5 +1,5 @@ -use crate::tl_mbox::evt::{EvtPacket, EvtSerial}; -use crate::tl_mbox::{PacketHeader, TL_EVT_HEADER_SIZE}; +use crate::evt::{EvtPacket, EvtSerial}; +use crate::{PacketHeader, TL_EVT_HEADER_SIZE}; #[derive(Copy, Clone)] #[repr(C, packed)] diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32-wpan/src/consts.rs similarity index 100% rename from embassy-stm32/src/tl_mbox/consts.rs rename to embassy-stm32-wpan/src/consts.rs diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32-wpan/src/evt.rs similarity index 94% rename from embassy-stm32/src/tl_mbox/evt.rs rename to embassy-stm32-wpan/src/evt.rs index 77ce7b4ca..b53fe506e 100644 --- a/embassy-stm32/src/tl_mbox/evt.rs +++ b/embassy-stm32-wpan/src/evt.rs @@ -2,13 +2,13 @@ use core::mem::MaybeUninit; use super::cmd::{AclDataPacket, AclDataSerial}; use super::consts::TlPacketType; -use super::mm::MemoryManager; use super::{PacketHeader, TL_EVT_HEADER_SIZE}; +use crate::mm; /** * The payload of `Evt` for a command status event */ -#[derive(Debug, Copy, Clone)] +#[derive(Copy, Clone)] #[repr(C, packed)] pub struct CsEvt { pub status: u8, @@ -19,7 +19,7 @@ pub struct CsEvt { /** * The payload of `Evt` for a command complete event */ -#[derive(Debug, Copy, Clone, Default)] +#[derive(Copy, Clone, Default)] #[repr(C, packed)] pub struct CcEvt { pub num_cmd: u8, @@ -41,14 +41,14 @@ impl CcEvt { } } -#[derive(Debug, Copy, Clone, Default)] +#[derive(Copy, Clone, Default)] #[repr(C, packed)] pub struct AsynchEvt { sub_evt_code: u16, payload: [u8; 1], } -#[derive(Debug, Copy, Clone, Default)] +#[derive(Copy, Clone, Default)] #[repr(C, packed)] pub struct Evt { pub evt_code: u8, @@ -56,7 +56,7 @@ pub struct Evt { pub payload: [u8; 1], } -#[derive(Debug, Copy, Clone, Default)] +#[derive(Copy, Clone, Default)] #[repr(C, packed)] pub struct EvtSerial { pub kind: u8, @@ -171,6 +171,6 @@ impl EvtBox { impl Drop for EvtBox { fn drop(&mut self) { - MemoryManager::evt_drop(self.ptr); + mm::MemoryManager::evt_drop(self.ptr); } } diff --git a/embassy-stm32-wpan/src/fmt.rs b/embassy-stm32-wpan/src/fmt.rs new file mode 100644 index 000000000..066970813 --- /dev/null +++ b/embassy-stm32-wpan/src/fmt.rs @@ -0,0 +1,225 @@ +#![macro_use] +#![allow(unused_macros)] + +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You may not enable both `defmt` and `log` features."); + +macro_rules! assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert!($($x)*); + } + }; +} + +macro_rules! assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_eq!($($x)*); + } + }; +} + +macro_rules! assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_ne!($($x)*); + } + }; +} + +macro_rules! debug_assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert!($($x)*); + } + }; +} + +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_eq!($($x)*); + } + }; +} + +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_ne!($($x)*); + } + }; +} + +macro_rules! todo { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::todo!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::todo!($($x)*); + } + }; +} + +macro_rules! unreachable { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } + }; +} + +macro_rules! panic { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::panic!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::panic!($($x)*); + } + }; +} + +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::trace!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::trace!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::debug!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::debug!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::info!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::info!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::warn!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::warn!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::error!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::error!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unwrap { + ($arg:expr) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32-wpan/src/lib.rs similarity index 59% rename from embassy-stm32/src/tl_mbox/mod.rs rename to embassy-stm32-wpan/src/lib.rs index 21a954417..b3206428e 100644 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -1,30 +1,37 @@ +#![no_std] + +// This must go FIRST so that all the other modules see its macros. +pub mod fmt; + use core::mem::MaybeUninit; -use bit_field::BitField; +use cmd::CmdPacket; use embassy_cortex_m::interrupt::Interrupt; use embassy_futures::block_on; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_stm32::interrupt; +use embassy_stm32::ipcc::{Config, Ipcc}; +use embassy_stm32::peripherals::IPCC; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_sync::signal::Signal; - -use self::cmd::{AclDataPacket, CmdPacket}; -use self::evt::{CcEvt, EvtBox}; -use self::ipcc::{Config, Ipcc}; -use self::unsafe_linked_list::LinkedListNode; -use crate::interrupt; -use crate::peripherals::IPCC; +use evt::{CcEvt, EvtBox}; +use tables::{ + BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable, + WirelessFwInfoTable, +}; +use unsafe_linked_list::LinkedListNode; pub mod ble; pub mod channels; pub mod cmd; pub mod consts; pub mod evt; -pub mod hci; -pub mod ipcc; pub mod mm; +pub mod rc; pub mod shci; pub mod sys; +pub mod tables; pub mod unsafe_linked_list; /// Interrupt handler. @@ -32,16 +39,12 @@ pub struct ReceiveInterruptHandler {} impl interrupt::Handler for ReceiveInterruptHandler { unsafe fn on_interrupt() { - debug!("ipcc rx interrupt"); - if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { - debug!("sys evt"); + debug!("RX SYS evt"); sys::Sys::evt_handler(); } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { - debug!("ble evt"); + debug!("RX BLE evt"); ble::Ble::evt_handler(); - } else { - todo!() } STATE.signal(()); @@ -52,198 +55,23 @@ pub struct TransmitInterruptHandler {} impl interrupt::Handler for TransmitInterruptHandler { unsafe fn on_interrupt() { - debug!("ipcc tx interrupt"); - if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { - debug!("sys cmd rsp"); - // TODO: handle this case + debug!("TX SYS cmd rsp"); let cc = sys::Sys::cmd_evt_handler(); - let a = unsafe { core::slice::from_raw_parts(&cc as *const _ as *const u8, core::mem::size_of::()) }; - debug!("{:#04x}", a); LAST_CC_EVT.signal(cc); } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { - debug!("mm"); + debug!("TX MM release"); mm::MemoryManager::free_buf_handler(); - } else { - todo!() + } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL) { + debug!("TX HCI acl"); + ble::Ble::acl_data_handler(); } STATE.signal(()); } } -#[derive(Debug, Copy, Clone)] -#[repr(C, packed)] -pub struct SafeBootInfoTable { - version: u32, -} - -#[derive(Debug, Copy, Clone)] -#[repr(C, packed)] -pub struct RssInfoTable { - version: u32, - memory_size: u32, - rss_info: u32, -} - -/** - * Version - * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version - * [4:7] = branch - 0: Mass Market - x: ... - * [8:15] = Subversion - * [16:23] = Version minor - * [24:31] = Version major - * - * Memory Size - * [0:7] = Flash ( Number of 4k sector) - * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension ) - * [16:23] = SRAM2b ( Number of 1k sector) - * [24:31] = SRAM2a ( Number of 1k sector) - */ -#[derive(Debug, Copy, Clone)] -#[repr(C, packed)] -pub struct WirelessFwInfoTable { - version: u32, - memory_size: u32, - thread_info: u32, - ble_info: u32, -} - -impl WirelessFwInfoTable { - pub fn version_major(&self) -> u8 { - let version = self.version; - (version.get_bits(24..31) & 0xff) as u8 - } - - pub fn version_minor(&self) -> u8 { - let version = self.version; - (version.clone().get_bits(16..23) & 0xff) as u8 - } - - pub fn subversion(&self) -> u8 { - let version = self.version; - (version.clone().get_bits(8..15) & 0xff) as u8 - } - - /// Size of FLASH, expressed in number of 4K sectors. - pub fn flash_size(&self) -> u8 { - let memory_size = self.memory_size; - (memory_size.clone().get_bits(0..7) & 0xff) as u8 - } - - /// Size of SRAM2a, expressed in number of 1K sectors. - pub fn sram2a_size(&self) -> u8 { - let memory_size = self.memory_size; - (memory_size.clone().get_bits(24..31) & 0xff) as u8 - } - - /// Size of SRAM2b, expressed in number of 1K sectors. - pub fn sram2b_size(&self) -> u8 { - let memory_size = self.memory_size; - (memory_size.clone().get_bits(16..23) & 0xff) as u8 - } -} - -#[derive(Debug, Clone)] -#[repr(C, align(4))] -pub struct DeviceInfoTable { - pub safe_boot_info_table: SafeBootInfoTable, - pub rss_info_table: RssInfoTable, - pub wireless_fw_info_table: WirelessFwInfoTable, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct BleTable { - pcmd_buffer: *mut CmdPacket, - pcs_buffer: *const u8, - pevt_queue: *const u8, - phci_acl_data_buffer: *mut AclDataPacket, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct ThreadTable { - nostack_buffer: *const u8, - clicmdrsp_buffer: *const u8, - otcmdrsp_buffer: *const u8, -} - -// TODO: use later -#[derive(Debug)] -#[repr(C, align(4))] -pub struct LldTestsTable { - clicmdrsp_buffer: *const u8, - m0cmd_buffer: *const u8, -} - -// TODO: use later -#[derive(Debug)] -#[repr(C, align(4))] -pub struct BleLldTable { - cmdrsp_buffer: *const u8, - m0cmd_buffer: *const u8, -} - -// TODO: use later -#[derive(Debug)] -#[repr(C, align(4))] -pub struct ZigbeeTable { - notif_m0_to_m4_buffer: *const u8, - appli_cmd_m4_to_m0_bufer: *const u8, - request_m0_to_m4_buffer: *const u8, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct SysTable { - pcmd_buffer: *mut CmdPacket, - sys_queue: *const LinkedListNode, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct MemManagerTable { - spare_ble_buffer: *const u8, - spare_sys_buffer: *const u8, - - blepool: *const u8, - blepoolsize: u32, - - pevt_free_buffer_queue: *mut LinkedListNode, - - traces_evt_pool: *const u8, - tracespoolsize: u32, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct TracesTable { - traces_queue: *const u8, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct Mac802_15_4Table { - p_cmdrsp_buffer: *const u8, - p_notack_buffer: *const u8, - evt_queue: *const u8, -} - -/// Reference table. Contains pointers to all other tables. -#[derive(Debug, Copy, Clone)] -#[repr(C)] -pub struct RefTable { - device_info_table: *const DeviceInfoTable, - ble_table: *const BleTable, - thread_table: *const ThreadTable, - sys_table: *const SysTable, - mem_manager_table: *const MemManagerTable, - traces_table: *const TracesTable, - mac_802_15_4_table: *const Mac802_15_4Table, -} - #[link_section = "TL_REF_TABLE"] pub static mut TL_REF_TABLE: MaybeUninit = MaybeUninit::uninit(); @@ -338,25 +166,21 @@ static mut BLE_CMD_BUFFER: MaybeUninit = MaybeUninit::uninit(); // fuck these "magic" numbers from ST ---v---v static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); -static HEAPLESS_EVT_QUEUE: Channel = Channel::new(); - -static STATE: Signal = Signal::new(); - /// current event that is produced during IPCC IRQ handler execution /// on SYS channel +static EVT_CHANNEL: Channel = Channel::new(); + /// last received Command Complete event static LAST_CC_EVT: Signal = Signal::new(); -pub struct TlMbox<'d> { - sys: sys::Sys, - ble: ble::Ble, - _mm: mm::MemoryManager, +static STATE: Signal = Signal::new(); +pub struct TlMbox<'d> { _ipcc: PeripheralRef<'d, IPCC>, } impl<'d> TlMbox<'d> { - pub fn new( + pub fn init( ipcc: impl Peripheral

+ 'd, _irqs: impl interrupt::Binding + interrupt::Binding, @@ -365,7 +189,7 @@ impl<'d> TlMbox<'d> { into_ref!(ipcc); unsafe { - TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { + TL_REF_TABLE = MaybeUninit::new(RefTable { device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), ble_table: TL_BLE_TABLE.as_ptr(), thread_table: TL_THREAD_TABLE.as_ptr(), @@ -394,23 +218,20 @@ impl<'d> TlMbox<'d> { Ipcc::enable(config); - let sys = sys::Sys::new(); - let ble = ble::Ble::new(); - let mm = mm::MemoryManager::new(); + sys::Sys::enable(); + ble::Ble::enable(); + mm::MemoryManager::enable(); // enable interrupts - crate::interrupt::IPCC_C1_RX::unpend(); - crate::interrupt::IPCC_C1_TX::unpend(); + interrupt::IPCC_C1_RX::unpend(); + interrupt::IPCC_C1_TX::unpend(); - unsafe { crate::interrupt::IPCC_C1_RX::enable() }; - unsafe { crate::interrupt::IPCC_C1_TX::enable() }; + unsafe { interrupt::IPCC_C1_RX::enable() }; + unsafe { interrupt::IPCC_C1_TX::enable() }; - Self { - sys, - ble, - _mm: mm, - _ipcc: ipcc, - } + STATE.reset(); + + Self { _ipcc: ipcc } } /// Returns CPU2 wireless firmware information (if present). @@ -429,16 +250,15 @@ impl<'d> TlMbox<'d> { /// /// Internal event queu is populated in IPCC_RX_IRQ handler pub fn dequeue_event(&mut self) -> Option { - HEAPLESS_EVT_QUEUE.try_recv().ok() + EVT_CHANNEL.try_recv().ok() } /// retrieves last Command Complete event and removes it from mailbox pub fn pop_last_cc_evt(&mut self) -> Option { if LAST_CC_EVT.signaled() { - let cc = Some(block_on(LAST_CC_EVT.wait())); + let cc = block_on(LAST_CC_EVT.wait()); LAST_CC_EVT.reset(); - - cc + Some(cc) } else { None } diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32-wpan/src/mm.rs similarity index 87% rename from embassy-stm32/src/tl_mbox/mm.rs rename to embassy-stm32-wpan/src/mm.rs index a40438499..ed13b0dbf 100644 --- a/embassy-stm32/src/tl_mbox/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -2,18 +2,20 @@ use core::mem::MaybeUninit; -use super::evt::EvtPacket; -use super::ipcc::Ipcc; -use super::unsafe_linked_list::LinkedListNode; -use super::{ - channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, - SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, +use embassy_stm32::ipcc::Ipcc; + +use crate::evt::EvtPacket; +use crate::tables::MemManagerTable; +use crate::unsafe_linked_list::LinkedListNode; +use crate::{ + channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF, + TL_MEM_MANAGER_TABLE, TL_REF_TABLE, }; pub(super) struct MemoryManager; impl MemoryManager { - pub fn new() -> Self { + pub fn enable() { unsafe { LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); @@ -28,8 +30,6 @@ impl MemoryManager { tracespoolsize: 0, }); } - - MemoryManager } pub fn evt_drop(evt: *mut EvtPacket) { diff --git a/embassy-stm32-wpan/src/rc.rs b/embassy-stm32-wpan/src/rc.rs new file mode 100644 index 000000000..aae2265ed --- /dev/null +++ b/embassy-stm32-wpan/src/rc.rs @@ -0,0 +1,50 @@ +use crate::ble::Ble; +use crate::consts::TlPacketType; +use crate::{shci, TlMbox, STATE}; + +pub struct RadioCoprocessor<'d> { + mbox: TlMbox<'d>, + rx_buf: [u8; 500], +} + +impl<'d> RadioCoprocessor<'d> { + pub fn new(mbox: TlMbox<'d>) -> Self { + Self { + mbox, + rx_buf: [0u8; 500], + } + } + + pub fn write(&self, buf: &[u8]) { + let cmd_code = buf[0]; + let cmd = TlPacketType::try_from(cmd_code).unwrap(); + + match &cmd { + TlPacketType::BleCmd => Ble::ble_send_cmd(buf), + _ => todo!(), + } + } + + pub async fn read(&mut self) -> &[u8] { + loop { + STATE.wait().await; + + while let Some(evt) = self.mbox.dequeue_event() { + let event = evt.evt(); + + evt.write(&mut self.rx_buf).unwrap(); + + if event.kind() == 18 { + shci::shci_ble_init(Default::default()); + self.rx_buf[0] = 0x04; + } + } + + if self.mbox.pop_last_cc_evt().is_some() { + continue; + } + + return &self.rx_buf; + } + } +} diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32-wpan/src/shci.rs similarity index 97% rename from embassy-stm32/src/tl_mbox/shci.rs rename to embassy-stm32-wpan/src/shci.rs index b19baa702..4f4d08886 100644 --- a/embassy-stm32/src/tl_mbox/shci.rs +++ b/embassy-stm32-wpan/src/shci.rs @@ -75,7 +75,7 @@ pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; pub fn shci_ble_init(param: ShciBleInitCmdParam) { - debug!("shci init"); + debug!("sending SHCI"); let mut packet = ShciBleInitCmdPacket { header: ShciHeader::default(), @@ -95,6 +95,6 @@ pub fn shci_ble_init(param: ShciBleInitCmdParam) { p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; - sys::send_cmd(); + sys::Sys::send_cmd(); } } diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32-wpan/src/sys.rs similarity index 68% rename from embassy-stm32/src/tl_mbox/sys.rs rename to embassy-stm32-wpan/src/sys.rs index c87aa440c..a19d12d27 100644 --- a/embassy-stm32/src/tl_mbox/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -1,27 +1,27 @@ -use embassy_futures::block_on; +use core::mem::MaybeUninit; -use super::cmd::{CmdPacket, CmdSerial}; -use super::evt::{CcEvt, EvtBox, EvtSerial}; -use super::ipcc::Ipcc; -use super::unsafe_linked_list::LinkedListNode; -use super::{channels, SysTable, HEAPLESS_EVT_QUEUE, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; +use embassy_stm32::ipcc::Ipcc; + +use crate::cmd::{CmdPacket, CmdSerial}; +use crate::evt::{CcEvt, EvtBox, EvtSerial}; +use crate::tables::SysTable; +use crate::unsafe_linked_list::LinkedListNode; +use crate::{channels, EVT_CHANNEL, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; pub struct Sys; impl Sys { - pub fn new() -> Self { + pub fn enable() { unsafe { LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); - TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { + TL_SYS_TABLE = MaybeUninit::new(SysTable { pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), }) } Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); - - Sys } pub fn cmd_evt_handler() -> CcEvt { @@ -38,12 +38,6 @@ impl Sys { // 5. profit unsafe { let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; - - let a = unsafe { - core::slice::from_raw_parts(&pcmd as *const _ as *const u8, core::mem::size_of::()) - }; - debug!("shci response {:#04x}", a); - let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial; let evt_serial: *const EvtSerial = cmd_serial.cast(); let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); @@ -62,15 +56,15 @@ impl Sys { let event = node_ptr.cast(); let event = EvtBox::new(event); - block_on(HEAPLESS_EVT_QUEUE.send(event)); + EVT_CHANNEL.try_send(event).unwrap(); } } Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); } -} -pub fn send_cmd() { - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); + pub fn send_cmd() { + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); + } } diff --git a/embassy-stm32-wpan/src/tables.rs b/embassy-stm32-wpan/src/tables.rs new file mode 100644 index 000000000..151216958 --- /dev/null +++ b/embassy-stm32-wpan/src/tables.rs @@ -0,0 +1,175 @@ +use bit_field::BitField; + +use crate::cmd::{AclDataPacket, CmdPacket}; +use crate::unsafe_linked_list::LinkedListNode; + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct SafeBootInfoTable { + version: u32, +} + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct RssInfoTable { + pub version: u32, + pub memory_size: u32, + pub rss_info: u32, +} + +/** + * Version + * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version + * [4:7] = branch - 0: Mass Market - x: ... + * [8:15] = Subversion + * [16:23] = Version minor + * [24:31] = Version major + * + * Memory Size + * [0:7] = Flash ( Number of 4k sector) + * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension ) + * [16:23] = SRAM2b ( Number of 1k sector) + * [24:31] = SRAM2a ( Number of 1k sector) + */ +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct WirelessFwInfoTable { + pub version: u32, + pub memory_size: u32, + pub thread_info: u32, + pub ble_info: u32, +} + +impl WirelessFwInfoTable { + pub fn version_major(&self) -> u8 { + let version = self.version; + (version.get_bits(24..31) & 0xff) as u8 + } + + pub fn version_minor(&self) -> u8 { + let version = self.version; + (version.clone().get_bits(16..23) & 0xff) as u8 + } + + pub fn subversion(&self) -> u8 { + let version = self.version; + (version.clone().get_bits(8..15) & 0xff) as u8 + } + + /// Size of FLASH, expressed in number of 4K sectors. + pub fn flash_size(&self) -> u8 { + let memory_size = self.memory_size; + (memory_size.clone().get_bits(0..7) & 0xff) as u8 + } + + /// Size of SRAM2a, expressed in number of 1K sectors. + pub fn sram2a_size(&self) -> u8 { + let memory_size = self.memory_size; + (memory_size.clone().get_bits(24..31) & 0xff) as u8 + } + + /// Size of SRAM2b, expressed in number of 1K sectors. + pub fn sram2b_size(&self) -> u8 { + let memory_size = self.memory_size; + (memory_size.clone().get_bits(16..23) & 0xff) as u8 + } +} + +#[derive(Debug, Clone)] +#[repr(C, align(4))] +pub struct DeviceInfoTable { + pub safe_boot_info_table: SafeBootInfoTable, + pub rss_info_table: RssInfoTable, + pub wireless_fw_info_table: WirelessFwInfoTable, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct BleTable { + pub pcmd_buffer: *mut CmdPacket, + pub pcs_buffer: *const u8, + pub pevt_queue: *const u8, + pub phci_acl_data_buffer: *mut AclDataPacket, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct ThreadTable { + pub nostack_buffer: *const u8, + pub clicmdrsp_buffer: *const u8, + pub otcmdrsp_buffer: *const u8, +} + +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct LldTestsTable { + pub clicmdrsp_buffer: *const u8, + pub m0cmd_buffer: *const u8, +} + +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct BleLldTable { + pub cmdrsp_buffer: *const u8, + pub m0cmd_buffer: *const u8, +} + +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct ZigbeeTable { + pub notif_m0_to_m4_buffer: *const u8, + pub appli_cmd_m4_to_m0_bufer: *const u8, + pub request_m0_to_m4_buffer: *const u8, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct SysTable { + pub pcmd_buffer: *mut CmdPacket, + pub sys_queue: *const LinkedListNode, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct MemManagerTable { + pub spare_ble_buffer: *const u8, + pub spare_sys_buffer: *const u8, + + pub blepool: *const u8, + pub blepoolsize: u32, + + pub pevt_free_buffer_queue: *mut LinkedListNode, + + pub traces_evt_pool: *const u8, + pub tracespoolsize: u32, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct TracesTable { + pub traces_queue: *const u8, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct Mac802_15_4Table { + pub p_cmdrsp_buffer: *const u8, + pub p_notack_buffer: *const u8, + pub evt_queue: *const u8, +} + +/// Reference table. Contains pointers to all other tables. +#[derive(Debug, Copy, Clone)] +#[repr(C)] +pub struct RefTable { + pub device_info_table: *const DeviceInfoTable, + pub ble_table: *const BleTable, + pub thread_table: *const ThreadTable, + pub sys_table: *const SysTable, + pub mem_manager_table: *const MemManagerTable, + pub traces_table: *const TracesTable, + pub mac_802_15_4_table: *const Mac802_15_4Table, +} diff --git a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs similarity index 92% rename from embassy-stm32/src/tl_mbox/unsafe_linked_list.rs rename to embassy-stm32-wpan/src/unsafe_linked_list.rs index 482e2bf5a..52c106fa2 100644 --- a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -57,6 +57,7 @@ impl LinkedListNode { }); } + /// Remove `node` from the linked list pub unsafe fn remove_node(mut node: *mut LinkedListNode) { interrupt::free(|_| { (*(*node).prev).next = (*node).next; @@ -64,6 +65,7 @@ impl LinkedListNode { }); } + /// Remove `list_head` into `node` pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { interrupt::free(|_| { *node = (*list_head).next; @@ -71,10 +73,11 @@ impl LinkedListNode { }); } - pub unsafe fn remove_tail(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + /// Remove `list_tail` into `node` + pub unsafe fn remove_tail(mut list_tail: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { interrupt::free(|_| { - *node = (*list_head).prev; - Self::remove_node((*list_head).prev); + *node = (*list_tail).prev; + Self::remove_node((*list_tail).prev); }); } diff --git a/embassy-stm32/src/tl_mbox/ipcc.rs b/embassy-stm32/src/ipcc.rs similarity index 75% rename from embassy-stm32/src/tl_mbox/ipcc.rs rename to embassy-stm32/src/ipcc.rs index d1ac731ed..8bb0774b8 100644 --- a/embassy-stm32/src/tl_mbox/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -167,8 +167,68 @@ impl sealed::Instance for crate::peripherals::IPCC { } unsafe fn _configure_pwr() { + let pwr = crate::pac::PWR; let rcc = crate::pac::RCC; + rcc.cfgr().modify(|w| w.set_stopwuck(true)); + + pwr.cr1().modify(|w| w.set_dbp(true)); + pwr.cr1().modify(|w| w.set_dbp(true)); + + // configure LSE + rcc.bdcr().modify(|w| w.set_lseon(true)); + + // select system clock source = PLL + // set PLL coefficients + // m: 2, + // n: 12, + // r: 3, + // q: 4, + // p: 3, + let src_bits = 0b11; + let pllp = (3 - 1) & 0b11111; + let pllq = (4 - 1) & 0b111; + let pllr = (3 - 1) & 0b111; + let plln = 12 & 0b1111111; + let pllm = (2 - 1) & 0b111; + rcc.pllcfgr().modify(|w| { + w.set_pllsrc(src_bits); + w.set_pllm(pllm); + w.set_plln(plln); + w.set_pllr(pllr); + w.set_pllp(pllp); + w.set_pllpen(true); + w.set_pllq(pllq); + w.set_pllqen(true); + }); + // enable PLL + rcc.cr().modify(|w| w.set_pllon(true)); + rcc.cr().write(|w| w.set_hsion(false)); + // while !rcc.cr().read().pllrdy() {} + + // configure SYSCLK mux to use PLL clocl + rcc.cfgr().modify(|w| w.set_sw(0b11)); + + // configure CPU1 & CPU2 dividers + rcc.cfgr().modify(|w| w.set_hpre(0)); // not divided + rcc.extcfgr().modify(|w| { + w.set_c2hpre(0b1000); // div2 + w.set_shdhpre(0); // not divided + }); + + // apply APB1 / APB2 values + rcc.cfgr().modify(|w| { + w.set_ppre1(0b000); // not divided + w.set_ppre2(0b000); // not divided + }); + + // TODO: required // set RF wake-up clock = LSE rcc.csr().modify(|w| w.set_rfwkpsel(0b01)); + + // set LPTIM1 & LPTIM2 clock source + rcc.ccipr().modify(|w| { + w.set_lptim1sel(0b00); // PCLK + w.set_lptim2sel(0b00); // PCLK + }); } diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 75d8af3dd..8c13774a0 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -41,6 +41,8 @@ pub mod crc; pub mod flash; #[cfg(all(spi_v1, rcc_f4))] pub mod i2s; +#[cfg(stm32wb)] +pub mod ipcc; pub mod pwm; #[cfg(quadspi)] pub mod qspi; @@ -52,8 +54,6 @@ pub mod rtc; pub mod sdmmc; #[cfg(spi)] pub mod spi; -#[cfg(stm32wb)] -pub mod tl_mbox; #[cfg(usart)] pub mod usart; #[cfg(usb)] diff --git a/embassy-stm32/src/tl_mbox/hci.rs b/embassy-stm32/src/tl_mbox/hci.rs deleted file mode 100644 index 5bb4ba666..000000000 --- a/embassy-stm32/src/tl_mbox/hci.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::ble::Ble; -use super::consts::TlPacketType; -use super::evt::CcEvt; -use super::shci::{shci_ble_init, ShciBleInitCmdParam}; -use super::{TlMbox, STATE}; - -pub struct RadioCoprocessor<'d> { - mbox: TlMbox<'d>, - config: ShciBleInitCmdParam, - rx_buffer: [u8; 500], -} - -impl<'d> RadioCoprocessor<'d> { - pub fn new(mbox: TlMbox<'d>, config: ShciBleInitCmdParam) -> Self { - Self { - mbox, - config, - rx_buffer: [0u8; 500], - } - } - - pub fn write(&mut self, params: &[u8]) -> Result<(), ()> { - let cmd_code = params[0]; - let cmd = TlPacketType::try_from(cmd_code)?; - - match cmd { - TlPacketType::BleCmd => Ble::send_cmd(params), - _ => todo!(), - } - - Ok(()) - } - - pub async fn read(&mut self) -> &[u8] { - self.rx_buffer = [0u8; 500]; - - loop { - STATE.wait().await; - - if let Some(evt) = self.mbox.dequeue_event() { - let event = evt.evt(); - evt.write(&mut self.rx_buffer).unwrap(); - - if event.kind() == 18 { - shci_ble_init(self.config); - self.rx_buffer[0] = 0x04; // replace event code with one that is supported by HCI - } - - if let Some(cc) = self.mbox.pop_last_cc_evt() { - - - continue; - } - - let payload_len = self.rx_buffer[2]; - return &self.rx_buffer[..3 + payload_len as usize]; - } - } - } -} diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 0525d3f37..3132ab3e4 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs @@ -4,15 +4,15 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::tl_mbox::hci::RadioCoprocessor; -use embassy_stm32::tl_mbox::ipcc::Config; -use embassy_stm32::tl_mbox::TlMbox; -use embassy_stm32::{bind_interrupts, tl_mbox}; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::Config; +use embassy_stm32_wpan::rc::RadioCoprocessor; +use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; - IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; + IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; + IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; }); #[embassy_executor::main] @@ -45,16 +45,16 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::new(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config); - let mut rc = RadioCoprocessor::new(mbox, Default::default()); - rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]).unwrap(); + let mut rc = RadioCoprocessor::new(mbox); let response = rc.read().await; info!("coprocessor ready {}", response); + rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); let response = rc.read().await; - info!("coprocessor ready {}", response); + info!("ble reset rsp {}", response); info!("Test OK"); cortex_m::asm::bkpt(); From 2dd5ce83ec0421564e85b667f5dabd592f313e5c Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 12:31:15 +0100 Subject: [PATCH 53/98] stm32/ipcc: fix `tl_mbox` example --- examples/stm32wb/src/bin/tl_mbox.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index 8f4e70af0..ae36a7e79 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -4,14 +4,15 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::tl_mbox::{Config, TlMbox}; -use embassy_stm32::{bind_interrupts, tl_mbox}; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::Config; +use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; - IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; + IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; + IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; }); #[embassy_executor::main] @@ -44,7 +45,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::new(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config); loop { let wireless_fw_info = mbox.wireless_fw_info(); From a1b27783a645673500833d13bbabb21d4e4202df Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 14:44:30 +0100 Subject: [PATCH 54/98] fix build --- embassy-stm32-wpan/Cargo.toml | 24 ++++++++++++++++++++---- embassy-stm32-wpan/build.rs | 34 ++++++++++++++++++++++++++++++++++ embassy-stm32-wpan/src/lib.rs | 18 +++++++++--------- examples/stm32wb/Cargo.toml | 1 + tests/stm32/src/bin/tl_mbox.rs | 11 ++++++----- 5 files changed, 70 insertions(+), 18 deletions(-) create mode 100644 embassy-stm32-wpan/build.rs diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index a6673d472..058d0e29f 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -5,13 +5,12 @@ edition = "2021" license = "MIT OR Apache-2.0" [dependencies] -embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", features = ["stm32wb55rg"] } +embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} -embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } -embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } +embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } +embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } cortex-m = "0.7.6" @@ -21,3 +20,20 @@ bit_field = "0.10.2" [features] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] + +stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] +stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] +stm32wb30ce = [ "embassy-stm32/stm32wb30ce" ] +stm32wb35cc = [ "embassy-stm32/stm32wb35cc" ] +stm32wb35ce = [ "embassy-stm32/stm32wb35ce" ] +stm32wb50cg = [ "embassy-stm32/stm32wb50cg" ] +stm32wb55cc = [ "embassy-stm32/stm32wb55cc" ] +stm32wb55ce = [ "embassy-stm32/stm32wb55ce" ] +stm32wb55cg = [ "embassy-stm32/stm32wb55cg" ] +stm32wb55rc = [ "embassy-stm32/stm32wb55rc" ] +stm32wb55re = [ "embassy-stm32/stm32wb55re" ] +stm32wb55rg = [ "embassy-stm32/stm32wb55rg" ] +stm32wb55vc = [ "embassy-stm32/stm32wb55vc" ] +stm32wb55ve = [ "embassy-stm32/stm32wb55ve" ] +stm32wb55vg = [ "embassy-stm32/stm32wb55vg" ] +stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] \ No newline at end of file diff --git a/embassy-stm32-wpan/build.rs b/embassy-stm32-wpan/build.rs new file mode 100644 index 000000000..4edf73d59 --- /dev/null +++ b/embassy-stm32-wpan/build.rs @@ -0,0 +1,34 @@ +use std::env; + +fn main() { + match env::vars() + .map(|(a, _)| a) + .filter(|x| x.starts_with("CARGO_FEATURE_STM32")) + .get_one() + { + Ok(_) => {} + Err(GetOneError::None) => panic!("No stm32xx Cargo feature enabled"), + Err(GetOneError::Multiple) => panic!("Multiple stm32xx Cargo features enabled"), + } +} + +enum GetOneError { + None, + Multiple, +} + +trait IteratorExt: Iterator { + fn get_one(self) -> Result; +} + +impl IteratorExt for T { + fn get_one(mut self) -> Result { + match self.next() { + None => Err(GetOneError::None), + Some(res) => match self.next() { + Some(_) => Err(GetOneError::Multiple), + None => Ok(res), + }, + } + } +} diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index b3206428e..c37b67dc4 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -6,10 +6,10 @@ pub mod fmt; use core::mem::MaybeUninit; use cmd::CmdPacket; -use embassy_cortex_m::interrupt::Interrupt; use embassy_futures::block_on; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::interrupt; +use embassy_stm32::interrupt::typelevel::Interrupt; use embassy_stm32::ipcc::{Config, Ipcc}; use embassy_stm32::peripherals::IPCC; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; @@ -37,7 +37,7 @@ pub mod unsafe_linked_list; /// Interrupt handler. pub struct ReceiveInterruptHandler {} -impl interrupt::Handler for ReceiveInterruptHandler { +impl interrupt::typelevel::Handler for ReceiveInterruptHandler { unsafe fn on_interrupt() { if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { debug!("RX SYS evt"); @@ -53,7 +53,7 @@ impl interrupt::Handler for ReceiveInterruptHandler { pub struct TransmitInterruptHandler {} -impl interrupt::Handler for TransmitInterruptHandler { +impl interrupt::typelevel::Handler for TransmitInterruptHandler { unsafe fn on_interrupt() { if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { debug!("TX SYS cmd rsp"); @@ -182,8 +182,8 @@ pub struct TlMbox<'d> { impl<'d> TlMbox<'d> { pub fn init( ipcc: impl Peripheral

+ 'd, - _irqs: impl interrupt::Binding - + interrupt::Binding, + _irqs: impl interrupt::typelevel::Binding + + interrupt::typelevel::Binding, config: Config, ) -> Self { into_ref!(ipcc); @@ -223,11 +223,11 @@ impl<'d> TlMbox<'d> { mm::MemoryManager::enable(); // enable interrupts - interrupt::IPCC_C1_RX::unpend(); - interrupt::IPCC_C1_TX::unpend(); + interrupt::typelevel::IPCC_C1_RX::unpend(); + interrupt::typelevel::IPCC_C1_TX::unpend(); - unsafe { interrupt::IPCC_C1_RX::enable() }; - unsafe { interrupt::IPCC_C1_TX::enable() }; + unsafe { interrupt::typelevel::IPCC_C1_RX::enable() }; + unsafe { interrupt::typelevel::IPCC_C1_TX::enable() }; STATE.reset(); diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 14897b171..5b82dd83b 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -9,6 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } +embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index fab9f0e1b..0f643d578 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -8,13 +8,14 @@ mod common; use common::*; use embassy_executor::Spawner; -use embassy_stm32::tl_mbox::{Config, TlMbox}; -use embassy_stm32::{bind_interrupts, tl_mbox}; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::Config; +use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; - IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; + IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; + IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; }); #[embassy_executor::main] @@ -23,7 +24,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::new(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config); loop { let wireless_fw_info = mbox.wireless_fw_info(); From bb5ceb2d9c511e7923b538ac14a30bd78368b189 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 14:52:14 +0100 Subject: [PATCH 55/98] fix CI error --- examples/stm32wb/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 5b82dd83b..83a443754 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } -embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt"] } +embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } defmt = "0.3" defmt-rtt = "0.4" From 553c93432559e75d211b84363840f1d272489283 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 14:54:17 +0100 Subject: [PATCH 56/98] fix CI for tests --- tests/stm32/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 3f48bf3f1..3a50493f4 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -29,6 +29,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } defmt = "0.3.0" defmt-rtt = "0.4" From 802416d267028dd0624f6f4183fd1d44278946e1 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 15:04:52 +0100 Subject: [PATCH 57/98] fix CI for tests --- tests/stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 3a50493f4..db97e929b 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -12,7 +12,7 @@ stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo -stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble"] # Nucleo +stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "dep:embassy-stm32-wpan"] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board @@ -29,7 +29,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } +embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg"] } defmt = "0.3.0" defmt-rtt = "0.4" From bf32dc5d3acee1f73fe445976bde474ffa6d04e0 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 15:07:46 +0100 Subject: [PATCH 58/98] clippy --- embassy-stm32-wpan/src/ble.rs | 4 ++-- embassy-stm32-wpan/src/shci.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index 4546bde07..19955a8a3 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -63,7 +63,7 @@ impl Ble { core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); - let mut cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; + let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; } @@ -72,7 +72,7 @@ impl Ble { #[allow(dead_code)] // Not used currently but reserved pub(super) fn ble_send_acl_data() { - let mut cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; + let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; diff --git a/embassy-stm32-wpan/src/shci.rs b/embassy-stm32-wpan/src/shci.rs index 4f4d08886..8537995ff 100644 --- a/embassy-stm32-wpan/src/shci.rs +++ b/embassy-stm32-wpan/src/shci.rs @@ -90,7 +90,7 @@ pub fn shci_ble_init(param: ShciBleInitCmdParam) { (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::() as u8; - let mut p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; + let p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; core::ptr::write(p_cmd_buffer, *cmd_ptr); p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; From 8d5f995a010eadcc70c6e933ca0facab133bbef4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 12 Jun 2023 16:37:36 +0200 Subject: [PATCH 59/98] usb-logger: fix breakage in log 0.4.19 https://github.com/rust-lang/log/issues/567 --- embassy-usb-logger/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-usb-logger/src/lib.rs b/embassy-usb-logger/src/lib.rs index 1d8dd13ce..6e50c40ba 100644 --- a/embassy-usb-logger/src/lib.rs +++ b/embassy-usb-logger/src/lib.rs @@ -138,7 +138,7 @@ macro_rules! run { ( $x:expr, $l:expr, $p:ident ) => { static LOGGER: ::embassy_usb_logger::UsbLogger<$x> = ::embassy_usb_logger::UsbLogger::new(); unsafe { - let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level($l)); + let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l)); } let _ = LOGGER.run(&mut ::embassy_usb_logger::LoggerState::new(), $p).await; }; From 6863786243e0f7cb28661d49165eeffacbfd8152 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Sat, 10 Jun 2023 18:14:45 +0200 Subject: [PATCH 60/98] Document external button. Add wifi_blinky.rs for easy beginners start. --- examples/rp/src/bin/button.rs | 5 ++- examples/rp/src/bin/wifi_blinky.rs | 59 ++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 examples/rp/src/bin/wifi_blinky.rs diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs index c5422c616..edfb09cdb 100644 --- a/examples/rp/src/bin/button.rs +++ b/examples/rp/src/bin/button.rs @@ -9,9 +9,12 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); - let button = Input::new(p.PIN_28, Pull::Up); let mut led = Output::new(p.PIN_25, Level::Low); + // Use PIN_28, Pin34 on J0 for RP Pico, as a input. + // You need to ad your own button. + let button = Input::new(p.PIN_28, Pull::Up); + loop { if button.is_high() { led.set_high(); diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs new file mode 100644 index 000000000..f567e7c5d --- /dev/null +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -0,0 +1,59 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use cyw43_pio::PioSpi; +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; +use embassy_rp::pio::Pio; +use embassy_time::{Duration, Timer}; +use static_cell::make_static; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn wifi_task( + runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, +) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); + let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); + + // To make flashing faster for development, you may want to flash the firmwares independently + // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: + // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; + //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; + + let pwr = Output::new(p.PIN_23, Level::Low); + let cs = Output::new(p.PIN_25, Level::High); + let mut pio = Pio::new(p.PIO0); + let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); + + let state = make_static!(cyw43::State::new()); + let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; + unwrap!(spawner.spawn(wifi_task(runner))); + + control.init(clm).await; + control + .set_power_management(cyw43::PowerManagementMode::PowerSave) + .await; + + let delay = Duration::from_secs(1); + loop { + info!("led on!"); + control.gpio_set(0, true).await; + Timer::after(delay).await; + + info!("led off!"); + control.gpio_set(0, false).await; + Timer::after(delay).await; + } +} From 23724b6bf6ce6492d40a3ff3af77c8b4d15a36d8 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Mon, 12 Jun 2023 18:12:35 +0200 Subject: [PATCH 61/98] Code cleanup. --- examples/rp/src/bin/wifi_blinky.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index f567e7c5d..be965807b 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -40,7 +40,7 @@ async fn main(spawner: Spawner) { let state = make_static!(cyw43::State::new()); let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; unwrap!(spawner.spawn(wifi_task(runner))); - + control.init(clm).await; control .set_power_management(cyw43::PowerManagementMode::PowerSave) From 35db5cf41653bdb995f5cad2d04788118a746921 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Mon, 12 Jun 2023 18:56:20 +0200 Subject: [PATCH 62/98] Spelling. --- examples/rp/src/bin/button.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs index edfb09cdb..0d246c093 100644 --- a/examples/rp/src/bin/button.rs +++ b/examples/rp/src/bin/button.rs @@ -12,7 +12,7 @@ async fn main(_spawner: Spawner) { let mut led = Output::new(p.PIN_25, Level::Low); // Use PIN_28, Pin34 on J0 for RP Pico, as a input. - // You need to ad your own button. + // You need to add your own button. let button = Input::new(p.PIN_28, Pull::Up); loop { From 9cfcc5b89afb8fee9371af3bfbe8480deb2ef634 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 13 Jun 2023 03:29:51 +0200 Subject: [PATCH 63/98] Fix docs build. --- .github/ci/doc.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 72c6465f7..947823b1f 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -9,6 +9,12 @@ export CARGO_TARGET_DIR=/ci/cache/target export BUILDER_THREADS=6 export BUILDER_COMPRESS=true +# force rustup to download the toolchain before starting building. +# Otherwise, the docs builder is running multiple instances of cargo rustdoc concurrently. +# They all see the toolchain is not installed and try to install it in parallel +# which makes rustup very sad +rustc --version > /dev/null + docserver-builder -i ./embassy-stm32 -o crates/embassy-stm32/git.zup docserver-builder -i ./embassy-boot/boot -o crates/embassy-boot/git.zup docserver-builder -i ./embassy-boot/nrf -o crates/embassy-boot-nrf/git.zup From 3c98587a884e7c13d4b3203669866e23ad05003a Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 12 Jun 2023 21:23:42 -0500 Subject: [PATCH 64/98] tests/ble: disable test for now does not work in --release --- tests/stm32/Cargo.toml | 4 ++-- tests/stm32/src/bin/tl_mbox.rs | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index db97e929b..dcc7d9b8a 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -12,13 +12,13 @@ stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo -stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "dep:embassy-stm32-wpan"] # Nucleo +stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma" ] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board sdmmc = [] chrono = ["embassy-stm32/chrono", "dep:chrono"] -ble = [] +ble = ["dep:embassy-stm32-wpan"] not-gpdma = [] [dependencies] diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index 0f643d578..b57519a54 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -50,6 +50,15 @@ async fn main(_spawner: Spawner) { Timer::after(Duration::from_millis(50)).await; } + // let mut rc = RadioCoprocessor::new(mbox); + // + // let response = rc.read().await; + // info!("coprocessor ready {}", response); + // + // rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); + // let response = rc.read().await; + // info!("ble reset rsp {}", response); + info!("Test OK"); cortex_m::asm::bkpt(); } From b55e618175e3af81f2b0d04bca45a96adc24a661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Mon, 12 Jun 2023 09:36:07 +0200 Subject: [PATCH 65/98] embassy-nrf: Idle detection for RX only uarte Introduce `with_idle()` to upgrade an `UarteRx` instance to `UarteRxWithIdle`. Use the method in the split constructor aswell. --- embassy-nrf/src/uarte.rs | 95 +++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 85a951ae0..48d57fea4 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -205,50 +205,7 @@ impl<'d, T: Instance> Uarte<'d, T> { ppi_ch1: impl Peripheral

+ 'd, ppi_ch2: impl Peripheral

+ 'd, ) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) { - let timer = Timer::new(timer); - - into_ref!(ppi_ch1, ppi_ch2); - - let r = T::regs(); - - // BAUDRATE register values are `baudrate * 2^32 / 16000000` - // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values - // - // We want to stop RX if line is idle for 2 bytes worth of time - // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit) - // This gives us the amount of 16M ticks for 20 bits. - let baudrate = r.baudrate.read().baudrate().variant().unwrap(); - let timeout = 0x8000_0000 / (baudrate as u32 / 40); - - timer.set_frequency(Frequency::F16MHz); - timer.cc(0).write(timeout); - timer.cc(0).short_compare_clear(); - timer.cc(0).short_compare_stop(); - - let mut ppi_ch1 = Ppi::new_one_to_two( - ppi_ch1.map_into(), - Event::from_reg(&r.events_rxdrdy), - timer.task_clear(), - timer.task_start(), - ); - ppi_ch1.enable(); - - let mut ppi_ch2 = Ppi::new_one_to_one( - ppi_ch2.map_into(), - timer.cc(0).event_compare(), - Task::from_reg(&r.tasks_stoprx), - ); - ppi_ch2.enable(); - - ( - self.tx, - UarteRxWithIdle { - rx: self.rx, - timer, - ppi_ch1: ppi_ch1, - _ppi_ch2: ppi_ch2, - }, - ) + (self.tx, self.rx.with_idle(timer, ppi_ch1, ppi_ch2)) } /// Return the endtx event for use with PPI @@ -563,6 +520,56 @@ impl<'d, T: Instance> UarteRx<'d, T> { Self { _p: uarte } } + /// Upgrade to an instance that supports idle line detection. + pub fn with_idle( + self, + timer: impl Peripheral

+ 'd, + ppi_ch1: impl Peripheral

+ 'd, + ppi_ch2: impl Peripheral

+ 'd, + ) -> UarteRxWithIdle<'d, T, U> { + let timer = Timer::new(timer); + + into_ref!(ppi_ch1, ppi_ch2); + + let r = T::regs(); + + // BAUDRATE register values are `baudrate * 2^32 / 16000000` + // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values + // + // We want to stop RX if line is idle for 2 bytes worth of time + // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit) + // This gives us the amount of 16M ticks for 20 bits. + let baudrate = r.baudrate.read().baudrate().variant().unwrap(); + let timeout = 0x8000_0000 / (baudrate as u32 / 40); + + timer.set_frequency(Frequency::F16MHz); + timer.cc(0).write(timeout); + timer.cc(0).short_compare_clear(); + timer.cc(0).short_compare_stop(); + + let mut ppi_ch1 = Ppi::new_one_to_two( + ppi_ch1.map_into(), + Event::from_reg(&r.events_rxdrdy), + timer.task_clear(), + timer.task_start(), + ); + ppi_ch1.enable(); + + let mut ppi_ch2 = Ppi::new_one_to_one( + ppi_ch2.map_into(), + timer.cc(0).event_compare(), + Task::from_reg(&r.tasks_stoprx), + ); + ppi_ch2.enable(); + + UarteRxWithIdle { + rx: self, + timer, + ppi_ch1: ppi_ch1, + _ppi_ch2: ppi_ch2, + } + } + /// Read bytes until the buffer is filled. pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { if buffer.len() == 0 { From 055f6afdccec98a8151b83cad3a87d8858c08e8c Mon Sep 17 00:00:00 2001 From: goueslati Date: Tue, 13 Jun 2023 09:51:21 +0100 Subject: [PATCH 66/98] stm32-wpan: add doc metadata --- .github/ci/doc.sh | 1 + embassy-stm32-wpan/Cargo.toml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 947823b1f..1402e742f 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -37,6 +37,7 @@ docserver-builder -i ./embassy-usb-logger -o crates/embassy-usb-logger/git.zup docserver-builder -i ./cyw43 -o crates/cyw43/git.zup docserver-builder -i ./cyw43-pio -o crates/cyw43-pio/git.zup docserver-builder -i ./embassy-net-w5500 -o crates/embassy-net-w5500/git.zup +docserver-builder -i ./embassy-stm32-wpan -o crates/embassy-stm32-wpan/git.zup export KUBECONFIG=/ci/secrets/kubeconfig.yml POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 058d0e29f..1c1b57b36 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -4,6 +4,12 @@ version = "0.1.0" edition = "2021" license = "MIT OR Apache-2.0" +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-wpan-v$VERSION/embassy-stm32-wpan/src" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32-wpan/src" +target = "thumbv7em-none-eabihf" +features = ["stm32wb55rg"] + [dependencies] embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } From 6c13f381c45aefece76f39d5b14da6b60e02b7ee Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 13 Jun 2023 17:12:34 -0500 Subject: [PATCH 67/98] stm32/wpan: get --release working --- embassy-stm32-wpan/src/ble.rs | 4 +- embassy-stm32-wpan/src/lib.rs | 74 ++++++++++--- embassy-stm32-wpan/src/mm.rs | 2 +- embassy-stm32-wpan/src/sys.rs | 6 +- embassy-stm32-wpan/src/unsafe_linked_list.rs | 105 ++++++++++++++----- tests/stm32/Cargo.toml | 2 +- tests/stm32/src/bin/tl_mbox.rs | 17 +-- 7 files changed, 156 insertions(+), 54 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index 19955a8a3..57195ef9d 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -18,7 +18,7 @@ impl Ble { unsafe { LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); - TL_BLE_TABLE = MaybeUninit::new(BleTable { + TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), pcs_buffer: CS_BUFFER.as_ptr().cast(), pevt_queue: EVT_QUEUE.as_ptr().cast(), @@ -41,6 +41,8 @@ impl Ble { let event = EvtBox::new(event); EVT_CHANNEL.try_send(event).unwrap(); + + break; } } diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index c37b67dc4..000282f2b 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -4,6 +4,7 @@ pub mod fmt; use core::mem::MaybeUninit; +use core::sync::atomic::{compiler_fence, Ordering}; use cmd::CmdPacket; use embassy_futures::block_on; @@ -189,33 +190,76 @@ impl<'d> TlMbox<'d> { into_ref!(ipcc); unsafe { - TL_REF_TABLE = MaybeUninit::new(RefTable { - device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), + TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { + device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), ble_table: TL_BLE_TABLE.as_ptr(), thread_table: TL_THREAD_TABLE.as_ptr(), sys_table: TL_SYS_TABLE.as_ptr(), mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), traces_table: TL_TRACES_TABLE.as_ptr(), mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), + // zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), + // lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), + // ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), }); - TL_SYS_TABLE = MaybeUninit::zeroed(); - TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); - TL_BLE_TABLE = MaybeUninit::zeroed(); - TL_THREAD_TABLE = MaybeUninit::zeroed(); - TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); - TL_TRACES_TABLE = MaybeUninit::zeroed(); - TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); + TL_SYS_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + TL_DEVICE_INFO_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + TL_BLE_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + TL_THREAD_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + TL_MEM_MANAGER_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); - EVT_POOL = MaybeUninit::zeroed(); - SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); - BLE_SPARE_EVT_BUF = MaybeUninit::zeroed(); + TL_TRACES_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + TL_MAC_802_15_4_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); +// TL_ZIGBEE_TABLE +// .as_mut_ptr() +// .write_volatile(MaybeUninit::zeroed().assume_init()); +// TL_LLD_TESTS_TABLE +// .as_mut_ptr() +// .write_volatile(MaybeUninit::zeroed().assume_init()); +// TL_BLE_LLD_TABLE +// .as_mut_ptr() +// .write_volatile(MaybeUninit::zeroed().assume_init()); - CS_BUFFER = MaybeUninit::zeroed(); - BLE_CMD_BUFFER = MaybeUninit::zeroed(); - HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); + EVT_POOL + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + SYS_SPARE_EVT_BUF + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + BLE_SPARE_EVT_BUF + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + + { + BLE_CMD_BUFFER + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + HCI_ACL_DATA_BUFFER + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + CS_BUFFER + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + } } + compiler_fence(Ordering::SeqCst); + Ipcc::enable(config); sys::Sys::enable(); diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs index ed13b0dbf..e46c63558 100644 --- a/embassy-stm32-wpan/src/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -20,7 +20,7 @@ impl MemoryManager { LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); - TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { + TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), blepool: EVT_POOL.as_ptr().cast(), diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index a19d12d27..0a1db7c1f 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -15,7 +15,7 @@ impl Sys { unsafe { LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); - TL_SYS_TABLE = MaybeUninit::new(SysTable { + TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), }) @@ -51,12 +51,14 @@ impl Sys { let node_ptr_ptr: *mut _ = &mut node_ptr; while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); + LinkedListNode::get_next_node(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); let event = node_ptr.cast(); let event = EvtBox::new(event); EVT_CHANNEL.try_send(event).unwrap(); + + break; } } diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs index 52c106fa2..95f4bef44 100644 --- a/embassy-stm32-wpan/src/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -11,6 +11,8 @@ unused_mut )] +use core::ptr; + use cortex_m::interrupt; #[derive(Copy, Clone)] @@ -30,54 +32,102 @@ impl Default for LinkedListNode { } impl LinkedListNode { - pub unsafe fn init_head(mut list_head: *mut LinkedListNode) { - (*list_head).next = list_head; - (*list_head).prev = list_head; + pub unsafe fn init_head(mut p_list_head: *mut LinkedListNode) { + ptr::write_volatile( + p_list_head, + LinkedListNode { + next: p_list_head, + prev: p_list_head, + }, + ); } - pub unsafe fn is_empty(mut list_head: *mut LinkedListNode) -> bool { - interrupt::free(|_| ((*list_head).next) == list_head) + pub unsafe fn is_empty(mut p_list_head: *mut LinkedListNode) -> bool { + interrupt::free(|_| ptr::read_volatile(p_list_head).next == p_list_head) } - pub unsafe fn insert_head(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) { + /// Insert `node` after `list_head` and before the next node + pub unsafe fn insert_head(mut p_list_head: *mut LinkedListNode, mut p_node: *mut LinkedListNode) { interrupt::free(|_| { - (*node).next = (*list_head).next; - (*node).prev = list_head; - (*list_head).next = node; - (*(*node).next).prev = node; + let mut list_head = ptr::read_volatile(p_list_head); + let mut node_next = ptr::read_volatile(list_head.next); + let node = LinkedListNode { + next: list_head.next, + prev: p_list_head, + }; + + list_head.next = p_node; + node_next.prev = p_node; + + // All nodes must be written because they will all be seen by another core + ptr::write_volatile(p_node, node); + ptr::write_volatile(node.next, node_next); + ptr::write_volatile(p_list_head, list_head); }); } - pub unsafe fn insert_tail(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) { + /// Insert `node` before `list_tail` and after the second-to-last node + pub unsafe fn insert_tail(mut p_list_tail: *mut LinkedListNode, mut p_node: *mut LinkedListNode) { interrupt::free(|_| { - (*node).next = list_head; - (*node).prev = (*list_head).prev; - (*list_head).prev = node; - (*(*node).prev).next = node; + let mut list_tail = ptr::read_volatile(p_list_tail); + let mut node_prev = ptr::read_volatile(list_tail.prev); + let node = LinkedListNode { + next: p_list_tail, + prev: list_tail.prev, + }; + + list_tail.prev = p_node; + node_prev.next = p_node; + + // All nodes must be written because they will all be seen by another core + ptr::write_volatile(p_node, node); + ptr::write_volatile(node.prev, node_prev); + ptr::write_volatile(p_list_tail, list_tail); }); } /// Remove `node` from the linked list - pub unsafe fn remove_node(mut node: *mut LinkedListNode) { + // pub unsafe fn remove_node(mut node: *mut LinkedListNode) { + // interrupt::free(|_| { + // (*(*node).prev).next = (*node).next; + // (*(*node).next).prev = (*node).prev; + // }); + // } + + /// Remove `node` from the linked list + pub unsafe fn remove_node(mut p_node: *mut LinkedListNode) { interrupt::free(|_| { - (*(*node).prev).next = (*node).next; - (*(*node).next).prev = (*node).prev; + let node = ptr::read_volatile(p_node); + let mut node_prev = ptr::read_volatile(node.prev); + let mut node_next = ptr::read_volatile(node.next); + + node_prev.next = node.next; + node_next.prev = node.prev; + + ptr::write_volatile(node.prev, node_prev); + ptr::write_volatile(node.next, node_next); }); } /// Remove `list_head` into `node` - pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { interrupt::free(|_| { - *node = (*list_head).next; - Self::remove_node((*list_head).next); + let list_head = ptr::read_volatile(p_list_head); + + // Allowed because a removed node is not seen by another core + *p_node = list_head.next; + Self::remove_node(list_head.next); }); } /// Remove `list_tail` into `node` - pub unsafe fn remove_tail(mut list_tail: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { interrupt::free(|_| { - *node = (*list_tail).prev; - Self::remove_node((*list_tail).prev); + let list_tail = ptr::read_volatile(p_list_tail); + + // Allowed because a removed node is not seen by another core + *p_node = list_tail.prev; + Self::remove_node(list_tail.prev); }); } @@ -114,9 +164,12 @@ impl LinkedListNode { }) } - pub unsafe fn get_next_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + pub unsafe fn get_next_node(mut p_ref_node: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { interrupt::free(|_| { - *node = (*ref_node).next; + let ref_node = ptr::read_volatile(p_ref_node); + + // Allowed because a removed node is not seen by another core + *p_node = ref_node.next; }); } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index dcc7d9b8a..487ef4626 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -12,7 +12,7 @@ stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo -stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma" ] # Nucleo +stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble" ] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index b57519a54..26d9cc68e 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -11,6 +11,7 @@ use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::Config; use embassy_stm32_wpan::TlMbox; +use embassy_stm32_wpan::rc::RadioCoprocessor; use embassy_time::{Duration, Timer}; bind_interrupts!(struct Irqs{ @@ -50,14 +51,14 @@ async fn main(_spawner: Spawner) { Timer::after(Duration::from_millis(50)).await; } - // let mut rc = RadioCoprocessor::new(mbox); - // - // let response = rc.read().await; - // info!("coprocessor ready {}", response); - // - // rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); - // let response = rc.read().await; - // info!("ble reset rsp {}", response); + let mut rc = RadioCoprocessor::new(mbox); + + let response = rc.read().await; + info!("coprocessor ready {}", response); + + rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); + let response = rc.read().await; + info!("ble reset rsp {}", response); info!("Test OK"); cortex_m::asm::bkpt(); From f15a0203e4c6f9b38099d3a2ebd40c554016a11d Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 13 Jun 2023 17:13:25 -0500 Subject: [PATCH 68/98] rustfmt --- embassy-stm32-wpan/src/ble.rs | 2 -- embassy-stm32-wpan/src/mm.rs | 2 -- embassy-stm32-wpan/src/sys.rs | 2 -- 3 files changed, 6 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index 57195ef9d..ed13cc495 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -1,5 +1,3 @@ -use core::mem::MaybeUninit; - use embassy_stm32::ipcc::Ipcc; use crate::cmd::{CmdPacket, CmdSerial}; diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs index e46c63558..68db49b82 100644 --- a/embassy-stm32-wpan/src/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -1,7 +1,5 @@ //! Memory manager routines -use core::mem::MaybeUninit; - use embassy_stm32::ipcc::Ipcc; use crate::evt::EvtPacket; diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index 0a1db7c1f..a7cbbae39 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -1,5 +1,3 @@ -use core::mem::MaybeUninit; - use embassy_stm32::ipcc::Ipcc; use crate::cmd::{CmdPacket, CmdSerial}; From 29513074ee0462e43b040b05d08a08430efee302 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 13 Jun 2023 17:16:12 -0500 Subject: [PATCH 69/98] rustfmt --- tests/stm32/src/bin/tl_mbox.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index 26d9cc68e..4669cbc62 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -10,8 +10,8 @@ use common::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::Config; -use embassy_stm32_wpan::TlMbox; use embassy_stm32_wpan::rc::RadioCoprocessor; +use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; bind_interrupts!(struct Irqs{ From c484f0715b28a7692b1c6c3b9d8caec50b84efc9 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 13 Jun 2023 17:17:10 -0500 Subject: [PATCH 70/98] rustfmt --- embassy-stm32-wpan/src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 000282f2b..2852d6270 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -225,15 +225,15 @@ impl<'d> TlMbox<'d> { TL_MAC_802_15_4_TABLE .as_mut_ptr() .write_volatile(MaybeUninit::zeroed().assume_init()); -// TL_ZIGBEE_TABLE -// .as_mut_ptr() -// .write_volatile(MaybeUninit::zeroed().assume_init()); -// TL_LLD_TESTS_TABLE -// .as_mut_ptr() -// .write_volatile(MaybeUninit::zeroed().assume_init()); -// TL_BLE_LLD_TABLE -// .as_mut_ptr() -// .write_volatile(MaybeUninit::zeroed().assume_init()); + // TL_ZIGBEE_TABLE + // .as_mut_ptr() + // .write_volatile(MaybeUninit::zeroed().assume_init()); + // TL_LLD_TESTS_TABLE + // .as_mut_ptr() + // .write_volatile(MaybeUninit::zeroed().assume_init()); + // TL_BLE_LLD_TABLE + // .as_mut_ptr() + // .write_volatile(MaybeUninit::zeroed().assume_init()); EVT_POOL .as_mut_ptr() From c1fc98c3136299780535bff22a842dd78df4a254 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 13 Jun 2023 18:04:05 -0500 Subject: [PATCH 71/98] stm32/wpan: fix linked list bug --- embassy-stm32-wpan/src/sys.rs | 4 +- embassy-stm32-wpan/src/unsafe_linked_list.rs | 41 +++++++++++++------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index a7cbbae39..f41fac58a 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -49,14 +49,12 @@ impl Sys { let node_ptr_ptr: *mut _ = &mut node_ptr; while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - LinkedListNode::get_next_node(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); + LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); let event = node_ptr.cast(); let event = EvtBox::new(event); EVT_CHANNEL.try_send(event).unwrap(); - - break; } } diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs index 95f4bef44..c4a6c3a72 100644 --- a/embassy-stm32-wpan/src/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -86,25 +86,17 @@ impl LinkedListNode { }); } - /// Remove `node` from the linked list - // pub unsafe fn remove_node(mut node: *mut LinkedListNode) { - // interrupt::free(|_| { - // (*(*node).prev).next = (*node).next; - // (*(*node).next).prev = (*node).prev; - // }); - // } - /// Remove `node` from the linked list pub unsafe fn remove_node(mut p_node: *mut LinkedListNode) { interrupt::free(|_| { + // Writes must occur sequentially, because if prev node, and next node are the same, both must be updated let node = ptr::read_volatile(p_node); let mut node_prev = ptr::read_volatile(node.prev); - let mut node_next = ptr::read_volatile(node.next); - node_prev.next = node.next; - node_next.prev = node.prev; - ptr::write_volatile(node.prev, node_prev); + + let mut node_next = ptr::read_volatile(node.next); + node_next.prev = node.prev; ptr::write_volatile(node.next, node_next); }); } @@ -116,7 +108,7 @@ impl LinkedListNode { // Allowed because a removed node is not seen by another core *p_node = list_head.next; - Self::remove_node(list_head.next); + Self::remove_node(*p_node); }); } @@ -127,7 +119,7 @@ impl LinkedListNode { // Allowed because a removed node is not seen by another core *p_node = list_tail.prev; - Self::remove_node(list_tail.prev); + Self::remove_node(*p_node); }); } @@ -179,3 +171,24 @@ impl LinkedListNode { }); } } + +#[allow(dead_code)] +unsafe fn debug_linked_list(mut p_node: *mut LinkedListNode) { + info!("iterating list from node: {:x}", p_node); + let mut p_current_node = p_node; + let mut i = 0; + loop { + let current_node = ptr::read_volatile(p_current_node); + info!( + "node (prev, current, next): {:x}, {:x}, {:x}", + current_node.prev, p_current_node, current_node.next + ); + + i += 1; + if i > 10 || current_node.next == p_node { + break; + } + + p_current_node = current_node.next; + } +} From bc0734eee5a9bef5d759e923f5545e8ff54deda7 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 13 Jun 2023 18:05:27 -0500 Subject: [PATCH 72/98] stm32/wpan: remove break --- embassy-stm32-wpan/src/ble.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index ed13cc495..ba369bb3a 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -39,8 +39,6 @@ impl Ble { let event = EvtBox::new(event); EVT_CHANNEL.try_send(event).unwrap(); - - break; } } From ae9983324d9ddfa747d7bfc11aecc401c0abfeb9 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 13 Jun 2023 21:10:42 -0500 Subject: [PATCH 73/98] stm32/wpan: cleanup linked list and fix edge cases --- embassy-stm32-wpan/src/ble.rs | 5 +- embassy-stm32-wpan/src/mm.rs | 6 +- embassy-stm32-wpan/src/sys.rs | 5 +- embassy-stm32-wpan/src/unsafe_linked_list.rs | 134 +++++++++++++------ 4 files changed, 96 insertions(+), 54 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index ba369bb3a..57348a925 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -29,11 +29,8 @@ impl Ble { pub(super) fn evt_handler() { unsafe { - let mut node_ptr = core::ptr::null_mut(); - let node_ptr_ptr: *mut _ = &mut node_ptr; - while !LinkedListNode::is_empty(EVT_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); + let node_ptr = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()); let event = node_ptr.cast(); let event = EvtBox::new(event); diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs index 68db49b82..06063b89a 100644 --- a/embassy-stm32-wpan/src/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -51,11 +51,9 @@ impl MemoryManager { /// gives free event buffers back to CPU2 from local buffer queue pub fn send_free_buf() { unsafe { - let mut node_ptr = core::ptr::null_mut(); - let node_ptr_ptr: *mut _ = &mut node_ptr; - while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), node_ptr_ptr); + let node_ptr = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); + LinkedListNode::insert_tail( (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue, node_ptr, diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index f41fac58a..0cff5c746 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -45,11 +45,8 @@ impl Sys { pub fn evt_handler() { unsafe { - let mut node_ptr = core::ptr::null_mut(); - let node_ptr_ptr: *mut _ = &mut node_ptr; - while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); + let node_ptr = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); let event = node_ptr.cast(); let event = EvtBox::new(event); diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs index c4a6c3a72..ddec1afbc 100644 --- a/embassy-stm32-wpan/src/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -50,19 +50,33 @@ impl LinkedListNode { pub unsafe fn insert_head(mut p_list_head: *mut LinkedListNode, mut p_node: *mut LinkedListNode) { interrupt::free(|_| { let mut list_head = ptr::read_volatile(p_list_head); - let mut node_next = ptr::read_volatile(list_head.next); - let node = LinkedListNode { - next: list_head.next, - prev: p_list_head, - }; + if p_list_head != list_head.next { + let mut node_next = ptr::read_volatile(list_head.next); + let node = LinkedListNode { + next: list_head.next, + prev: p_list_head, + }; - list_head.next = p_node; - node_next.prev = p_node; + list_head.next = p_node; + node_next.prev = p_node; - // All nodes must be written because they will all be seen by another core - ptr::write_volatile(p_node, node); - ptr::write_volatile(node.next, node_next); - ptr::write_volatile(p_list_head, list_head); + // All nodes must be written because they will all be seen by another core + ptr::write_volatile(p_node, node); + ptr::write_volatile(node.next, node_next); + ptr::write_volatile(p_list_head, list_head); + } else { + let node = LinkedListNode { + next: list_head.next, + prev: p_list_head, + }; + + list_head.next = p_node; + list_head.prev = p_node; + + // All nodes must be written because they will all be seen by another core + ptr::write_volatile(p_node, node); + ptr::write_volatile(p_list_head, list_head); + } }); } @@ -70,57 +84,84 @@ impl LinkedListNode { pub unsafe fn insert_tail(mut p_list_tail: *mut LinkedListNode, mut p_node: *mut LinkedListNode) { interrupt::free(|_| { let mut list_tail = ptr::read_volatile(p_list_tail); - let mut node_prev = ptr::read_volatile(list_tail.prev); - let node = LinkedListNode { - next: p_list_tail, - prev: list_tail.prev, - }; + if p_list_tail != list_tail.prev { + let mut node_prev = ptr::read_volatile(list_tail.prev); + let node = LinkedListNode { + next: p_list_tail, + prev: list_tail.prev, + }; - list_tail.prev = p_node; - node_prev.next = p_node; + list_tail.prev = p_node; + node_prev.next = p_node; - // All nodes must be written because they will all be seen by another core - ptr::write_volatile(p_node, node); - ptr::write_volatile(node.prev, node_prev); - ptr::write_volatile(p_list_tail, list_tail); + // All nodes must be written because they will all be seen by another core + ptr::write_volatile(p_node, node); + ptr::write_volatile(node.prev, node_prev); + ptr::write_volatile(p_list_tail, list_tail); + } else { + let node = LinkedListNode { + next: p_list_tail, + prev: list_tail.prev, + }; + + list_tail.prev = p_node; + list_tail.next = p_node; + + // All nodes must be written because they will all be seen by another core + ptr::write_volatile(p_node, node); + ptr::write_volatile(p_list_tail, list_tail); + } }); } /// Remove `node` from the linked list pub unsafe fn remove_node(mut p_node: *mut LinkedListNode) { interrupt::free(|_| { - // Writes must occur sequentially, because if prev node, and next node are the same, both must be updated let node = ptr::read_volatile(p_node); - let mut node_prev = ptr::read_volatile(node.prev); - node_prev.next = node.next; - ptr::write_volatile(node.prev, node_prev); + if node.next != node.prev { + let mut node_next = ptr::read_volatile(node.next); + let mut node_prev = ptr::read_volatile(node.prev); - let mut node_next = ptr::read_volatile(node.next); - node_next.prev = node.prev; - ptr::write_volatile(node.next, node_next); + node_prev.next = node.next; + node_next.prev = node.prev; + + ptr::write_volatile(node.next, node_next); + ptr::write_volatile(node.prev, node_prev); + } else { + let mut node_next = ptr::read_volatile(node.next); + + node_next.next = node.next; + node_next.prev = node.prev; + + ptr::write_volatile(node.next, node_next); + } }); } - /// Remove `list_head` into `node` - pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { + /// Remove `list_head` and return a pointer to the `node`. + pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode) -> *mut LinkedListNode { interrupt::free(|_| { let list_head = ptr::read_volatile(p_list_head); // Allowed because a removed node is not seen by another core - *p_node = list_head.next; - Self::remove_node(*p_node); - }); + let p_node = list_head.next; + Self::remove_node(p_node); + + p_node + }) } - /// Remove `list_tail` into `node` - pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { + /// Remove `list_tail` and return a pointer to the `node`. + pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode) -> *mut LinkedListNode { interrupt::free(|_| { let list_tail = ptr::read_volatile(p_list_tail); // Allowed because a removed node is not seen by another core - *p_node = list_tail.prev; - Self::remove_node(*p_node); - }); + let p_node = list_tail.prev; + Self::remove_node(p_node); + + p_node + }) } pub unsafe fn insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { @@ -130,6 +171,8 @@ impl LinkedListNode { (*ref_node).next = node; (*(*node).next).prev = node; }); + + todo!("this function has not been converted to volatile semantics"); } pub unsafe fn insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { @@ -139,6 +182,8 @@ impl LinkedListNode { (*ref_node).prev = node; (*(*node).prev).next = node; }); + + todo!("this function has not been converted to volatile semantics"); } pub unsafe fn get_size(mut list_head: *mut LinkedListNode) -> usize { @@ -153,7 +198,9 @@ impl LinkedListNode { } size - }) + }); + + todo!("this function has not been converted to volatile semantics"); } pub unsafe fn get_next_node(mut p_ref_node: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { @@ -165,9 +212,12 @@ impl LinkedListNode { }); } - pub unsafe fn get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + pub unsafe fn get_prev_node(mut p_ref_node: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { interrupt::free(|_| { - *node = (*ref_node).prev; + let ref_node = ptr::read_volatile(p_ref_node); + + // Allowed because a removed node is not seen by another core + *p_node = ref_node.prev; }); } } From 4601f4e1ebc94aa50edd224af087168bc996d7af Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 13 Jun 2023 21:15:01 -0500 Subject: [PATCH 74/98] stm32/wpan: minor linked list cleanpu --- embassy-stm32-wpan/src/unsafe_linked_list.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs index ddec1afbc..a312178b3 100644 --- a/embassy-stm32-wpan/src/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -203,22 +203,22 @@ impl LinkedListNode { todo!("this function has not been converted to volatile semantics"); } - pub unsafe fn get_next_node(mut p_ref_node: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { + pub unsafe fn get_next_node(mut p_ref_node: *mut LinkedListNode) -> *mut LinkedListNode { interrupt::free(|_| { let ref_node = ptr::read_volatile(p_ref_node); // Allowed because a removed node is not seen by another core - *p_node = ref_node.next; - }); + ref_node.next + }) } - pub unsafe fn get_prev_node(mut p_ref_node: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) { + pub unsafe fn get_prev_node(mut p_ref_node: *mut LinkedListNode) -> *mut LinkedListNode { interrupt::free(|_| { let ref_node = ptr::read_volatile(p_ref_node); // Allowed because a removed node is not seen by another core - *p_node = ref_node.prev; - }); + ref_node.prev + }) } } From c94ba8489289789e295a248720c96040b2dc724c Mon Sep 17 00:00:00 2001 From: Kevin Lannen Date: Wed, 14 Jun 2023 10:44:51 -0600 Subject: [PATCH 75/98] stm32g4: PLL: Add support for configuring PLL_P and PLL_Q --- embassy-stm32/src/rcc/g4.rs | 207 ++++++++++++++++++++++++++------ examples/stm32g4/src/bin/pll.rs | 15 ++- 2 files changed, 184 insertions(+), 38 deletions(-) diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 2b52416b2..9401af4c3 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -17,7 +17,7 @@ pub const LSI_FREQ: Hertz = Hertz(32_000); pub enum ClockSrc { HSE(Hertz), HSI16, - PLLCLK(PllSrc, PllM, PllN, PllR), + PLL, } /// AHB prescaler @@ -60,6 +60,68 @@ impl Into for PllSrc { } } +seq_macro::seq!(P in 2..=31 { + /// Output divider for the PLL P output. + #[derive(Clone, Copy)] + pub enum PllP { + // Note: If PLL P is set to 0 the PLLP bit controls the output division. There does not seem to + // a good reason to do this so the API does not support it. + // Div1 is invalid + #( + Div~P, + )* + } + + impl From for u8 { + /// Returns the register value for the P output divider. + fn from(val: PllP) -> u8 { + match val { + #( + PllP::Div~P => P, + )* + } + } + } +}); + +impl PllP { + /// Returns the numeric value of the P output divider. + pub fn to_div(self) -> u32 { + let val: u8 = self.into(); + val as u32 + } +} + +/// Output divider for the PLL Q output. +#[derive(Clone, Copy)] +pub enum PllQ { + Div2, + Div4, + Div6, + Div8, +} + +impl PllQ { + /// Returns the numeric value of the Q output divider. + pub fn to_div(self) -> u32 { + let val: u8 = self.into(); + (val as u32 + 1) * 2 + } +} + +impl From for u8 { + /// Returns the register value for the Q output divider. + fn from(val: PllQ) -> u8 { + match val { + PllQ::Div2 => 0b00, + PllQ::Div4 => 0b01, + PllQ::Div6 => 0b10, + PllQ::Div8 => 0b11, + } + } +} + +/// Output divider for the PLL R output. #[derive(Clone, Copy)] pub enum PllR { Div2, @@ -69,6 +131,7 @@ pub enum PllR { } impl PllR { + /// Returns the numeric value of the R output divider. pub fn to_div(self) -> u32 { let val: u8 = self.into(); (val as u32 + 1) * 2 @@ -76,6 +139,7 @@ impl PllR { } impl From for u8 { + /// Returns the register value for the R output divider. fn from(val: PllR) -> u8 { match val { PllR::Div2 => 0b00, @@ -87,6 +151,7 @@ impl From for u8 { } seq_macro::seq!(N in 8..=127 { + /// Multiplication factor for the PLL VCO input clock. #[derive(Clone, Copy)] pub enum PllN { #( @@ -95,6 +160,7 @@ seq_macro::seq!(N in 8..=127 { } impl From for u8 { + /// Returns the register value for the N multiplication factor. fn from(val: PllN) -> u8 { match val { #( @@ -105,6 +171,7 @@ seq_macro::seq!(N in 8..=127 { } impl PllN { + /// Returns the numeric value of the N multiplication factor. pub fn to_mul(self) -> u32 { match self { #( @@ -115,7 +182,7 @@ seq_macro::seq!(N in 8..=127 { } }); -// Pre-division +/// PLL Pre-division. This must be set such that the PLL input is between 2.66 MHz and 16 MHz. #[derive(Copy, Clone)] pub enum PllM { Div1, @@ -137,6 +204,7 @@ pub enum PllM { } impl PllM { + /// Returns the numeric value of the M pre-division. pub fn to_div(self) -> u32 { let val: u8 = self.into(); val as u32 + 1 @@ -144,6 +212,7 @@ impl PllM { } impl From for u8 { + /// Returns the register value for the M pre-division. fn from(val: PllM) -> u8 { match val { PllM::Div1 => 0b0000, @@ -166,6 +235,31 @@ impl From for u8 { } } +/// PLL Configuration +/// +/// Use this struct to configure the PLL source, input frequency, multiplication factor, and output +/// dividers. Be sure to keep check the datasheet for your specific part for the appropriate +/// frequency ranges for each of these settings. +pub struct Pll { + /// PLL Source clock selection. + pub source: PllSrc, + + /// PLL pre-divider + pub prediv_m: PllM, + + /// PLL multiplication factor for VCO + pub mul_n: PllN, + + /// PLL division factor for P clock (ADC Clock) + pub div_p: Option, + + /// PLL division factor for Q clock (USB, I2S23, SAI1, FDCAN, QSPI) + pub div_q: Option, + + /// PLL division factor for R clock (SYSCLK) + pub div_r: Option, +} + impl AHBPrescaler { const fn div(self) -> u32 { match self { @@ -229,6 +323,9 @@ pub struct Config { pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, pub low_power_run: bool, + /// Iff PLL is requested as the main clock source in the `mux` field then the PLL configuration + /// MUST turn on the PLLR output. + pub pll: Option, } impl Default for Config { @@ -240,11 +337,80 @@ impl Default for Config { apb1_pre: APBPrescaler::NotDivided, apb2_pre: APBPrescaler::NotDivided, low_power_run: false, + pll: None, } } } +pub struct PllFreq { + pub pll_p: Option, + pub pll_q: Option, + pub pll_r: Option, +} + pub(crate) unsafe fn init(config: Config) { + let pll_freq = config.pll.map(|pll_config| { + let src_freq = match pll_config.source { + PllSrc::HSI16 => { + RCC.cr().write(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + + HSI_FREQ.0 + } + PllSrc::HSE(freq) => { + RCC.cr().write(|w| w.set_hseon(true)); + while !RCC.cr().read().hserdy() {} + freq.0 + } + }; + + // Disable PLL before configuration + RCC.cr().modify(|w| w.set_pllon(false)); + while RCC.cr().read().pllrdy() {} + + let internal_freq = src_freq / pll_config.prediv_m.to_div() * pll_config.mul_n.to_mul(); + + RCC.pllcfgr().write(|w| { + w.set_plln(pll_config.mul_n.into()); + w.set_pllm(pll_config.prediv_m.into()); + w.set_pllsrc(pll_config.source.into()); + }); + + let pll_p_freq = pll_config.div_p.map(|div_p| { + RCC.pllcfgr().modify(|w| { + w.set_pllpdiv(div_p.into()); + w.set_pllpen(true); + }); + Hertz(internal_freq / div_p.to_div()) + }); + + let pll_q_freq = pll_config.div_q.map(|div_q| { + RCC.pllcfgr().modify(|w| { + w.set_pllq(div_q.into()); + w.set_pllqen(true); + }); + Hertz(internal_freq / div_q.to_div()) + }); + + let pll_r_freq = pll_config.div_r.map(|div_r| { + RCC.pllcfgr().modify(|w| { + w.set_pllr(div_r.into()); + w.set_pllren(true); + }); + Hertz(internal_freq / div_r.to_div()) + }); + + // Enable the PLL + RCC.cr().modify(|w| w.set_pllon(true)); + while !RCC.cr().read().pllrdy() {} + + PllFreq { + pll_p: pll_p_freq, + pll_q: pll_q_freq, + pll_r: pll_r_freq, + } + }); + let (sys_clk, sw) = match config.mux { ClockSrc::HSI16 => { // Enable HSI16 @@ -260,29 +426,12 @@ pub(crate) unsafe fn init(config: Config) { (freq.0, Sw::HSE) } - ClockSrc::PLLCLK(src, prediv, mul, div) => { - let src_freq = match src { - PllSrc::HSI16 => { - // Enable HSI16 as clock source for PLL - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} + ClockSrc::PLL => { + assert!(pll_freq.is_some()); + assert!(pll_freq.as_ref().unwrap().pll_r.is_some()); - HSI_FREQ.0 - } - PllSrc::HSE(freq) => { - // Enable HSE as clock source for PLL - RCC.cr().write(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} + let freq = pll_freq.unwrap().pll_r.unwrap().0; - freq.0 - } - }; - - // Make sure PLL is disabled while we configure it - RCC.cr().modify(|w| w.set_pllon(false)); - while RCC.cr().read().pllrdy() {} - - let freq = src_freq / prediv.to_div() * mul.to_mul() / div.to_div(); assert!(freq <= 170_000_000); if freq >= 150_000_000 { @@ -316,18 +465,6 @@ pub(crate) unsafe fn init(config: Config) { } } - RCC.pllcfgr().write(move |w| { - w.set_plln(mul.into()); - w.set_pllm(prediv.into()); - w.set_pllr(div.into()); - w.set_pllsrc(src.into()); - }); - - // Enable PLL - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - RCC.pllcfgr().modify(|w| w.set_pllren(true)); - (freq, Sw::PLLRCLK) } }; diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs index 8cee41e9b..ef7d4800c 100644 --- a/examples/stm32g4/src/bin/pll.rs +++ b/examples/stm32g4/src/bin/pll.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{ClockSrc, PllM, PllN, PllR, PllSrc}; +use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllR, PllSrc}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -13,8 +13,17 @@ use {defmt_rtt as _, panic_probe as _}; async fn main(_spawner: Spawner) { let mut config = Config::default(); - // Configure PLL to max frequency of 170 MHz - config.rcc.mux = ClockSrc::PLLCLK(PllSrc::HSI16, PllM::Div4, PllN::Mul85, PllR::Div2); + config.rcc.pll = Some(Pll { + source: PllSrc::HSI16, + prediv_m: PllM::Div4, + mul_n: PllN::Mul85, + div_p: None, + div_q: None, + // Main system clock at 170 MHz + div_r: Some(PllR::Div2), + }); + + config.rcc.mux = ClockSrc::PLL; let _p = embassy_stm32::init(config); info!("Hello World!"); From 61aa6b5236b68b037db1c5f349e8183a2980ffc5 Mon Sep 17 00:00:00 2001 From: Kevin Lannen Date: Wed, 14 Jun 2023 11:07:19 -0600 Subject: [PATCH 76/98] STM32G4: Add USB Serial example --- examples/stm32g4/Cargo.toml | 1 + examples/stm32g4/src/bin/usb_serial.rs | 110 +++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 examples/stm32g4/src/bin/usb_serial.rs diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index f94df2dd3..fbfbc6408 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -10,6 +10,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } +embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs new file mode 100644 index 000000000..ecbe3a6e6 --- /dev/null +++ b/examples/stm32g4/src/bin/usb_serial.rs @@ -0,0 +1,110 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::{panic, *}; +use embassy_executor::Spawner; +use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllQ, PllR, PllSrc}; +use embassy_stm32::time::Hertz; +use embassy_stm32::usb::{self, Driver, Instance}; +use embassy_stm32::{bind_interrupts, pac, peripherals, Config}; +use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; +use embassy_usb::driver::EndpointError; +use embassy_usb::Builder; +use futures::future::join; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + USB_LP => usb::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + + config.rcc.pll = Some(Pll { + source: PllSrc::HSE(Hertz(8000000)), + prediv_m: PllM::Div2, + mul_n: PllN::Mul72, + div_p: None, + // USB and CAN at 48 MHz + div_q: Some(PllQ::Div6), + // Main system clock at 144 MHz + div_r: Some(PllR::Div2), + }); + + config.rcc.mux = ClockSrc::PLL; + + let p = embassy_stm32::init(config); + info!("Hello World!"); + + unsafe { + pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10)); + } + + let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); + + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-Serial Example"); + config.serial_number = Some("123456"); + + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + config.composite_with_iads = true; + + let mut device_descriptor = [0; 256]; + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut device_descriptor, + &mut config_descriptor, + &mut bos_descriptor, + &mut control_buf, + ); + + let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); + + let mut usb = builder.build(); + + let usb_fut = usb.run(); + + let echo_fut = async { + loop { + class.wait_connection().await; + info!("Connected"); + let _ = echo(&mut class).await; + info!("Disconnected"); + } + }; + + join(usb_fut, echo_fut).await; +} + +struct Disconnected {} + +impl From for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => Disconnected {}, + } + } +} + +async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = class.read_packet(&mut buf).await?; + let data = &buf[..n]; + info!("data: {:x}", data); + class.write_packet(data).await?; + } +} From 837950cd7440460f0e1f89e1ab9607f1a9d656ab Mon Sep 17 00:00:00 2001 From: Peter Gibson Date: Wed, 14 Jun 2023 11:56:44 +1000 Subject: [PATCH 77/98] ensure DR is read to clear idle/overflow interrupt when they occur independently of the rxne --- embassy-stm32/src/usart/buffered.rs | 37 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 613da5674..f55123e1d 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -21,27 +21,32 @@ impl interrupt::typelevel::Handler for Interrupt // RX unsafe { let sr = sr(r).read(); + // Reading DR clears the rxne, error and idle interrupt flags on v1. + let dr = if sr.ore() || sr.idle() || sr.rxne() { + Some(rdr(r).read_volatile()) + } + else { + None + }; clear_interrupt_flags(r, sr); + if sr.pe() { + warn!("Parity error"); + } + if sr.fe() { + warn!("Framing error"); + } + if sr.ne() { + warn!("Noise error"); + } + if sr.ore() { + warn!("Overrun error"); + } if sr.rxne() { - if sr.pe() { - warn!("Parity error"); - } - if sr.fe() { - warn!("Framing error"); - } - if sr.ne() { - warn!("Noise error"); - } - if sr.ore() { - warn!("Overrun error"); - } - let mut rx_writer = state.rx_buf.writer(); let buf = rx_writer.push_slice(); if !buf.is_empty() { - // This read also clears the error and idle interrupt flags on v1. - buf[0] = rdr(r).read_volatile(); + buf[0] = dr.unwrap(); rx_writer.push_done(1); } else { // FIXME: Should we disable any further RX interrupts when the buffer becomes full. @@ -54,7 +59,7 @@ impl interrupt::typelevel::Handler for Interrupt if sr.idle() { state.rx_waker.wake(); - }; + } } // TX From d23717904b283fa46a02525acfb42eb9f42e61e3 Mon Sep 17 00:00:00 2001 From: Peter Gibson Date: Thu, 15 Jun 2023 18:33:01 +1000 Subject: [PATCH 78/98] fix formatting --- embassy-stm32/src/usart/buffered.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index f55123e1d..e04b3ea0f 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -48,7 +48,8 @@ impl interrupt::typelevel::Handler for Interrupt if !buf.is_empty() { buf[0] = dr.unwrap(); rx_writer.push_done(1); - } else { + } + else { // FIXME: Should we disable any further RX interrupts when the buffer becomes full. } From d236f3dbf9b53c5e646020946d8da1458eb591a1 Mon Sep 17 00:00:00 2001 From: Peter Gibson Date: Thu, 15 Jun 2023 18:35:58 +1000 Subject: [PATCH 79/98] actually fix formatting --- embassy-stm32/src/usart/buffered.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index e04b3ea0f..530760bd1 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -24,8 +24,7 @@ impl interrupt::typelevel::Handler for Interrupt // Reading DR clears the rxne, error and idle interrupt flags on v1. let dr = if sr.ore() || sr.idle() || sr.rxne() { Some(rdr(r).read_volatile()) - } - else { + } else { None }; clear_interrupt_flags(r, sr); @@ -48,8 +47,7 @@ impl interrupt::typelevel::Handler for Interrupt if !buf.is_empty() { buf[0] = dr.unwrap(); rx_writer.push_done(1); - } - else { + } else { // FIXME: Should we disable any further RX interrupts when the buffer becomes full. } From 837ebe405feabfbee92e9f5e4fc36a5ac56a281c Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 16 Jun 2023 01:32:18 +0200 Subject: [PATCH 80/98] rp: update rp-pac. --- embassy-rp/Cargo.toml | 2 +- embassy-rp/src/adc.rs | 120 +++---- embassy-rp/src/clocks.rs | 82 ++--- embassy-rp/src/critical_section_impl.rs | 19 +- embassy-rp/src/dma.rs | 48 ++- embassy-rp/src/flash.rs | 2 +- embassy-rp/src/float/div.rs | 70 ++-- embassy-rp/src/gpio.rs | 170 +++++---- embassy-rp/src/i2c.rs | 312 ++++++++-------- embassy-rp/src/lib.rs | 30 +- embassy-rp/src/multicore.rs | 56 ++- embassy-rp/src/pio.rs | 450 ++++++++++-------------- embassy-rp/src/pwm.rs | 88 ++--- embassy-rp/src/reset.rs | 4 +- embassy-rp/src/rtc/mod.rs | 81 ++--- embassy-rp/src/spi.rs | 207 +++++------ embassy-rp/src/timer.rs | 30 +- embassy-rp/src/uart/buffered.rs | 275 +++++++-------- embassy-rp/src/uart/mod.rs | 317 ++++++++--------- embassy-rp/src/usb.rs | 299 ++++++++-------- embassy-rp/src/watchdog.rs | 60 ++-- tests/rp/src/bin/float.rs | 10 +- 22 files changed, 1239 insertions(+), 1493 deletions(-) diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index b68f95385..49aa6a4d5 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -76,7 +76,7 @@ embedded-storage = { version = "0.3" } rand_core = "0.6.4" fixed = "1.23.1" -rp-pac = { version = "4" } +rp-pac = { version = "5" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index f29c4dfe1..b96d5a4a8 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -50,16 +50,14 @@ impl<'d> Adc<'d> { _irq: impl Binding, _config: Config, ) -> Self { - unsafe { - let reset = Self::reset(); - crate::reset::reset(reset); - crate::reset::unreset_wait(reset); - let r = Self::regs(); - // Enable ADC - r.cs().write(|w| w.set_en(true)); - // Wait for ADC ready - while !r.cs().read().ready() {} - } + let reset = Self::reset(); + crate::reset::reset(reset); + crate::reset::unreset_wait(reset); + let r = Self::regs(); + // Enable ADC + r.cs().write(|w| w.set_en(true)); + // Wait for ADC ready + while !r.cs().read().ready() {} // Setup IRQ interrupt::ADC_IRQ_FIFO.unpend(); @@ -70,80 +68,70 @@ impl<'d> Adc<'d> { async fn wait_for_ready() { let r = Self::regs(); - unsafe { - r.inte().write(|w| w.set_fifo(true)); - compiler_fence(Ordering::SeqCst); - poll_fn(|cx| { - WAKER.register(cx.waker()); - if r.cs().read().ready() { - return Poll::Ready(()); - } - Poll::Pending - }) - .await; - } + r.inte().write(|w| w.set_fifo(true)); + compiler_fence(Ordering::SeqCst); + poll_fn(|cx| { + WAKER.register(cx.waker()); + if r.cs().read().ready() { + return Poll::Ready(()); + } + Poll::Pending + }) + .await; } pub async fn read, ID = u8> + Pin>(&mut self, pin: &mut PIN) -> u16 { let r = Self::regs(); - unsafe { - // disable pull-down and pull-up resistors - // pull-down resistors are enabled by default - pin.pad_ctrl().modify(|w| { - w.set_ie(true); - let (pu, pd) = (false, false); - w.set_pue(pu); - w.set_pde(pd); - }); - r.cs().modify(|w| { - w.set_ainsel(PIN::channel()); - w.set_start_once(true) - }); - Self::wait_for_ready().await; - r.result().read().result().into() - } + // disable pull-down and pull-up resistors + // pull-down resistors are enabled by default + pin.pad_ctrl().modify(|w| { + w.set_ie(true); + let (pu, pd) = (false, false); + w.set_pue(pu); + w.set_pde(pd); + }); + r.cs().modify(|w| { + w.set_ainsel(PIN::channel()); + w.set_start_once(true) + }); + Self::wait_for_ready().await; + r.result().read().result().into() } pub async fn read_temperature(&mut self) -> u16 { let r = Self::regs(); - unsafe { - r.cs().modify(|w| w.set_ts_en(true)); - if !r.cs().read().ready() { - Self::wait_for_ready().await; - } - r.cs().modify(|w| { - w.set_ainsel(4); - w.set_start_once(true) - }); + r.cs().modify(|w| w.set_ts_en(true)); + if !r.cs().read().ready() { Self::wait_for_ready().await; - r.result().read().result().into() } + r.cs().modify(|w| { + w.set_ainsel(4); + w.set_start_once(true) + }); + Self::wait_for_ready().await; + r.result().read().result().into() } pub fn blocking_read, ID = u8>>(&mut self, _pin: &mut PIN) -> u16 { let r = Self::regs(); - unsafe { - r.cs().modify(|w| { - w.set_ainsel(PIN::channel()); - w.set_start_once(true) - }); - while !r.cs().read().ready() {} - r.result().read().result().into() - } + r.cs().modify(|w| { + w.set_ainsel(PIN::channel()); + w.set_start_once(true) + }); + while !r.cs().read().ready() {} + r.result().read().result().into() } pub fn blocking_read_temperature(&mut self) -> u16 { let r = Self::regs(); - unsafe { - r.cs().modify(|w| w.set_ts_en(true)); - while !r.cs().read().ready() {} - r.cs().modify(|w| { - w.set_ainsel(4); - w.set_start_once(true) - }); - while !r.cs().read().ready() {} - r.result().read().result().into() - } + r.cs().modify(|w| w.set_ts_en(true)); + while !r.cs().read().ready() {} + r.cs().modify(|w| { + w.set_ainsel(4); + w.set_start_once(true) + }); + while !r.cs().read().ready() {} + r.result().read().result().into() } } diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 67439fda3..4c6223107 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -542,7 +542,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { reset::unreset_wait(peris); } -unsafe fn configure_rosc(config: RoscConfig) -> u32 { +fn configure_rosc(config: RoscConfig) -> u32 { let p = pac::ROSC; p.freqa().write(|w| { @@ -620,7 +620,7 @@ pub fn clk_rtc_freq() -> u16 { CLOCKS.rtc.load(Ordering::Relaxed) } -unsafe fn start_xosc(crystal_hz: u32) { +fn start_xosc(crystal_hz: u32) { pac::XOSC .ctrl() .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); @@ -635,7 +635,7 @@ unsafe fn start_xosc(crystal_hz: u32) { } #[inline(always)] -unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 { +fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 { let ref_freq = input_freq / config.refdiv as u32; assert!(config.fbdiv >= 16 && config.fbdiv <= 320); assert!(config.post_div1 >= 1 && config.post_div1 <= 7); @@ -700,9 +700,7 @@ impl<'d, T: Pin> Gpin<'d, T> { pub fn new(gpin: impl Peripheral

+ 'd) -> Gpin<'d, P> { into_ref!(gpin); - unsafe { - gpin.io().ctrl().write(|w| w.set_funcsel(0x08)); - } + gpin.io().ctrl().write(|w| w.set_funcsel(0x08)); Gpin { gpin: gpin.map_into(), @@ -717,12 +715,10 @@ impl<'d, T: Pin> Gpin<'d, T> { impl<'d, T: Pin> Drop for Gpin<'d, T> { fn drop(&mut self) { - unsafe { - self.gpin - .io() - .ctrl() - .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); - } + self.gpin + .io() + .ctrl() + .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); } } @@ -768,53 +764,43 @@ impl<'d, T: GpoutPin> Gpout<'d, T> { pub fn new(gpout: impl Peripheral

+ 'd) -> Self { into_ref!(gpout); - unsafe { - gpout.io().ctrl().write(|w| w.set_funcsel(0x08)); - } + gpout.io().ctrl().write(|w| w.set_funcsel(0x08)); Self { gpout } } pub fn set_div(&self, int: u32, frac: u8) { - unsafe { - let c = pac::CLOCKS; - c.clk_gpout_div(self.gpout.number()).write(|w| { - w.set_int(int); - w.set_frac(frac); - }); - } + let c = pac::CLOCKS; + c.clk_gpout_div(self.gpout.number()).write(|w| { + w.set_int(int); + w.set_frac(frac); + }); } pub fn set_src(&self, src: GpoutSrc) { - unsafe { - let c = pac::CLOCKS; - c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { - w.set_auxsrc(ClkGpoutCtrlAuxsrc(src as _)); - }); - } + let c = pac::CLOCKS; + c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { + w.set_auxsrc(ClkGpoutCtrlAuxsrc(src as _)); + }); } pub fn enable(&self) { - unsafe { - let c = pac::CLOCKS; - c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { - w.set_enable(true); - }); - } + let c = pac::CLOCKS; + c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { + w.set_enable(true); + }); } pub fn disable(&self) { - unsafe { - let c = pac::CLOCKS; - c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { - w.set_enable(false); - }); - } + let c = pac::CLOCKS; + c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { + w.set_enable(false); + }); } pub fn get_freq(&self) -> u32 { let c = pac::CLOCKS; - let src = unsafe { c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc() }; + let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc(); let base = match src { ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(), @@ -831,7 +817,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> { _ => unreachable!(), }; - let div = unsafe { c.clk_gpout_div(self.gpout.number()).read() }; + let div = c.clk_gpout_div(self.gpout.number()).read(); let int = if div.int() == 0 { 65536 } else { div.int() } as u64; let frac = div.frac() as u64; @@ -842,12 +828,10 @@ impl<'d, T: GpoutPin> Gpout<'d, T> { impl<'d, T: GpoutPin> Drop for Gpout<'d, T> { fn drop(&mut self) { self.disable(); - unsafe { - self.gpout - .io() - .ctrl() - .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); - } + self.gpout + .io() + .ctrl() + .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); } } @@ -864,7 +848,7 @@ impl RoscRng { let mut acc = 0; for _ in 0..u8::BITS { acc <<= 1; - acc |= unsafe { random_reg.read().randombit() as u8 }; + acc |= random_reg.read().randombit() as u8; } acc } diff --git a/embassy-rp/src/critical_section_impl.rs b/embassy-rp/src/critical_section_impl.rs index ce284c856..d233e6fab 100644 --- a/embassy-rp/src/critical_section_impl.rs +++ b/embassy-rp/src/critical_section_impl.rs @@ -103,14 +103,11 @@ where /// Try to claim the spinlock. Will return `Some(Self)` if the lock is obtained, and `None` if the lock is /// already in use somewhere else. pub fn try_claim() -> Option { - // Safety: We're only reading from this register - unsafe { - let lock = pac::SIO.spinlock(N).read(); - if lock > 0 { - Some(Self(core::marker::PhantomData)) - } else { - None - } + let lock = pac::SIO.spinlock(N).read(); + if lock > 0 { + Some(Self(core::marker::PhantomData)) + } else { + None } } @@ -120,10 +117,8 @@ where /// /// Only call this function if you hold the spin-lock. pub unsafe fn release() { - unsafe { - // Write (any value): release the lock - pac::SIO.spinlock(N).write_value(1); - } + // Write (any value): release the lock + pac::SIO.spinlock(N).write_value(1); } } diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 25819f03e..1a458778c 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -14,7 +14,7 @@ use crate::{interrupt, pac, peripherals}; #[cfg(feature = "rt")] #[interrupt] -unsafe fn DMA_IRQ_0() { +fn DMA_IRQ_0() { let ints0 = pac::DMA.ints0().read().ints0(); for channel in 0..CHANNEL_COUNT { let ctrl_trig = pac::DMA.ch(channel).ctrl_trig().read(); @@ -128,28 +128,26 @@ fn copy_inner<'a, C: Channel>( ) -> Transfer<'a, C> { into_ref!(ch); - unsafe { - let p = ch.regs(); + let p = ch.regs(); - p.read_addr().write_value(from as u32); - p.write_addr().write_value(to as u32); - p.trans_count().write_value(len as u32); + p.read_addr().write_value(from as u32); + p.write_addr().write_value(to as u32); + p.trans_count().write_value(len as u32); - compiler_fence(Ordering::SeqCst); + compiler_fence(Ordering::SeqCst); - p.ctrl_trig().write(|w| { - // TODO: Add all DREQ options to pac vals::TreqSel, and use - // `set_treq:sel` - w.0 = ((dreq as u32) & 0x3f) << 15usize; - w.set_data_size(data_size); - w.set_incr_read(incr_read); - w.set_incr_write(incr_write); - w.set_chain_to(ch.number()); - w.set_en(true); - }); + p.ctrl_trig().write(|w| { + // TODO: Add all DREQ options to pac vals::TreqSel, and use + // `set_treq:sel` + w.0 = ((dreq as u32) & 0x3f) << 15usize; + w.set_data_size(data_size); + w.set_incr_read(incr_read); + w.set_incr_write(incr_write); + w.set_chain_to(ch.number()); + w.set_en(true); + }); - compiler_fence(Ordering::SeqCst); - } + compiler_fence(Ordering::SeqCst); Transfer::new(ch) } @@ -169,12 +167,10 @@ impl<'a, C: Channel> Transfer<'a, C> { impl<'a, C: Channel> Drop for Transfer<'a, C> { fn drop(&mut self) { let p = self.channel.regs(); - unsafe { - pac::DMA - .chan_abort() - .modify(|m| m.set_chan_abort(1 << self.channel.number())); - while p.ctrl_trig().read().busy() {} - } + pac::DMA + .chan_abort() + .modify(|m| m.set_chan_abort(1 << self.channel.number())); + while p.ctrl_trig().read().busy() {} } } @@ -186,7 +182,7 @@ impl<'a, C: Channel> Future for Transfer<'a, C> { // calls to wake will deregister the waker. CHANNEL_WAKERS[self.channel.number() as usize].register(cx.waker()); - if unsafe { self.channel.regs().ctrl_trig().read().busy() } { + if self.channel.regs().ctrl_trig().read().busy() { Poll::Pending } else { Poll::Ready(()) diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 5d928abad..96d2d4541 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -167,7 +167,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { /// - DMA must not access flash memory unsafe fn in_ram(&mut self, operation: impl FnOnce()) -> Result<(), Error> { // Make sure we're running on CORE0 - let core_id: u32 = unsafe { pac::SIO.cpuid().read() }; + let core_id: u32 = pac::SIO.cpuid().read(); if core_id != 0 { return Err(Error::InvalidCore); } diff --git a/embassy-rp/src/float/div.rs b/embassy-rp/src/float/div.rs index 094dec446..aff0dcb07 100644 --- a/embassy-rp/src/float/div.rs +++ b/embassy-rp/src/float/div.rs @@ -17,45 +17,43 @@ where { let sio = rp_pac::SIO; - unsafe { - // Since we can't save the signed-ness of the calculation, we have to make - // sure that there's at least an 8 cycle delay before we read the result. - // The Pico SDK ensures this by using a 6 cycle push and two 1 cycle reads. - // Since we can't be sure the Rust implementation will optimize to the same, - // just use an explicit wait. - while !sio.div().csr().read().ready() {} + // Since we can't save the signed-ness of the calculation, we have to make + // sure that there's at least an 8 cycle delay before we read the result. + // The Pico SDK ensures this by using a 6 cycle push and two 1 cycle reads. + // Since we can't be sure the Rust implementation will optimize to the same, + // just use an explicit wait. + while !sio.div().csr().read().ready() {} - // Read the quotient last, since that's what clears the dirty flag - let dividend = sio.div().udividend().read(); - let divisor = sio.div().udivisor().read(); - let remainder = sio.div().remainder().read(); - let quotient = sio.div().quotient().read(); + // Read the quotient last, since that's what clears the dirty flag + let dividend = sio.div().udividend().read(); + let divisor = sio.div().udivisor().read(); + let remainder = sio.div().remainder().read(); + let quotient = sio.div().quotient().read(); - // If we get interrupted here (before a write sets the DIRTY flag) its fine, since - // we have the full state, so the interruptor doesn't have to restore it. Once the - // write happens and the DIRTY flag is set, the interruptor becomes responsible for - // restoring our state. - let result = f(); + // If we get interrupted here (before a write sets the DIRTY flag) its fine, since + // we have the full state, so the interruptor doesn't have to restore it. Once the + // write happens and the DIRTY flag is set, the interruptor becomes responsible for + // restoring our state. + let result = f(); - // If we are interrupted here, then the interruptor will start an incorrect calculation - // using a wrong divisor, but we'll restore the divisor and result ourselves correctly. - // This sets DIRTY, so any interruptor will save the state. - sio.div().udividend().write_value(dividend); - // If we are interrupted here, the the interruptor may start the calculation using - // incorrectly signed inputs, but we'll restore the result ourselves. - // This sets DIRTY, so any interruptor will save the state. - sio.div().udivisor().write_value(divisor); - // If we are interrupted here, the interruptor will have restored everything but the - // quotient may be wrongly signed. If the calculation started by the above writes is - // still ongoing it is stopped, so it won't replace the result we're restoring. - // DIRTY and READY set, but only DIRTY matters to make the interruptor save the state. - sio.div().remainder().write_value(remainder); - // State fully restored after the quotient write. This sets both DIRTY and READY, so - // whatever we may have interrupted can read the result. - sio.div().quotient().write_value(quotient); + // If we are interrupted here, then the interruptor will start an incorrect calculation + // using a wrong divisor, but we'll restore the divisor and result ourselves correctly. + // This sets DIRTY, so any interruptor will save the state. + sio.div().udividend().write_value(dividend); + // If we are interrupted here, the the interruptor may start the calculation using + // incorrectly signed inputs, but we'll restore the result ourselves. + // This sets DIRTY, so any interruptor will save the state. + sio.div().udivisor().write_value(divisor); + // If we are interrupted here, the interruptor will have restored everything but the + // quotient may be wrongly signed. If the calculation started by the above writes is + // still ongoing it is stopped, so it won't replace the result we're restoring. + // DIRTY and READY set, but only DIRTY matters to make the interruptor save the state. + sio.div().remainder().write_value(remainder); + // State fully restored after the quotient write. This sets both DIRTY and READY, so + // whatever we may have interrupted can read the result. + sio.div().quotient().write_value(quotient); - result - } + result } fn save_divider(f: F) -> R @@ -63,7 +61,7 @@ where F: FnOnce() -> R, { let sio = rp_pac::SIO; - if unsafe { !sio.div().csr().read().dirty() } { + if !sio.div().csr().read().dirty() { // Not dirty, so nothing is waiting for the calculation. So we can just // issue it directly without a save/restore. f() diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 66faa2489..ce0d02557 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -144,7 +144,7 @@ pub(crate) unsafe fn init() { #[cfg(feature = "rt")] #[interrupt] -unsafe fn IO_IRQ_BANK0() { +fn IO_IRQ_BANK0() { let cpu = SIO.cpuid().read() as usize; // There are two sets of interrupt registers, one for cpu0 and one for cpu1 // and here we are selecting the set that belongs to the currently executing @@ -185,46 +185,44 @@ struct InputFuture<'a, T: Pin> { impl<'d, T: Pin> InputFuture<'d, T> { pub fn new(pin: impl Peripheral

+ 'd, level: InterruptTrigger) -> Self { into_ref!(pin); - unsafe { - let pin_group = (pin.pin() % 8) as usize; - // first, clear the INTR register bits. without this INTR will still - // contain reports of previous edges, causing the IRQ to fire early - // on stale state. clearing these means that we can only detect edges - // that occur *after* the clear happened, but since both this and the - // alternative are fundamentally racy it's probably fine. - // (the alternative being checking the current level and waiting for - // its inverse, but that requires reading the current level and thus - // missing anything that happened before the level was read.) - pac::IO_BANK0.intr(pin.pin() as usize / 8).write(|w| { - w.set_edge_high(pin_group, true); - w.set_edge_low(pin_group, true); - }); + let pin_group = (pin.pin() % 8) as usize; + // first, clear the INTR register bits. without this INTR will still + // contain reports of previous edges, causing the IRQ to fire early + // on stale state. clearing these means that we can only detect edges + // that occur *after* the clear happened, but since both this and the + // alternative are fundamentally racy it's probably fine. + // (the alternative being checking the current level and waiting for + // its inverse, but that requires reading the current level and thus + // missing anything that happened before the level was read.) + pac::IO_BANK0.intr(pin.pin() as usize / 8).write(|w| { + w.set_edge_high(pin_group, true); + w.set_edge_low(pin_group, true); + }); - // Each INTR register is divided into 8 groups, one group for each - // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, - // and EGDE_HIGH. - pin.int_proc() - .inte((pin.pin() / 8) as usize) - .write_set(|w| match level { - InterruptTrigger::LevelHigh => { - trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin()); - w.set_level_high(pin_group, true); - } - InterruptTrigger::LevelLow => { - w.set_level_low(pin_group, true); - } - InterruptTrigger::EdgeHigh => { - w.set_edge_high(pin_group, true); - } - InterruptTrigger::EdgeLow => { - w.set_edge_low(pin_group, true); - } - InterruptTrigger::AnyEdge => { - w.set_edge_high(pin_group, true); - w.set_edge_low(pin_group, true); - } - }); - } + // Each INTR register is divided into 8 groups, one group for each + // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, + // and EGDE_HIGH. + pin.int_proc() + .inte((pin.pin() / 8) as usize) + .write_set(|w| match level { + InterruptTrigger::LevelHigh => { + trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin()); + w.set_level_high(pin_group, true); + } + InterruptTrigger::LevelLow => { + w.set_level_low(pin_group, true); + } + InterruptTrigger::EdgeHigh => { + w.set_edge_high(pin_group, true); + } + InterruptTrigger::EdgeLow => { + w.set_edge_low(pin_group, true); + } + InterruptTrigger::AnyEdge => { + w.set_edge_high(pin_group, true); + w.set_edge_low(pin_group, true); + } + }); Self { pin, level } } @@ -242,7 +240,7 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> { // then we want to access the interrupt enable register for our // pin (there are 4 of these PROC0_INTE0, PROC0_INTE1, PROC0_INTE2, and // PROC0_INTE3 per cpu). - let inte: pac::io::regs::Int = unsafe { self.pin.int_proc().inte((self.pin.pin() / 8) as usize).read() }; + let inte: pac::io::regs::Int = self.pin.int_proc().inte((self.pin.pin() / 8) as usize).read(); // The register is divided into groups of four, one group for // each pin. Each group consists of four trigger levels LEVEL_LOW, // LEVEL_HIGH, EDGE_LOW, and EDGE_HIGH for each pin. @@ -449,15 +447,13 @@ impl<'d, T: Pin> Flex<'d, T> { pub fn new(pin: impl Peripheral

+ 'd) -> Self { into_ref!(pin); - unsafe { - pin.pad_ctrl().write(|w| { - w.set_ie(true); - }); + pin.pad_ctrl().write(|w| { + w.set_ie(true); + }); - pin.io().ctrl().write(|w| { - w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::SIO_0.0); - }); - } + pin.io().ctrl().write(|w| { + w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::SIO_0.0); + }); Self { pin } } @@ -470,43 +466,37 @@ impl<'d, T: Pin> Flex<'d, T> { /// Set the pin's pull. #[inline] pub fn set_pull(&mut self, pull: Pull) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_ie(true); - let (pu, pd) = match pull { - Pull::Up => (true, false), - Pull::Down => (false, true), - Pull::None => (false, false), - }; - w.set_pue(pu); - w.set_pde(pd); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_ie(true); + let (pu, pd) = match pull { + Pull::Up => (true, false), + Pull::Down => (false, true), + Pull::None => (false, false), + }; + w.set_pue(pu); + w.set_pde(pd); + }); } /// Set the pin's drive strength. #[inline] pub fn set_drive_strength(&mut self, strength: Drive) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_drive(match strength { - Drive::_2mA => pac::pads::vals::Drive::_2MA, - Drive::_4mA => pac::pads::vals::Drive::_4MA, - Drive::_8mA => pac::pads::vals::Drive::_8MA, - Drive::_12mA => pac::pads::vals::Drive::_12MA, - }); + self.pin.pad_ctrl().modify(|w| { + w.set_drive(match strength { + Drive::_2mA => pac::pads::vals::Drive::_2MA, + Drive::_4mA => pac::pads::vals::Drive::_4MA, + Drive::_8mA => pac::pads::vals::Drive::_8MA, + Drive::_12mA => pac::pads::vals::Drive::_12MA, }); - } + }); } // Set the pin's slew rate. #[inline] pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_slewfast(slew_rate == SlewRate::Fast); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_slewfast(slew_rate == SlewRate::Fast); + }); } /// Put the pin into input mode. @@ -514,7 +504,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// The pull setting is left unchanged. #[inline] pub fn set_as_input(&mut self) { - unsafe { self.pin.sio_oe().value_clr().write_value(self.bit()) } + self.pin.sio_oe().value_clr().write_value(self.bit()) } /// Put the pin into output mode. @@ -523,17 +513,17 @@ impl<'d, T: Pin> Flex<'d, T> { /// at a specific level, call `set_high`/`set_low` on the pin first. #[inline] pub fn set_as_output(&mut self) { - unsafe { self.pin.sio_oe().value_set().write_value(self.bit()) } + self.pin.sio_oe().value_set().write_value(self.bit()) } #[inline] fn is_set_as_output(&self) -> bool { - unsafe { (self.pin.sio_oe().value().read() & self.bit()) != 0 } + (self.pin.sio_oe().value().read() & self.bit()) != 0 } #[inline] pub fn toggle_set_as_output(&mut self) { - unsafe { self.pin.sio_oe().value_xor().write_value(self.bit()) } + self.pin.sio_oe().value_xor().write_value(self.bit()) } #[inline] @@ -543,7 +533,7 @@ impl<'d, T: Pin> Flex<'d, T> { #[inline] pub fn is_low(&self) -> bool { - unsafe { self.pin.sio_in().read() & self.bit() == 0 } + self.pin.sio_in().read() & self.bit() == 0 } /// Returns current pin level @@ -555,13 +545,13 @@ impl<'d, T: Pin> Flex<'d, T> { /// Set the output as high. #[inline] pub fn set_high(&mut self) { - unsafe { self.pin.sio_out().value_set().write_value(self.bit()) } + self.pin.sio_out().value_set().write_value(self.bit()) } /// Set the output as low. #[inline] pub fn set_low(&mut self) { - unsafe { self.pin.sio_out().value_clr().write_value(self.bit()) } + self.pin.sio_out().value_clr().write_value(self.bit()) } /// Set the output level. @@ -576,7 +566,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// Is the output level high? #[inline] pub fn is_set_high(&self) -> bool { - unsafe { (self.pin.sio_out().value().read() & self.bit()) == 0 } + (self.pin.sio_out().value().read() & self.bit()) == 0 } /// Is the output level low? @@ -594,7 +584,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// Toggle pin output #[inline] pub fn toggle(&mut self) { - unsafe { self.pin.sio_out().value_xor().write_value(self.bit()) } + self.pin.sio_out().value_xor().write_value(self.bit()) } #[inline] @@ -626,12 +616,10 @@ impl<'d, T: Pin> Flex<'d, T> { impl<'d, T: Pin> Drop for Flex<'d, T> { #[inline] fn drop(&mut self) { - unsafe { - self.pin.pad_ctrl().write(|_| {}); - self.pin.io().ctrl().write(|w| { - w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0); - }); - } + self.pin.pad_ctrl().write(|_| {}); + self.pin.io().ctrl().write(|w| { + w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0); + }); } } @@ -688,7 +676,7 @@ pub(crate) mod sealed { Bank::Bank0 => crate::pac::IO_BANK0, Bank::Qspi => crate::pac::IO_QSPI, }; - let proc = unsafe { SIO.cpuid().read() }; + let proc = SIO.cpuid().read(); io_block.int_proc(proc as _) } } diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index ce9a082a2..791c64554 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -85,7 +85,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let r = T::regs(); // mask everything initially - unsafe { r.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)) } + r.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; @@ -135,13 +135,11 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let last = remaining_queue == 0; batch += 1; - unsafe { - p.ic_data_cmd().write(|w| { - w.set_restart(restart && remaining_queue == buffer.len() - 1); - w.set_stop(last && send_stop); - w.set_cmd(true); - }); - } + p.ic_data_cmd().write(|w| { + w.set_restart(restart && remaining_queue == buffer.len() - 1); + w.set_stop(last && send_stop); + w.set_cmd(true); + }); } // We've either run out of txfifo or just plain finished setting up @@ -161,7 +159,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { Poll::Pending } }, - |_me| unsafe { + |_me| { // Set the read threshold to the number of bytes we're // expecting so we don't get spurious interrupts. p.ic_rx_tl().write(|w| w.set_rx_tl(batch - 1)); @@ -185,7 +183,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let rxbytes = (rxfifo as usize).min(remaining); let received = buffer.len() - remaining; for b in &mut buffer[received..received + rxbytes] { - *b = unsafe { p.ic_data_cmd().read().dat() }; + *b = p.ic_data_cmd().read().dat(); } remaining -= rxbytes; } @@ -211,13 +209,11 @@ impl<'d, T: Instance> I2c<'d, T, Async> { if let Some(byte) = bytes.next() { let last = bytes.peek().is_none(); - unsafe { - p.ic_data_cmd().write(|w| { - w.set_stop(last && send_stop); - w.set_cmd(false); - w.set_dat(byte); - }); - } + p.ic_data_cmd().write(|w| { + w.set_stop(last && send_stop); + w.set_cmd(false); + w.set_dat(byte); + }); } else { break 'xmit Ok(()); } @@ -235,7 +231,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { Poll::Pending } }, - |_me| unsafe { + |_me| { // Set tx "free" threshold a little high so that we get // woken before the fifo completely drains to minimize // transfer stalls. @@ -267,7 +263,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let had_abort2 = self .wait_on( - |me| unsafe { + |me| { // We could see an abort while processing fifo backlog, // so handle it here. let abort = me.read_and_clear_abort_reason(); @@ -279,7 +275,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { Poll::Pending } }, - |_me| unsafe { + |_me| { p.ic_intr_mask().modify(|w| { w.set_m_stop_det(true); w.set_m_tx_abrt(true); @@ -287,9 +283,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { }, ) .await; - unsafe { - p.ic_clr_stop_det().read(); - } + p.ic_clr_stop_det().read(); had_abort.and(had_abort2) } else { @@ -336,95 +330,93 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { let p = T::regs(); - unsafe { - let reset = T::reset(); - crate::reset::reset(reset); - crate::reset::unreset_wait(reset); + let reset = T::reset(); + crate::reset::reset(reset); + crate::reset::unreset_wait(reset); - p.ic_enable().write(|w| w.set_enable(false)); + p.ic_enable().write(|w| w.set_enable(false)); - // Select controller mode & speed - p.ic_con().modify(|w| { - // Always use "fast" mode (<= 400 kHz, works fine for standard - // mode too) - w.set_speed(i2c::vals::Speed::FAST); - w.set_master_mode(true); - w.set_ic_slave_disable(true); - w.set_ic_restart_en(true); - w.set_tx_empty_ctrl(true); - }); + // Select controller mode & speed + p.ic_con().modify(|w| { + // Always use "fast" mode (<= 400 kHz, works fine for standard + // mode too) + w.set_speed(i2c::vals::Speed::FAST); + w.set_master_mode(true); + w.set_ic_slave_disable(true); + w.set_ic_restart_en(true); + w.set_tx_empty_ctrl(true); + }); - // Set FIFO watermarks to 1 to make things simpler. This is encoded - // by a register value of 0. - p.ic_tx_tl().write(|w| w.set_tx_tl(0)); - p.ic_rx_tl().write(|w| w.set_rx_tl(0)); + // Set FIFO watermarks to 1 to make things simpler. This is encoded + // by a register value of 0. + p.ic_tx_tl().write(|w| w.set_tx_tl(0)); + p.ic_rx_tl().write(|w| w.set_rx_tl(0)); - // Configure SCL & SDA pins - scl.io().ctrl().write(|w| w.set_funcsel(3)); - sda.io().ctrl().write(|w| w.set_funcsel(3)); + // Configure SCL & SDA pins + scl.io().ctrl().write(|w| w.set_funcsel(3)); + sda.io().ctrl().write(|w| w.set_funcsel(3)); - scl.pad_ctrl().write(|w| { - w.set_schmitt(true); - w.set_ie(true); - w.set_od(false); - w.set_pue(true); - w.set_pde(false); - }); - sda.pad_ctrl().write(|w| { - w.set_schmitt(true); - w.set_ie(true); - w.set_od(false); - w.set_pue(true); - w.set_pde(false); - }); + scl.pad_ctrl().write(|w| { + w.set_schmitt(true); + w.set_ie(true); + w.set_od(false); + w.set_pue(true); + w.set_pde(false); + }); + sda.pad_ctrl().write(|w| { + w.set_schmitt(true); + w.set_ie(true); + w.set_od(false); + w.set_pue(true); + w.set_pde(false); + }); - // Configure baudrate + // Configure baudrate - // There are some subtleties to I2C timing which we are completely - // ignoring here See: - // https://github.com/raspberrypi/pico-sdk/blob/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7/src/rp2_common/hardware_i2c/i2c.c#L69 - let clk_base = crate::clocks::clk_peri_freq(); + // There are some subtleties to I2C timing which we are completely + // ignoring here See: + // https://github.com/raspberrypi/pico-sdk/blob/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7/src/rp2_common/hardware_i2c/i2c.c#L69 + let clk_base = crate::clocks::clk_peri_freq(); - let period = (clk_base + config.frequency / 2) / config.frequency; - let lcnt = period * 3 / 5; // spend 3/5 (60%) of the period low - let hcnt = period - lcnt; // and 2/5 (40%) of the period high + let period = (clk_base + config.frequency / 2) / config.frequency; + let lcnt = period * 3 / 5; // spend 3/5 (60%) of the period low + let hcnt = period - lcnt; // and 2/5 (40%) of the period high - // Check for out-of-range divisors: - assert!(hcnt <= 0xffff); - assert!(lcnt <= 0xffff); - assert!(hcnt >= 8); - assert!(lcnt >= 8); + // Check for out-of-range divisors: + assert!(hcnt <= 0xffff); + assert!(lcnt <= 0xffff); + assert!(hcnt >= 8); + assert!(lcnt >= 8); - // Per I2C-bus specification a device in standard or fast mode must - // internally provide a hold time of at least 300ns for the SDA - // signal to bridge the undefined region of the falling edge of SCL. - // A smaller hold time of 120ns is used for fast mode plus. - let sda_tx_hold_count = if config.frequency < 1_000_000 { - // sda_tx_hold_count = clk_base [cycles/s] * 300ns * (1s / - // 1e9ns) Reduce 300/1e9 to 3/1e7 to avoid numbers that don't - // fit in uint. Add 1 to avoid division truncation. - ((clk_base * 3) / 10_000_000) + 1 - } else { - // fast mode plus requires a clk_base > 32MHz - assert!(clk_base >= 32_000_000); + // Per I2C-bus specification a device in standard or fast mode must + // internally provide a hold time of at least 300ns for the SDA + // signal to bridge the undefined region of the falling edge of SCL. + // A smaller hold time of 120ns is used for fast mode plus. + let sda_tx_hold_count = if config.frequency < 1_000_000 { + // sda_tx_hold_count = clk_base [cycles/s] * 300ns * (1s / + // 1e9ns) Reduce 300/1e9 to 3/1e7 to avoid numbers that don't + // fit in uint. Add 1 to avoid division truncation. + ((clk_base * 3) / 10_000_000) + 1 + } else { + // fast mode plus requires a clk_base > 32MHz + assert!(clk_base >= 32_000_000); - // sda_tx_hold_count = clk_base [cycles/s] * 120ns * (1s / - // 1e9ns) Reduce 120/1e9 to 3/25e6 to avoid numbers that don't - // fit in uint. Add 1 to avoid division truncation. - ((clk_base * 3) / 25_000_000) + 1 - }; - assert!(sda_tx_hold_count <= lcnt - 2); + // sda_tx_hold_count = clk_base [cycles/s] * 120ns * (1s / + // 1e9ns) Reduce 120/1e9 to 3/25e6 to avoid numbers that don't + // fit in uint. Add 1 to avoid division truncation. + ((clk_base * 3) / 25_000_000) + 1 + }; + assert!(sda_tx_hold_count <= lcnt - 2); - p.ic_fs_scl_hcnt().write(|w| w.set_ic_fs_scl_hcnt(hcnt as u16)); - p.ic_fs_scl_lcnt().write(|w| w.set_ic_fs_scl_lcnt(lcnt as u16)); - p.ic_fs_spklen() - .write(|w| w.set_ic_fs_spklen(if lcnt < 16 { 1 } else { (lcnt / 16) as u8 })); - p.ic_sda_hold() - .modify(|w| w.set_ic_sda_tx_hold(sda_tx_hold_count as u16)); + p.ic_fs_scl_hcnt().write(|w| w.set_ic_fs_scl_hcnt(hcnt as u16)); + p.ic_fs_scl_lcnt().write(|w| w.set_ic_fs_scl_lcnt(lcnt as u16)); + p.ic_fs_spklen() + .write(|w| w.set_ic_fs_spklen(if lcnt < 16 { 1 } else { (lcnt / 16) as u8 })); + p.ic_sda_hold() + .modify(|w| w.set_ic_sda_tx_hold(sda_tx_hold_count as u16)); - // Enable I2C block - p.ic_enable().write(|w| w.set_enable(true)); - } + // Enable I2C block + p.ic_enable().write(|w| w.set_enable(true)); Self { phantom: PhantomData } } @@ -439,11 +431,9 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { } let p = T::regs(); - unsafe { - p.ic_enable().write(|w| w.set_enable(false)); - p.ic_tar().write(|w| w.set_ic_tar(addr)); - p.ic_enable().write(|w| w.set_enable(true)); - } + p.ic_enable().write(|w| w.set_enable(false)); + p.ic_tar().write(|w| w.set_ic_tar(addr)); + p.ic_enable().write(|w| w.set_enable(true)); Ok(()) } @@ -455,40 +445,38 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { #[inline] fn tx_fifo_capacity() -> u8 { let p = T::regs(); - unsafe { FIFO_SIZE - p.ic_txflr().read().txflr() } + FIFO_SIZE - p.ic_txflr().read().txflr() } #[inline] fn rx_fifo_len() -> u8 { let p = T::regs(); - unsafe { p.ic_rxflr().read().rxflr() } + p.ic_rxflr().read().rxflr() } fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> { let p = T::regs(); - unsafe { - let abort_reason = p.ic_tx_abrt_source().read(); - if abort_reason.0 != 0 { - // Note clearing the abort flag also clears the reason, and this - // instance of flag is clear-on-read! Note also the - // IC_CLR_TX_ABRT register always reads as 0. - p.ic_clr_tx_abrt().read(); + let abort_reason = p.ic_tx_abrt_source().read(); + if abort_reason.0 != 0 { + // Note clearing the abort flag also clears the reason, and this + // instance of flag is clear-on-read! Note also the + // IC_CLR_TX_ABRT register always reads as 0. + p.ic_clr_tx_abrt().read(); - let reason = if abort_reason.abrt_7b_addr_noack() - | abort_reason.abrt_10addr1_noack() - | abort_reason.abrt_10addr2_noack() - { - AbortReason::NoAcknowledge - } else if abort_reason.arb_lost() { - AbortReason::ArbitrationLoss - } else { - AbortReason::Other(abort_reason.0) - }; - - Err(Error::Abort(reason)) + let reason = if abort_reason.abrt_7b_addr_noack() + | abort_reason.abrt_10addr1_noack() + | abort_reason.abrt_10addr2_noack() + { + AbortReason::NoAcknowledge + } else if abort_reason.arb_lost() { + AbortReason::ArbitrationLoss } else { - Ok(()) - } + AbortReason::Other(abort_reason.0) + }; + + Err(Error::Abort(reason)) + } else { + Ok(()) } } @@ -503,24 +491,21 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { let first = i == 0; let last = i == lastindex; - // NOTE(unsafe) We have &mut self - unsafe { - // wait until there is space in the FIFO to write the next byte - while Self::tx_fifo_full() {} + // wait until there is space in the FIFO to write the next byte + while Self::tx_fifo_full() {} - p.ic_data_cmd().write(|w| { - w.set_restart(restart && first); - w.set_stop(send_stop && last); + p.ic_data_cmd().write(|w| { + w.set_restart(restart && first); + w.set_stop(send_stop && last); - w.set_cmd(true); - }); + w.set_cmd(true); + }); - while Self::rx_fifo_len() == 0 { - self.read_and_clear_abort_reason()?; - } - - *byte = p.ic_data_cmd().read().dat(); + while Self::rx_fifo_len() == 0 { + self.read_and_clear_abort_reason()?; } + + *byte = p.ic_data_cmd().read().dat(); } Ok(()) @@ -536,36 +521,33 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { for (i, byte) in write.iter().enumerate() { let last = i == write.len() - 1; - // NOTE(unsafe) We have &mut self - unsafe { - p.ic_data_cmd().write(|w| { - w.set_stop(send_stop && last); - w.set_dat(*byte); - }); + p.ic_data_cmd().write(|w| { + w.set_stop(send_stop && last); + w.set_dat(*byte); + }); - // Wait until the transmission of the address/data from the - // internal shift register has completed. For this to function - // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The - // TX_EMPTY_CTRL flag was set in i2c_init. - while !p.ic_raw_intr_stat().read().tx_empty() {} + // Wait until the transmission of the address/data from the + // internal shift register has completed. For this to function + // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The + // TX_EMPTY_CTRL flag was set in i2c_init. + while !p.ic_raw_intr_stat().read().tx_empty() {} - let abort_reason = self.read_and_clear_abort_reason(); + let abort_reason = self.read_and_clear_abort_reason(); - if abort_reason.is_err() || (send_stop && last) { - // If the transaction was aborted or if it completed - // successfully wait until the STOP condition has occurred. + if abort_reason.is_err() || (send_stop && last) { + // If the transaction was aborted or if it completed + // successfully wait until the STOP condition has occurred. - while !p.ic_raw_intr_stat().read().stop_det() {} + while !p.ic_raw_intr_stat().read().stop_det() {} - p.ic_clr_stop_det().read().clr_stop_det(); - } - - // Note the hardware issues a STOP automatically on an abort - // condition. Note also the hardware clears RX FIFO as well as - // TX on abort, ecause we set hwparam - // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0. - abort_reason?; + p.ic_clr_stop_det().read().clr_stop_det(); } + + // Note the hardware issues a STOP automatically on an abort + // condition. Note also the hardware clears RX FIFO as well as + // TX on abort, ecause we set hwparam + // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0. + abort_reason?; } Ok(()) } diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index d6f73219f..4fd3cb46a 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -261,33 +261,39 @@ pub fn init(config: config::Config) -> Peripherals { /// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. trait RegExt { - unsafe fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R; - unsafe fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R; - unsafe fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R; + fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R; + fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R; + fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R; } impl RegExt for pac::common::Reg { - unsafe fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R { + fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R { let mut val = Default::default(); let res = f(&mut val); - let ptr = (self.ptr() as *mut u8).add(0x1000) as *mut T; - ptr.write_volatile(val); + unsafe { + let ptr = (self.as_ptr() as *mut u8).add(0x1000) as *mut T; + ptr.write_volatile(val); + } res } - unsafe fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R { + fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R { let mut val = Default::default(); let res = f(&mut val); - let ptr = (self.ptr() as *mut u8).add(0x2000) as *mut T; - ptr.write_volatile(val); + unsafe { + let ptr = (self.as_ptr() as *mut u8).add(0x2000) as *mut T; + ptr.write_volatile(val); + } res } - unsafe fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R { + fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R { let mut val = Default::default(); let res = f(&mut val); - let ptr = (self.ptr() as *mut u8).add(0x3000) as *mut T; - ptr.write_volatile(val); + unsafe { + let ptr = (self.as_ptr() as *mut u8).add(0x3000) as *mut T; + ptr.write_volatile(val); + } res } } diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index 2a7e4822a..468e8470a 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -163,14 +163,12 @@ where } // Reset the core - unsafe { - let psm = pac::PSM; - psm.frce_off().modify(|w| w.set_proc1(true)); - while !psm.frce_off().read().proc1() { - cortex_m::asm::nop(); - } - psm.frce_off().modify(|w| w.set_proc1(false)); + let psm = pac::PSM; + psm.frce_off().modify(|w| w.set_proc1(true)); + while !psm.frce_off().read().proc1() { + cortex_m::asm::nop(); } + psm.frce_off().modify(|w| w.set_proc1(false)); // The ARM AAPCS ABI requires 8-byte stack alignment. // #[align] on `struct Stack` ensures the bottom is aligned, but the top could still be @@ -270,14 +268,12 @@ pub fn resume_core1() { // Push a value to the inter-core FIFO, block until space is available #[inline(always)] fn fifo_write(value: u32) { - unsafe { - let sio = pac::SIO; - // Wait for the FIFO to have enough space - while !sio.fifo().st().read().rdy() { - cortex_m::asm::nop(); - } - sio.fifo().wr().write_value(value); + let sio = pac::SIO; + // Wait for the FIFO to have enough space + while !sio.fifo().st().read().rdy() { + cortex_m::asm::nop(); } + sio.fifo().wr().write_value(value); // Fire off an event to the other core. // This is required as the other core may be `wfe` (waiting for event) cortex_m::asm::sev(); @@ -286,38 +282,32 @@ fn fifo_write(value: u32) { // Pop a value from inter-core FIFO, block until available #[inline(always)] fn fifo_read() -> u32 { - unsafe { - let sio = pac::SIO; - // Wait until FIFO has data - while !sio.fifo().st().read().vld() { - cortex_m::asm::nop(); - } - sio.fifo().rd().read() + let sio = pac::SIO; + // Wait until FIFO has data + while !sio.fifo().st().read().vld() { + cortex_m::asm::nop(); } + sio.fifo().rd().read() } // Pop a value from inter-core FIFO, `wfe` until available #[inline(always)] #[allow(unused)] fn fifo_read_wfe() -> u32 { - unsafe { - let sio = pac::SIO; - // Wait until FIFO has data - while !sio.fifo().st().read().vld() { - cortex_m::asm::wfe(); - } - sio.fifo().rd().read() + let sio = pac::SIO; + // Wait until FIFO has data + while !sio.fifo().st().read().vld() { + cortex_m::asm::wfe(); } + sio.fifo().rd().read() } // Drain inter-core FIFO #[inline(always)] fn fifo_drain() { - unsafe { - let sio = pac::SIO; - while sio.fifo().st().read().vld() { - let _ = sio.fifo().rd().read(); - } + let sio = pac::SIO; + while sio.fifo().st().read().vld() { + let _ = sio.fifo().rd().read(); } } diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 0fa3bd771..1b36e0a54 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -87,7 +87,7 @@ const SMIRQ_MASK: u32 = 1 << 8; #[cfg(feature = "rt")] #[interrupt] -unsafe fn PIO0_IRQ_0() { +fn PIO0_IRQ_0() { use crate::pac; let ints = pac::PIO0.irqs(0).ints().read().0; for bit in 0..12 { @@ -100,7 +100,7 @@ unsafe fn PIO0_IRQ_0() { #[cfg(feature = "rt")] #[interrupt] -unsafe fn PIO1_IRQ_0() { +fn PIO1_IRQ_0() { use crate::pac; let ints = pac::PIO1.irqs(0).ints().read().0; for bit in 0..12 { @@ -145,11 +145,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI Poll::Ready(()) } else { WAKERS[PIO::PIO_NO as usize].fifo_out()[SM].register(cx.waker()); - unsafe { - PIO::PIO.irqs(0).inte().write_set(|m| { - m.0 = TXNFULL_MASK << SM; - }); - } + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = TXNFULL_MASK << SM; + }); // debug!("Pending"); Poll::Pending } @@ -158,11 +156,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoOutFuture<'a, 'd, PIO, SM> { fn drop(&mut self) { - unsafe { - PIO::PIO.irqs(0).inte().write_clear(|m| { - m.0 = TXNFULL_MASK << SM; - }); - } + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = TXNFULL_MASK << SM; + }); } } @@ -186,11 +182,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO Poll::Ready(v) } else { WAKERS[PIO::PIO_NO as usize].fifo_in()[SM].register(cx.waker()); - unsafe { - PIO::PIO.irqs(0).inte().write_set(|m| { - m.0 = RXNEMPTY_MASK << SM; - }); - } + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = RXNEMPTY_MASK << SM; + }); //debug!("Pending"); Poll::Pending } @@ -199,11 +193,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoInFuture<'a, 'd, PIO, SM> { fn drop(&mut self) { - unsafe { - PIO::PIO.irqs(0).inte().write_clear(|m| { - m.0 = RXNEMPTY_MASK << SM; - }); - } + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = RXNEMPTY_MASK << SM; + }); } } @@ -220,30 +212,24 @@ impl<'a, 'd, PIO: Instance> Future for IrqFuture<'a, 'd, PIO> { //debug!("Poll {},{}", PIO::PIO_NO, SM); // Check if IRQ flag is already set - if unsafe { PIO::PIO.irq().read().0 & (1 << self.irq_no) != 0 } { - unsafe { - PIO::PIO.irq().write(|m| m.0 = 1 << self.irq_no); - } + if PIO::PIO.irq().read().0 & (1 << self.irq_no) != 0 { + PIO::PIO.irq().write(|m| m.0 = 1 << self.irq_no); return Poll::Ready(()); } WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker()); - unsafe { - PIO::PIO.irqs(0).inte().write_set(|m| { - m.0 = SMIRQ_MASK << self.irq_no; - }); - } + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = SMIRQ_MASK << self.irq_no; + }); Poll::Pending } } impl<'a, 'd, PIO: Instance> Drop for IrqFuture<'a, 'd, PIO> { fn drop(&mut self) { - unsafe { - PIO::PIO.irqs(0).inte().write_clear(|m| { - m.0 = SMIRQ_MASK << self.irq_no; - }); - } + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = SMIRQ_MASK << self.irq_no; + }); } } @@ -256,57 +242,47 @@ impl<'l, PIO: Instance> Pin<'l, PIO> { /// Set the pin's drive strength. #[inline] pub fn set_drive_strength(&mut self, strength: Drive) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_drive(match strength { - Drive::_2mA => pac::pads::vals::Drive::_2MA, - Drive::_4mA => pac::pads::vals::Drive::_4MA, - Drive::_8mA => pac::pads::vals::Drive::_8MA, - Drive::_12mA => pac::pads::vals::Drive::_12MA, - }); + self.pin.pad_ctrl().modify(|w| { + w.set_drive(match strength { + Drive::_2mA => pac::pads::vals::Drive::_2MA, + Drive::_4mA => pac::pads::vals::Drive::_4MA, + Drive::_8mA => pac::pads::vals::Drive::_8MA, + Drive::_12mA => pac::pads::vals::Drive::_12MA, }); - } + }); } // Set the pin's slew rate. #[inline] pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_slewfast(slew_rate == SlewRate::Fast); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_slewfast(slew_rate == SlewRate::Fast); + }); } /// Set the pin's pull. #[inline] pub fn set_pull(&mut self, pull: Pull) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_pue(pull == Pull::Up); - w.set_pde(pull == Pull::Down); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_pue(pull == Pull::Up); + w.set_pde(pull == Pull::Down); + }); } /// Set the pin's schmitt trigger. #[inline] pub fn set_schmitt(&mut self, enable: bool) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_schmitt(enable); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_schmitt(enable); + }); } pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) { let mask = 1 << self.pin(); - unsafe { - if bypass { - PIO::PIO.input_sync_bypass().write_set(|w| *w = mask); - } else { - PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask); - } + if bypass { + PIO::PIO.input_sync_bypass().write_set(|w| *w = mask); + } else { + PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask); } } @@ -321,41 +297,37 @@ pub struct StateMachineRx<'d, PIO: Instance, const SM: usize> { impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { pub fn empty(&self) -> bool { - unsafe { PIO::PIO.fstat().read().rxempty() & (1u8 << SM) != 0 } + PIO::PIO.fstat().read().rxempty() & (1u8 << SM) != 0 } pub fn full(&self) -> bool { - unsafe { PIO::PIO.fstat().read().rxfull() & (1u8 << SM) != 0 } + PIO::PIO.fstat().read().rxfull() & (1u8 << SM) != 0 } pub fn level(&self) -> u8 { - unsafe { (PIO::PIO.flevel().read().0 >> (SM * 8 + 4)) as u8 & 0x0f } + (PIO::PIO.flevel().read().0 >> (SM * 8 + 4)) as u8 & 0x0f } pub fn stalled(&self) -> bool { - unsafe { - let fdebug = PIO::PIO.fdebug(); - let ret = fdebug.read().rxstall() & (1 << SM) != 0; - if ret { - fdebug.write(|w| w.set_rxstall(1 << SM)); - } - ret + let fdebug = PIO::PIO.fdebug(); + let ret = fdebug.read().rxstall() & (1 << SM) != 0; + if ret { + fdebug.write(|w| w.set_rxstall(1 << SM)); } + ret } pub fn underflowed(&self) -> bool { - unsafe { - let fdebug = PIO::PIO.fdebug(); - let ret = fdebug.read().rxunder() & (1 << SM) != 0; - if ret { - fdebug.write(|w| w.set_rxunder(1 << SM)); - } - ret + let fdebug = PIO::PIO.fdebug(); + let ret = fdebug.read().rxunder() & (1 << SM) != 0; + if ret { + fdebug.write(|w| w.set_rxunder(1 << SM)); } + ret } pub fn pull(&mut self) -> u32 { - unsafe { PIO::PIO.rxf(SM).read() } + PIO::PIO.rxf(SM).read() } pub fn try_pull(&mut self) -> Option { @@ -374,24 +346,22 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { ch: PeripheralRef<'a, C>, data: &'a mut [W], ) -> Transfer<'a, C> { - unsafe { - let pio_no = PIO::PIO_NO; - let p = ch.regs(); - p.write_addr().write_value(data.as_ptr() as u32); - p.read_addr().write_value(PIO::PIO.rxf(SM).ptr() as u32); - p.trans_count().write_value(data.len() as u32); - compiler_fence(Ordering::SeqCst); - p.ctrl_trig().write(|w| { - // Set RX DREQ for this statemachine - w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8 + 4)); - w.set_data_size(W::size()); - w.set_chain_to(ch.number()); - w.set_incr_read(false); - w.set_incr_write(true); - w.set_en(true); - }); - compiler_fence(Ordering::SeqCst); - } + let pio_no = PIO::PIO_NO; + let p = ch.regs(); + p.write_addr().write_value(data.as_ptr() as u32); + p.read_addr().write_value(PIO::PIO.rxf(SM).as_ptr() as u32); + p.trans_count().write_value(data.len() as u32); + compiler_fence(Ordering::SeqCst); + p.ctrl_trig().write(|w| { + // Set RX DREQ for this statemachine + w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8 + 4)); + w.set_data_size(W::size()); + w.set_chain_to(ch.number()); + w.set_incr_read(false); + w.set_incr_write(true); + w.set_en(true); + }); + compiler_fence(Ordering::SeqCst); Transfer::new(ch) } } @@ -402,42 +372,36 @@ pub struct StateMachineTx<'d, PIO: Instance, const SM: usize> { impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { pub fn empty(&self) -> bool { - unsafe { PIO::PIO.fstat().read().txempty() & (1u8 << SM) != 0 } + PIO::PIO.fstat().read().txempty() & (1u8 << SM) != 0 } pub fn full(&self) -> bool { - unsafe { PIO::PIO.fstat().read().txfull() & (1u8 << SM) != 0 } + PIO::PIO.fstat().read().txfull() & (1u8 << SM) != 0 } pub fn level(&self) -> u8 { - unsafe { (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f } + (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f } pub fn stalled(&self) -> bool { - unsafe { - let fdebug = PIO::PIO.fdebug(); - let ret = fdebug.read().txstall() & (1 << SM) != 0; - if ret { - fdebug.write(|w| w.set_txstall(1 << SM)); - } - ret + let fdebug = PIO::PIO.fdebug(); + let ret = fdebug.read().txstall() & (1 << SM) != 0; + if ret { + fdebug.write(|w| w.set_txstall(1 << SM)); } + ret } pub fn overflowed(&self) -> bool { - unsafe { - let fdebug = PIO::PIO.fdebug(); - let ret = fdebug.read().txover() & (1 << SM) != 0; - if ret { - fdebug.write(|w| w.set_txover(1 << SM)); - } - ret + let fdebug = PIO::PIO.fdebug(); + let ret = fdebug.read().txover() & (1 << SM) != 0; + if ret { + fdebug.write(|w| w.set_txover(1 << SM)); } + ret } pub fn push(&mut self, v: u32) { - unsafe { - PIO::PIO.txf(SM).write_value(v); - } + PIO::PIO.txf(SM).write_value(v); } pub fn try_push(&mut self, v: u32) -> bool { @@ -453,24 +417,22 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { } pub fn dma_push<'a, C: Channel, W: Word>(&'a mut self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> { - unsafe { - let pio_no = PIO::PIO_NO; - let p = ch.regs(); - p.read_addr().write_value(data.as_ptr() as u32); - p.write_addr().write_value(PIO::PIO.txf(SM).ptr() as u32); - p.trans_count().write_value(data.len() as u32); - compiler_fence(Ordering::SeqCst); - p.ctrl_trig().write(|w| { - // Set TX DREQ for this statemachine - w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8)); - w.set_data_size(W::size()); - w.set_chain_to(ch.number()); - w.set_incr_read(true); - w.set_incr_write(false); - w.set_en(true); - }); - compiler_fence(Ordering::SeqCst); - } + let pio_no = PIO::PIO_NO; + let p = ch.regs(); + p.read_addr().write_value(data.as_ptr() as u32); + p.write_addr().write_value(PIO::PIO.txf(SM).as_ptr() as u32); + p.trans_count().write_value(data.len() as u32); + compiler_fence(Ordering::SeqCst); + p.ctrl_trig().write(|w| { + // Set TX DREQ for this statemachine + w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8)); + w.set_data_size(W::size()); + w.set_chain_to(ch.number()); + w.set_incr_read(true); + w.set_incr_write(false); + w.set_en(true); + }); + compiler_fence(Ordering::SeqCst); Transfer::new(ch) } } @@ -482,9 +444,7 @@ pub struct StateMachine<'d, PIO: Instance, const SM: usize> { impl<'d, PIO: Instance, const SM: usize> Drop for StateMachine<'d, PIO, SM> { fn drop(&mut self) { - unsafe { - PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(1 << SM)); - } + PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(1 << SM)); on_pio_drop::(); } } @@ -647,45 +607,43 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { assert!(config.shift_in.threshold <= 32, "shift_in.threshold must be <= 32"); assert!(config.shift_out.threshold <= 32, "shift_out.threshold must be <= 32"); let sm = Self::this_sm(); - unsafe { - sm.clkdiv().write(|w| w.0 = config.clock_divider.to_bits() << 8); - sm.execctrl().write(|w| { - w.set_side_en(config.exec.side_en); - w.set_side_pindir(config.exec.side_pindir); - w.set_jmp_pin(config.exec.jmp_pin); - w.set_out_en_sel(config.out_en_sel); - w.set_inline_out_en(config.inline_out_en); - w.set_out_sticky(config.out_sticky); - w.set_wrap_top(config.exec.wrap_top); - w.set_wrap_bottom(config.exec.wrap_bottom); - w.set_status_sel(match config.status_sel { - StatusSource::TxFifoLevel => SmExecctrlStatusSel::TXLEVEL, - StatusSource::RxFifoLevel => SmExecctrlStatusSel::RXLEVEL, - }); - w.set_status_n(config.status_n); + sm.clkdiv().write(|w| w.0 = config.clock_divider.to_bits() << 8); + sm.execctrl().write(|w| { + w.set_side_en(config.exec.side_en); + w.set_side_pindir(config.exec.side_pindir); + w.set_jmp_pin(config.exec.jmp_pin); + w.set_out_en_sel(config.out_en_sel); + w.set_inline_out_en(config.inline_out_en); + w.set_out_sticky(config.out_sticky); + w.set_wrap_top(config.exec.wrap_top); + w.set_wrap_bottom(config.exec.wrap_bottom); + w.set_status_sel(match config.status_sel { + StatusSource::TxFifoLevel => SmExecctrlStatusSel::TXLEVEL, + StatusSource::RxFifoLevel => SmExecctrlStatusSel::RXLEVEL, }); - sm.shiftctrl().write(|w| { - w.set_fjoin_rx(config.fifo_join == FifoJoin::RxOnly); - w.set_fjoin_tx(config.fifo_join == FifoJoin::TxOnly); - w.set_pull_thresh(config.shift_out.threshold); - w.set_push_thresh(config.shift_in.threshold); - w.set_out_shiftdir(config.shift_out.direction == ShiftDirection::Right); - w.set_in_shiftdir(config.shift_in.direction == ShiftDirection::Right); - w.set_autopull(config.shift_out.auto_fill); - w.set_autopush(config.shift_in.auto_fill); - }); - sm.pinctrl().write(|w| { - w.set_sideset_count(config.pins.sideset_count); - w.set_set_count(config.pins.set_count); - w.set_out_count(config.pins.out_count); - w.set_in_base(config.pins.in_base); - w.set_sideset_base(config.pins.sideset_base); - w.set_set_base(config.pins.set_base); - w.set_out_base(config.pins.out_base); - }); - if let Some(origin) = config.origin { - pio_instr_util::exec_jmp(self, origin); - } + w.set_status_n(config.status_n); + }); + sm.shiftctrl().write(|w| { + w.set_fjoin_rx(config.fifo_join == FifoJoin::RxOnly); + w.set_fjoin_tx(config.fifo_join == FifoJoin::TxOnly); + w.set_pull_thresh(config.shift_out.threshold); + w.set_push_thresh(config.shift_in.threshold); + w.set_out_shiftdir(config.shift_out.direction == ShiftDirection::Right); + w.set_in_shiftdir(config.shift_in.direction == ShiftDirection::Right); + w.set_autopull(config.shift_out.auto_fill); + w.set_autopush(config.shift_in.auto_fill); + }); + sm.pinctrl().write(|w| { + w.set_sideset_count(config.pins.sideset_count); + w.set_set_count(config.pins.set_count); + w.set_out_count(config.pins.out_count); + w.set_in_base(config.pins.in_base); + w.set_sideset_base(config.pins.sideset_base); + w.set_set_base(config.pins.set_base); + w.set_out_base(config.pins.out_base); + }); + if let Some(origin) = config.origin { + unsafe { pio_instr_util::exec_jmp(self, origin) } } } @@ -696,45 +654,35 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { pub fn restart(&mut self) { let mask = 1u8 << SM; - unsafe { - PIO::PIO.ctrl().write_set(|w| w.set_sm_restart(mask)); - } + PIO::PIO.ctrl().write_set(|w| w.set_sm_restart(mask)); } pub fn set_enable(&mut self, enable: bool) { let mask = 1u8 << SM; - unsafe { - if enable { - PIO::PIO.ctrl().write_set(|w| w.set_sm_enable(mask)); - } else { - PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(mask)); - } + if enable { + PIO::PIO.ctrl().write_set(|w| w.set_sm_enable(mask)); + } else { + PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(mask)); } } pub fn is_enabled(&self) -> bool { - unsafe { PIO::PIO.ctrl().read().sm_enable() & (1u8 << SM) != 0 } + PIO::PIO.ctrl().read().sm_enable() & (1u8 << SM) != 0 } pub fn clkdiv_restart(&mut self) { let mask = 1u8 << SM; - unsafe { - PIO::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask)); - } + PIO::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask)); } fn with_paused(&mut self, f: impl FnOnce(&mut Self)) { let enabled = self.is_enabled(); self.set_enable(false); - let pincfg = unsafe { Self::this_sm().pinctrl().read() }; - let execcfg = unsafe { Self::this_sm().execctrl().read() }; - unsafe { - Self::this_sm().execctrl().write_clear(|w| w.set_out_sticky(true)); - } + let pincfg = Self::this_sm().pinctrl().read(); + let execcfg = Self::this_sm().execctrl().read(); + Self::this_sm().execctrl().write_clear(|w| w.set_out_sticky(true)); f(self); - unsafe { - Self::this_sm().pinctrl().write_value(pincfg); - Self::this_sm().execctrl().write_value(execcfg); - } + Self::this_sm().pinctrl().write_value(pincfg); + Self::this_sm().execctrl().write_value(execcfg); self.set_enable(enabled); } @@ -743,14 +691,12 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { pub fn set_pin_dirs(&mut self, dir: Direction, pins: &[&Pin<'d, PIO>]) { self.with_paused(|sm| { for pin in pins { - unsafe { - Self::this_sm().pinctrl().write(|w| { - w.set_set_base(pin.pin()); - w.set_set_count(1); - }); - // SET PINDIRS, (dir) - sm.exec_instr(0b111_00000_100_00000 | dir as u16); - } + Self::this_sm().pinctrl().write(|w| { + w.set_set_base(pin.pin()); + w.set_set_count(1); + }); + // SET PINDIRS, (dir) + unsafe { sm.exec_instr(0b111_00000_100_00000 | dir as u16) }; } }); } @@ -760,29 +706,25 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { pub fn set_pins(&mut self, level: Level, pins: &[&Pin<'d, PIO>]) { self.with_paused(|sm| { for pin in pins { - unsafe { - Self::this_sm().pinctrl().write(|w| { - w.set_set_base(pin.pin()); - w.set_set_count(1); - }); - // SET PINS, (dir) - sm.exec_instr(0b111_00000_000_00000 | level as u16); - } + Self::this_sm().pinctrl().write(|w| { + w.set_set_base(pin.pin()); + w.set_set_count(1); + }); + // SET PINS, (dir) + unsafe { sm.exec_instr(0b111_00000_000_00000 | level as u16) }; } }); } pub fn clear_fifos(&mut self) { // Toggle FJOIN_RX to flush FIFOs - unsafe { - let shiftctrl = Self::this_sm().shiftctrl(); - shiftctrl.modify(|w| { - w.set_fjoin_rx(!w.fjoin_rx()); - }); - shiftctrl.modify(|w| { - w.set_fjoin_rx(!w.fjoin_rx()); - }); - } + let shiftctrl = Self::this_sm().shiftctrl(); + shiftctrl.modify(|w| { + w.set_fjoin_rx(!w.fjoin_rx()); + }); + shiftctrl.modify(|w| { + w.set_fjoin_rx(!w.fjoin_rx()); + }); } pub unsafe fn exec_instr(&mut self, instr: u16) { @@ -856,11 +798,9 @@ impl<'d, PIO: Instance> Common<'d, PIO> { if (self.instructions_used | used_mask) & mask != 0 { return Err(addr); } - unsafe { - PIO::PIO.instr_mem(addr).write(|w| { - w.set_instr_mem(instr); - }); - } + PIO::PIO.instr_mem(addr).write(|w| { + w.set_instr_mem(instr); + }); used_mask |= mask; } self.instructions_used |= used_mask; @@ -877,17 +817,15 @@ impl<'d, PIO: Instance> Common<'d, PIO> { } pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { - unsafe { - // this can interfere with per-pin bypass functions. splitting the - // modification is going to be fine since nothing that relies on - // it can reasonably run before we finish. - PIO::PIO.input_sync_bypass().write_set(|w| *w = mask & bypass); - PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass); - } + // this can interfere with per-pin bypass functions. splitting the + // modification is going to be fine since nothing that relies on + // it can reasonably run before we finish. + PIO::PIO.input_sync_bypass().write_set(|w| *w = mask & bypass); + PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass); } pub fn get_input_sync_bypass(&self) -> u32 { - unsafe { PIO::PIO.input_sync_bypass().read() } + PIO::PIO.input_sync_bypass().read() } /// Register a pin for PIO usage. Pins will be released from the PIO block @@ -896,9 +834,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> { /// of [`Pio`] do not keep pin registrations alive.** pub fn make_pio_pin(&mut self, pin: impl Peripheral

+ 'd) -> Pin<'d, PIO> { into_ref!(pin); - unsafe { - pin.io().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL.0)); - } + pin.io().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL.0)); // we can be relaxed about this because we're &mut here and nothing is cached PIO::state().used_pins.fetch_or(1 << pin.pin_bank(), Ordering::Relaxed); Pin { @@ -916,13 +852,11 @@ impl<'d, PIO: Instance> Common<'d, PIO> { _pio: PhantomData, }; f(&mut batch); - unsafe { - PIO::PIO.ctrl().modify(|w| { - w.set_clkdiv_restart(batch.clkdiv_restart); - w.set_sm_restart(batch.sm_restart); - w.set_sm_enable((w.sm_enable() & !batch.sm_enable_mask) | batch.sm_enable); - }); - } + PIO::PIO.ctrl().modify(|w| { + w.set_clkdiv_restart(batch.clkdiv_restart); + w.set_sm_restart(batch.sm_restart); + w.set_sm_enable((w.sm_enable() & !batch.sm_enable_mask) | batch.sm_enable); + }); } } @@ -974,11 +908,11 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> { } pub fn check_any(&self, irqs: u8) -> bool { - unsafe { PIO::PIO.irq().read().irq() & irqs != 0 } + PIO::PIO.irq().read().irq() & irqs != 0 } pub fn check_all(&self, irqs: u8) -> bool { - unsafe { PIO::PIO.irq().read().irq() & irqs == irqs } + PIO::PIO.irq().read().irq() & irqs == irqs } pub fn clear(&self, irq_no: usize) { @@ -987,7 +921,7 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> { } pub fn clear_all(&self, irqs: u8) { - unsafe { PIO::PIO.irq().write(|w| w.set_irq(irqs)) } + PIO::PIO.irq().write(|w| w.set_irq(irqs)) } pub fn set(&self, irq_no: usize) { @@ -996,7 +930,7 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> { } pub fn set_all(&self, irqs: u8) { - unsafe { PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs)) } + PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs)) } } @@ -1068,9 +1002,7 @@ fn on_pio_drop() { // we only have 30 pins. don't test the other two since gpio() asserts. for i in 0..30 { if used_pins & (1 << i) != 0 { - unsafe { - pac::IO_BANK0.gpio(i).ctrl().write(|w| w.set_funcsel(null)); - } + pac::IO_BANK0.gpio(i).ctrl().write(|w| w.set_funcsel(null)); } } } diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs index 0f9dcf479..20bb88446 100644 --- a/embassy-rp/src/pwm.rs +++ b/embassy-rp/src/pwm.rs @@ -71,20 +71,18 @@ impl<'d, T: Channel> Pwm<'d, T> { into_ref!(inner); let p = inner.regs(); - unsafe { - p.csr().modify(|w| { - w.set_divmode(divmode); - w.set_en(false); - }); - p.ctr().write(|w| w.0 = 0); - Self::configure(p, &config); + p.csr().modify(|w| { + w.set_divmode(divmode); + w.set_en(false); + }); + p.ctr().write(|w| w.0 = 0); + Self::configure(p, &config); - if let Some(pin) = &a { - pin.io().ctrl().write(|w| w.set_funcsel(4)); - } - if let Some(pin) = &b { - pin.io().ctrl().write(|w| w.set_funcsel(4)); - } + if let Some(pin) = &a { + pin.io().ctrl().write(|w| w.set_funcsel(4)); + } + if let Some(pin) = &b { + pin.io().ctrl().write(|w| w.set_funcsel(4)); } Self { inner, @@ -161,31 +159,29 @@ impl<'d, T: Channel> Pwm<'d, T> { panic!("Requested divider is too large"); } - unsafe { - p.div().write_value(ChDiv(config.divider.to_bits() as u32)); - p.cc().write(|w| { - w.set_a(config.compare_a); - w.set_b(config.compare_b); - }); - p.top().write(|w| w.set_top(config.top)); - p.csr().modify(|w| { - w.set_a_inv(config.invert_a); - w.set_b_inv(config.invert_b); - w.set_ph_correct(config.phase_correct); - w.set_en(config.enable); - }); - } + p.div().write_value(ChDiv(config.divider.to_bits() as u32)); + p.cc().write(|w| { + w.set_a(config.compare_a); + w.set_b(config.compare_b); + }); + p.top().write(|w| w.set_top(config.top)); + p.csr().modify(|w| { + w.set_a_inv(config.invert_a); + w.set_b_inv(config.invert_b); + w.set_ph_correct(config.phase_correct); + w.set_en(config.enable); + }); } #[inline] - pub unsafe fn phase_advance(&mut self) { + pub fn phase_advance(&mut self) { let p = self.inner.regs(); p.csr().write_set(|w| w.set_ph_adv(true)); while p.csr().read().ph_adv() {} } #[inline] - pub unsafe fn phase_retard(&mut self) { + pub fn phase_retard(&mut self) { let p = self.inner.regs(); p.csr().write_set(|w| w.set_ph_ret(true)); while p.csr().read().ph_ret() {} @@ -193,12 +189,12 @@ impl<'d, T: Channel> Pwm<'d, T> { #[inline] pub fn counter(&self) -> u16 { - unsafe { self.inner.regs().ctr().read().ctr() } + self.inner.regs().ctr().read().ctr() } #[inline] pub fn set_counter(&self, ctr: u16) { - unsafe { self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) } + self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) } #[inline] @@ -209,14 +205,12 @@ impl<'d, T: Channel> Pwm<'d, T> { #[inline] pub fn wrapped(&mut self) -> bool { - unsafe { pac::PWM.intr().read().0 & self.bit() != 0 } + pac::PWM.intr().read().0 & self.bit() != 0 } #[inline] pub fn clear_wrapped(&mut self) { - unsafe { - pac::PWM.intr().write_value(Intr(self.bit() as _)); - } + pac::PWM.intr().write_value(Intr(self.bit() as _)); } #[inline] @@ -237,26 +231,22 @@ impl PwmBatch { pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) { let mut en = PwmBatch(0); batch(&mut en); - unsafe { - if enabled { - pac::PWM.en().write_set(|w| w.0 = en.0); - } else { - pac::PWM.en().write_clear(|w| w.0 = en.0); - } + if enabled { + pac::PWM.en().write_set(|w| w.0 = en.0); + } else { + pac::PWM.en().write_clear(|w| w.0 = en.0); } } } impl<'d, T: Channel> Drop for Pwm<'d, T> { fn drop(&mut self) { - unsafe { - self.inner.regs().csr().write_clear(|w| w.set_en(false)); - if let Some(pin) = &self.pin_a { - pin.io().ctrl().write(|w| w.set_funcsel(31)); - } - if let Some(pin) = &self.pin_b { - pin.io().ctrl().write(|w| w.set_funcsel(31)); - } + self.inner.regs().csr().write_clear(|w| w.set_en(false)); + if let Some(pin) = &self.pin_a { + pin.io().ctrl().write(|w| w.set_funcsel(31)); + } + if let Some(pin) = &self.pin_b { + pin.io().ctrl().write(|w| w.set_funcsel(31)); } } } diff --git a/embassy-rp/src/reset.rs b/embassy-rp/src/reset.rs index edd47c223..70512fa14 100644 --- a/embassy-rp/src/reset.rs +++ b/embassy-rp/src/reset.rs @@ -4,11 +4,11 @@ use crate::pac; pub const ALL_PERIPHERALS: Peripherals = Peripherals(0x01ffffff); -pub unsafe fn reset(peris: Peripherals) { +pub(crate) fn reset(peris: Peripherals) { pac::RESETS.reset().write_value(peris); } -pub unsafe fn unreset_wait(peris: Peripherals) { +pub(crate) fn unreset_wait(peris: Peripherals) { // TODO use the "atomic clear" register version pac::RESETS.reset().modify(|v| *v = Peripherals(v.0 & !peris.0)); while ((!pac::RESETS.reset_done().read().0) & peris.0) != 0 {} diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index e1d886d4a..b18f12fc4 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs @@ -26,7 +26,7 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { into_ref!(inner); // Set the RTC divider - unsafe { inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)) }; + inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)); let mut result = Self { inner }; result.set_leap_year_check(true); // should be on by default, make sure this is the case. @@ -38,17 +38,14 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { /// /// Leap year checking is enabled by default. pub fn set_leap_year_check(&mut self, leap_year_check_enabled: bool) { - unsafe { - self.inner - .regs() - .ctrl() - .modify(|w| w.set_force_notleapyear(!leap_year_check_enabled)) - }; + self.inner.regs().ctrl().modify(|w| { + w.set_force_notleapyear(!leap_year_check_enabled); + }); } /// Checks to see if this RealTimeClock is running pub fn is_running(&self) -> bool { - unsafe { self.inner.regs().ctrl().read().rtc_active() } + self.inner.regs().ctrl().read().rtc_active() } /// Set the datetime to a new value. @@ -60,25 +57,23 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { self::datetime::validate_datetime(&t).map_err(RtcError::InvalidDateTime)?; // disable RTC while we configure it - unsafe { - self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); - while self.inner.regs().ctrl().read().rtc_active() { - core::hint::spin_loop(); - } + self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); + while self.inner.regs().ctrl().read().rtc_active() { + core::hint::spin_loop(); + } - self.inner.regs().setup_0().write(|w| { - self::datetime::write_setup_0(&t, w); - }); - self.inner.regs().setup_1().write(|w| { - self::datetime::write_setup_1(&t, w); - }); + self.inner.regs().setup_0().write(|w| { + self::datetime::write_setup_0(&t, w); + }); + self.inner.regs().setup_1().write(|w| { + self::datetime::write_setup_1(&t, w); + }); - // Load the new datetime and re-enable RTC - self.inner.regs().ctrl().write(|w| w.set_load(true)); - self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); - while !self.inner.regs().ctrl().read().rtc_active() { - core::hint::spin_loop(); - } + // Load the new datetime and re-enable RTC + self.inner.regs().ctrl().write(|w| w.set_load(true)); + self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); + while !self.inner.regs().ctrl().read().rtc_active() { + core::hint::spin_loop(); } Ok(()) } @@ -93,8 +88,8 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { return Err(RtcError::NotRunning); } - let rtc_0 = unsafe { self.inner.regs().rtc_0().read() }; - let rtc_1 = unsafe { self.inner.regs().rtc_1().read() }; + let rtc_0 = self.inner.regs().rtc_0().read(); + let rtc_1 = self.inner.regs().rtc_1().read(); self::datetime::datetime_from_registers(rtc_0, rtc_1).map_err(RtcError::InvalidDateTime) } @@ -103,12 +98,10 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { /// /// [`schedule_alarm`]: #method.schedule_alarm pub fn disable_alarm(&mut self) { - unsafe { - self.inner.regs().irq_setup_0().modify(|s| s.set_match_ena(false)); + self.inner.regs().irq_setup_0().modify(|s| s.set_match_ena(false)); - while self.inner.regs().irq_setup_0().read().match_active() { - core::hint::spin_loop(); - } + while self.inner.regs().irq_setup_0().read().match_active() { + core::hint::spin_loop(); } } @@ -132,21 +125,19 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { pub fn schedule_alarm(&mut self, filter: DateTimeFilter) { self.disable_alarm(); - unsafe { - self.inner.regs().irq_setup_0().write(|w| { - filter.write_setup_0(w); - }); - self.inner.regs().irq_setup_1().write(|w| { - filter.write_setup_1(w); - }); + self.inner.regs().irq_setup_0().write(|w| { + filter.write_setup_0(w); + }); + self.inner.regs().irq_setup_1().write(|w| { + filter.write_setup_1(w); + }); - self.inner.regs().inte().modify(|w| w.set_rtc(true)); + self.inner.regs().inte().modify(|w| w.set_rtc(true)); - // Set the enable bit and check if it is set - self.inner.regs().irq_setup_0().modify(|w| w.set_match_ena(true)); - while !self.inner.regs().irq_setup_0().read().match_active() { - core::hint::spin_loop(); - } + // Set the enable bit and check if it is set + self.inner.regs().irq_setup_0().modify(|w| w.set_match_ena(true)); + while !self.inner.regs().irq_setup_0().read().match_active() { + core::hint::spin_loop(); } } diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 7da214743..e817d074e 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -79,39 +79,37 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { ) -> Self { into_ref!(inner); - unsafe { - let p = inner.regs(); - let (presc, postdiv) = calc_prescs(config.frequency); + let p = inner.regs(); + let (presc, postdiv) = calc_prescs(config.frequency); - p.cpsr().write(|w| w.set_cpsdvsr(presc)); - p.cr0().write(|w| { - w.set_dss(0b0111); // 8bit - w.set_spo(config.polarity == Polarity::IdleHigh); - w.set_sph(config.phase == Phase::CaptureOnSecondTransition); - w.set_scr(postdiv); - }); + p.cpsr().write(|w| w.set_cpsdvsr(presc)); + p.cr0().write(|w| { + w.set_dss(0b0111); // 8bit + w.set_spo(config.polarity == Polarity::IdleHigh); + w.set_sph(config.phase == Phase::CaptureOnSecondTransition); + w.set_scr(postdiv); + }); - // Always enable DREQ signals -- harmless if DMA is not listening - p.dmacr().write(|reg| { - reg.set_rxdmae(true); - reg.set_txdmae(true); - }); + // Always enable DREQ signals -- harmless if DMA is not listening + p.dmacr().write(|reg| { + reg.set_rxdmae(true); + reg.set_txdmae(true); + }); - // finally, enable. - p.cr1().write(|w| w.set_sse(true)); + // finally, enable. + p.cr1().write(|w| w.set_sse(true)); - if let Some(pin) = &clk { - pin.io().ctrl().write(|w| w.set_funcsel(1)); - } - if let Some(pin) = &mosi { - pin.io().ctrl().write(|w| w.set_funcsel(1)); - } - if let Some(pin) = &miso { - pin.io().ctrl().write(|w| w.set_funcsel(1)); - } - if let Some(pin) = &cs { - pin.io().ctrl().write(|w| w.set_funcsel(1)); - } + if let Some(pin) = &clk { + pin.io().ctrl().write(|w| w.set_funcsel(1)); + } + if let Some(pin) = &mosi { + pin.io().ctrl().write(|w| w.set_funcsel(1)); + } + if let Some(pin) = &miso { + pin.io().ctrl().write(|w| w.set_funcsel(1)); + } + if let Some(pin) = &cs { + pin.io().ctrl().write(|w| w.set_funcsel(1)); } Self { inner, @@ -122,60 +120,52 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { } pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - for &b in data { - while !p.sr().read().tnf() {} - p.dr().write(|w| w.set_data(b as _)); - while !p.sr().read().rne() {} - let _ = p.dr().read(); - } + let p = self.inner.regs(); + for &b in data { + while !p.sr().read().tnf() {} + p.dr().write(|w| w.set_data(b as _)); + while !p.sr().read().rne() {} + let _ = p.dr().read(); } self.flush()?; Ok(()) } pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - for b in data { - while !p.sr().read().tnf() {} - p.dr().write(|w| w.set_data(*b as _)); - while !p.sr().read().rne() {} - *b = p.dr().read().data() as u8; - } + let p = self.inner.regs(); + for b in data { + while !p.sr().read().tnf() {} + p.dr().write(|w| w.set_data(*b as _)); + while !p.sr().read().rne() {} + *b = p.dr().read().data() as u8; } self.flush()?; Ok(()) } pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - for b in data { - while !p.sr().read().tnf() {} - p.dr().write(|w| w.set_data(0)); - while !p.sr().read().rne() {} - *b = p.dr().read().data() as u8; - } + let p = self.inner.regs(); + for b in data { + while !p.sr().read().tnf() {} + p.dr().write(|w| w.set_data(0)); + while !p.sr().read().rne() {} + *b = p.dr().read().data() as u8; } self.flush()?; Ok(()) } pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - let len = read.len().max(write.len()); - for i in 0..len { - let wb = write.get(i).copied().unwrap_or(0); - while !p.sr().read().tnf() {} - p.dr().write(|w| w.set_data(wb as _)); - while !p.sr().read().rne() {} - let rb = p.dr().read().data() as u8; - if let Some(r) = read.get_mut(i) { - *r = rb; - } + let p = self.inner.regs(); + let len = read.len().max(write.len()); + for i in 0..len { + let wb = write.get(i).copied().unwrap_or(0); + while !p.sr().read().tnf() {} + p.dr().write(|w| w.set_data(wb as _)); + while !p.sr().read().rne() {} + let rb = p.dr().read().data() as u8; + if let Some(r) = read.get_mut(i) { + *r = rb; } } self.flush()?; @@ -183,29 +173,25 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { } pub fn flush(&mut self) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - while p.sr().read().bsy() {} - } + let p = self.inner.regs(); + while p.sr().read().bsy() {} Ok(()) } pub fn set_frequency(&mut self, freq: u32) { let (presc, postdiv) = calc_prescs(freq); let p = self.inner.regs(); - unsafe { - // disable - p.cr1().write(|w| w.set_sse(false)); + // disable + p.cr1().write(|w| w.set_sse(false)); - // change stuff - p.cpsr().write(|w| w.set_cpsdvsr(presc)); - p.cr0().modify(|w| { - w.set_scr(postdiv); - }); + // change stuff + p.cpsr().write(|w| w.set_cpsdvsr(presc)); + p.cr0().modify(|w| { + w.set_scr(postdiv); + }); - // enable - p.cr1().write(|w| w.set_sse(true)); - } + // enable + p.cr1().write(|w| w.set_sse(true)); } } @@ -337,21 +323,19 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let tx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::write(tx_ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) + crate::dma::write(tx_ch, buffer, self.inner.regs().dr().as_ptr() as *mut _, T::TX_DREQ) }; tx_transfer.await; let p = self.inner.regs(); - unsafe { - while p.sr().read().bsy() {} + while p.sr().read().bsy() {} - // clear RX FIFO contents to prevent stale reads - while p.sr().read().rne() { - let _: u16 = p.dr().read().data(); - } - // clear RX overrun interrupt - p.icr().write(|w| w.set_roric(true)); + // clear RX FIFO contents to prevent stale reads + while p.sr().read().rne() { + let _: u16 = p.dr().read().data(); } + // clear RX overrun interrupt + p.icr().write(|w| w.set_roric(true)); Ok(()) } @@ -363,14 +347,19 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let rx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) + crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, buffer, T::RX_DREQ) }; let tx_ch = self.tx_dma.as_mut().unwrap(); let tx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ) + crate::dma::write_repeated( + tx_ch, + self.inner.regs().dr().as_ptr() as *mut u8, + buffer.len(), + T::TX_DREQ, + ) }; join(tx_transfer, rx_transfer).await; Ok(()) @@ -394,7 +383,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let rx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) + crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, rx_ptr, T::RX_DREQ) }; let mut tx_ch = self.tx_dma.as_mut().unwrap(); @@ -403,13 +392,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let tx_transfer = async { let p = self.inner.regs(); unsafe { - crate::dma::write(&mut tx_ch, tx_ptr, p.dr().ptr() as *mut _, T::TX_DREQ).await; + crate::dma::write(&mut tx_ch, tx_ptr, p.dr().as_ptr() as *mut _, T::TX_DREQ).await; if rx_len > tx_len { let write_bytes_len = rx_len - tx_len; // write dummy data // this will disable incrementation of the buffers - crate::dma::write_repeated(tx_ch, p.dr().ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await + crate::dma::write_repeated(tx_ch, p.dr().as_ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await } } }; @@ -418,16 +407,14 @@ impl<'d, T: Instance> Spi<'d, T, Async> { // if tx > rx we should clear any overflow of the FIFO SPI buffer if tx_len > rx_len { let p = self.inner.regs(); - unsafe { - while p.sr().read().bsy() {} + while p.sr().read().bsy() {} - // clear RX FIFO contents to prevent stale reads - while p.sr().read().rne() { - let _: u16 = p.dr().read().data(); - } - // clear RX overrun interrupt - p.icr().write(|w| w.set_roric(true)); + // clear RX FIFO contents to prevent stale reads + while p.sr().read().rne() { + let _: u16 = p.dr().read().data(); } + // clear RX overrun interrupt + p.icr().write(|w| w.set_roric(true)); } Ok(()) @@ -625,14 +612,12 @@ impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> { fn set_config(&mut self, config: &Self::Config) { let p = self.inner.regs(); let (presc, postdiv) = calc_prescs(config.frequency); - unsafe { - p.cpsr().write(|w| w.set_cpsdvsr(presc)); - p.cr0().write(|w| { - w.set_dss(0b0111); // 8bit - w.set_spo(config.polarity == Polarity::IdleHigh); - w.set_sph(config.phase == Phase::CaptureOnSecondTransition); - w.set_scr(postdiv); - }); - } + p.cpsr().write(|w| w.set_cpsdvsr(presc)); + p.cr0().write(|w| { + w.set_dss(0b0111); // 8bit + w.set_spo(config.polarity == Polarity::IdleHigh); + w.set_sph(config.phase == Phase::CaptureOnSecondTransition); + w.set_scr(postdiv); + }); } } diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs index ca8c96c0f..faa8df037 100644 --- a/embassy-rp/src/timer.rs +++ b/embassy-rp/src/timer.rs @@ -34,13 +34,11 @@ embassy_time::time_driver_impl!(static DRIVER: TimerDriver = TimerDriver{ impl Driver for TimerDriver { fn now(&self) -> u64 { loop { - unsafe { - let hi = pac::TIMER.timerawh().read(); - let lo = pac::TIMER.timerawl().read(); - let hi2 = pac::TIMER.timerawh().read(); - if hi == hi2 { - return (hi as u64) << 32 | (lo as u64); - } + let hi = pac::TIMER.timerawh().read(); + let lo = pac::TIMER.timerawl().read(); + let hi2 = pac::TIMER.timerawh().read(); + if hi == hi2 { + return (hi as u64) << 32 | (lo as u64); } } } @@ -78,13 +76,13 @@ impl Driver for TimerDriver { // Note that we're not checking the high bits at all. This means the irq may fire early // if the alarm is more than 72 minutes (2^32 us) in the future. This is OK, since on irq fire // it is checked if the alarm time has passed. - unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; + pac::TIMER.alarm(n).write_value(timestamp as u32); let now = self.now(); if timestamp <= now { // If alarm timestamp has passed the alarm will not fire. // Disarm the alarm and return `false` to indicate that. - unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) } + pac::TIMER.armed().write(|w| w.set_armed(1 << n)); alarm.timestamp.set(u64::MAX); @@ -106,17 +104,17 @@ impl TimerDriver { } else { // Not elapsed, arm it again. // This can happen if it was set more than 2^32 us in the future. - unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; + pac::TIMER.alarm(n).write_value(timestamp as u32); } }); // clear the irq - unsafe { pac::TIMER.intr().write(|w| w.set_alarm(n, true)) } + pac::TIMER.intr().write(|w| w.set_alarm(n, true)); } fn trigger_alarm(&self, n: usize, cs: CriticalSection) { // disarm - unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) } + pac::TIMER.armed().write(|w| w.set_armed(1 << n)); let alarm = &self.alarms.borrow(cs)[n]; alarm.timestamp.set(u64::MAX); @@ -153,24 +151,24 @@ pub unsafe fn init() { #[cfg(feature = "rt")] #[interrupt] -unsafe fn TIMER_IRQ_0() { +fn TIMER_IRQ_0() { DRIVER.check_alarm(0) } #[cfg(feature = "rt")] #[interrupt] -unsafe fn TIMER_IRQ_1() { +fn TIMER_IRQ_1() { DRIVER.check_alarm(1) } #[cfg(feature = "rt")] #[interrupt] -unsafe fn TIMER_IRQ_2() { +fn TIMER_IRQ_2() { DRIVER.check_alarm(2) } #[cfg(feature = "rt")] #[interrupt] -unsafe fn TIMER_IRQ_3() { +fn TIMER_IRQ_3() { DRIVER.check_alarm(3) } diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index 6660d5dc9..30eeb5476 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs @@ -73,16 +73,14 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>( // we clear it after it happens. The downside is that the we manually have // to pend the ISR when we want data transmission to start. let regs = T::regs(); - unsafe { - regs.uartimsc().write(|w| { - w.set_rxim(true); - w.set_rtim(true); - w.set_txim(true); - }); + regs.uartimsc().write(|w| { + w.set_rxim(true); + w.set_rtim(true); + w.set_txim(true); + }); - T::Interrupt::unpend(); - T::Interrupt::enable(); - }; + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; } impl<'d, T: Instance> BufferedUart<'d, T> { @@ -247,12 +245,10 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> { // (Re-)Enable the interrupt to receive more data in case it was // disabled because the buffer was full or errors were detected. let regs = T::regs(); - unsafe { - regs.uartimsc().write_set(|w| { - w.set_rxim(true); - w.set_rtim(true); - }); - } + regs.uartimsc().write_set(|w| { + w.set_rxim(true); + w.set_rtim(true); + }); Poll::Ready(result) } @@ -299,12 +295,10 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> { // (Re-)Enable the interrupt to receive more data in case it was // disabled because the buffer was full or errors were detected. let regs = T::regs(); - unsafe { - regs.uartimsc().write_set(|w| { - w.set_rxim(true); - w.set_rtim(true); - }); - } + regs.uartimsc().write_set(|w| { + w.set_rxim(true); + w.set_rtim(true); + }); } } @@ -414,7 +408,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> { } pub fn busy(&self) -> bool { - unsafe { T::regs().uartfr().read().busy() } + T::regs().uartfr().read().busy() } /// Assert a break condition after waiting for the transmit buffers to empty, @@ -426,42 +420,35 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> { /// for the transmit fifo to empty, which may take a while on slow links. pub async fn send_break(&mut self, bits: u32) { let regs = T::regs(); - let bits = bits.max(unsafe { + let bits = bits.max({ let lcr = regs.uartlcr_h().read(); let width = lcr.wlen() as u32 + 5; let parity = lcr.pen() as u32; let stops = 1 + lcr.stp2() as u32; 2 * (1 + width + parity + stops) }); - let divx64 = unsafe { - ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32 - } as u64; + let divx64 = (((regs.uartibrd().read().baud_divint() as u32) << 6) + + regs.uartfbrd().read().baud_divfrac() as u32) as u64; let div_clk = clk_peri_freq() as u64 * 64; let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk; Self::flush().await.unwrap(); while self.busy() {} - unsafe { - regs.uartlcr_h().write_set(|w| w.set_brk(true)); - } + regs.uartlcr_h().write_set(|w| w.set_brk(true)); Timer::after(Duration::from_micros(wait_usecs)).await; - unsafe { - regs.uartlcr_h().write_clear(|w| w.set_brk(true)); - } + regs.uartlcr_h().write_clear(|w| w.set_brk(true)); } } impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { fn drop(&mut self) { let state = T::buffered_state(); - unsafe { - state.rx_buf.deinit(); + unsafe { state.rx_buf.deinit() } - // TX is inactive if the the buffer is not available. - // We can now unregister the interrupt handler - if state.tx_buf.len() == 0 { - T::Interrupt::disable(); - } + // TX is inactive if the the buffer is not available. + // We can now unregister the interrupt handler + if state.tx_buf.len() == 0 { + T::Interrupt::disable(); } } } @@ -469,14 +456,12 @@ impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> { fn drop(&mut self) { let state = T::buffered_state(); - unsafe { - state.tx_buf.deinit(); + unsafe { state.tx_buf.deinit() } - // RX is inactive if the the buffer is not available. - // We can now unregister the interrupt handler - if state.rx_buf.len() == 0 { - T::Interrupt::disable(); - } + // RX is inactive if the the buffer is not available. + // We can now unregister the interrupt handler + if state.rx_buf.len() == 0 { + T::Interrupt::disable(); } } } @@ -494,94 +479,92 @@ impl interrupt::typelevel::Handler for BufferedInterr let s = T::buffered_state(); - unsafe { - // Clear TX and error interrupt flags - // RX interrupt flags are cleared by reading from the FIFO. - let ris = r.uartris().read(); - r.uarticr().write(|w| { - w.set_txic(ris.txris()); - w.set_feic(ris.feris()); - w.set_peic(ris.peris()); - w.set_beic(ris.beris()); - w.set_oeic(ris.oeris()); - }); + // Clear TX and error interrupt flags + // RX interrupt flags are cleared by reading from the FIFO. + let ris = r.uartris().read(); + r.uarticr().write(|w| { + w.set_txic(ris.txris()); + w.set_feic(ris.feris()); + w.set_peic(ris.peris()); + w.set_beic(ris.beris()); + w.set_oeic(ris.oeris()); + }); - trace!("on_interrupt ris={:#X}", ris.0); + trace!("on_interrupt ris={:#X}", ris.0); - // Errors - if ris.feris() { - warn!("Framing error"); - } - if ris.peris() { - warn!("Parity error"); - } - if ris.beris() { - warn!("Break error"); - } - if ris.oeris() { - warn!("Overrun error"); - } - - // RX - let mut rx_writer = s.rx_buf.writer(); - let rx_buf = rx_writer.push_slice(); - let mut n_read = 0; - let mut error = false; - for rx_byte in rx_buf { - if r.uartfr().read().rxfe() { - break; - } - let dr = r.uartdr().read(); - if (dr.0 >> 8) != 0 { - s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed); - error = true; - // only fill the buffer with valid characters. the current character is fine - // if the error is an overrun, but if we add it to the buffer we'll report - // the overrun one character too late. drop it instead and pretend we were - // a bit slower at draining the rx fifo than we actually were. - // this is consistent with blocking uart error reporting. - break; - } - *rx_byte = dr.data(); - n_read += 1; - } - if n_read > 0 { - rx_writer.push_done(n_read); - s.rx_waker.wake(); - } else if error { - s.rx_waker.wake(); - } - // Disable any further RX interrupts when the buffer becomes full or - // errors have occurred. This lets us buffer additional errors in the - // fifo without needing more error storage locations, and most applications - // will want to do a full reset of their uart state anyway once an error - // has happened. - if s.rx_buf.is_full() || error { - r.uartimsc().write_clear(|w| { - w.set_rxim(true); - w.set_rtim(true); - }); - } - - // TX - let mut tx_reader = s.tx_buf.reader(); - let tx_buf = tx_reader.pop_slice(); - let mut n_written = 0; - for tx_byte in tx_buf.iter_mut() { - if r.uartfr().read().txff() { - break; - } - r.uartdr().write(|w| w.set_data(*tx_byte)); - n_written += 1; - } - if n_written > 0 { - tx_reader.pop_done(n_written); - s.tx_waker.wake(); - } - // The TX interrupt only triggers once when the FIFO threshold is - // crossed. No need to disable it when the buffer becomes empty - // as it does re-trigger anymore once we have cleared it. + // Errors + if ris.feris() { + warn!("Framing error"); } + if ris.peris() { + warn!("Parity error"); + } + if ris.beris() { + warn!("Break error"); + } + if ris.oeris() { + warn!("Overrun error"); + } + + // RX + let mut rx_writer = unsafe { s.rx_buf.writer() }; + let rx_buf = rx_writer.push_slice(); + let mut n_read = 0; + let mut error = false; + for rx_byte in rx_buf { + if r.uartfr().read().rxfe() { + break; + } + let dr = r.uartdr().read(); + if (dr.0 >> 8) != 0 { + s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed); + error = true; + // only fill the buffer with valid characters. the current character is fine + // if the error is an overrun, but if we add it to the buffer we'll report + // the overrun one character too late. drop it instead and pretend we were + // a bit slower at draining the rx fifo than we actually were. + // this is consistent with blocking uart error reporting. + break; + } + *rx_byte = dr.data(); + n_read += 1; + } + if n_read > 0 { + rx_writer.push_done(n_read); + s.rx_waker.wake(); + } else if error { + s.rx_waker.wake(); + } + // Disable any further RX interrupts when the buffer becomes full or + // errors have occurred. This lets us buffer additional errors in the + // fifo without needing more error storage locations, and most applications + // will want to do a full reset of their uart state anyway once an error + // has happened. + if s.rx_buf.is_full() || error { + r.uartimsc().write_clear(|w| { + w.set_rxim(true); + w.set_rtim(true); + }); + } + + // TX + let mut tx_reader = unsafe { s.tx_buf.reader() }; + let tx_buf = tx_reader.pop_slice(); + let mut n_written = 0; + for tx_byte in tx_buf.iter_mut() { + if r.uartfr().read().txff() { + break; + } + r.uartdr().write(|w| w.set_data(*tx_byte)); + n_written += 1; + } + if n_written > 0 { + tx_reader.pop_done(n_written); + s.tx_waker.wake(); + } + // The TX interrupt only triggers once when the FIFO threshold is + // crossed. No need to disable it when the buffer becomes empty + // as it does re-trigger anymore once we have cleared it. } } @@ -695,24 +678,22 @@ mod eh02 { fn read(&mut self) -> Result> { let r = T::regs(); - unsafe { - if r.uartfr().read().rxfe() { - return Err(nb::Error::WouldBlock); - } + if r.uartfr().read().rxfe() { + return Err(nb::Error::WouldBlock); + } - let dr = r.uartdr().read(); + let dr = r.uartdr().read(); - if dr.oe() { - Err(nb::Error::Other(Error::Overrun)) - } else if dr.be() { - Err(nb::Error::Other(Error::Break)) - } else if dr.pe() { - Err(nb::Error::Other(Error::Parity)) - } else if dr.fe() { - Err(nb::Error::Other(Error::Framing)) - } else { - Ok(dr.data()) - } + if dr.oe() { + Err(nb::Error::Other(Error::Overrun)) + } else if dr.be() { + Err(nb::Error::Other(Error::Break)) + } else if dr.pe() { + Err(nb::Error::Other(Error::Parity)) + } else if dr.fe() { + Err(nb::Error::Other(Error::Framing)) + } else { + Ok(dr.data()) } } } diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 5e3ae8a25..7b94bce5e 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -146,23 +146,21 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { let r = T::regs(); - unsafe { - for &b in buffer { - while r.uartfr().read().txff() {} - r.uartdr().write(|w| w.set_data(b)); - } + for &b in buffer { + while r.uartfr().read().txff() {} + r.uartdr().write(|w| w.set_data(b)); } Ok(()) } pub fn blocking_flush(&mut self) -> Result<(), Error> { let r = T::regs(); - unsafe { while !r.uartfr().read().txfe() {} } + while !r.uartfr().read().txfe() {} Ok(()) } pub fn busy(&self) -> bool { - unsafe { T::regs().uartfr().read().busy() } + T::regs().uartfr().read().busy() } /// Assert a break condition after waiting for the transmit buffers to empty, @@ -174,28 +172,23 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { /// for the transmit fifo to empty, which may take a while on slow links. pub async fn send_break(&mut self, bits: u32) { let regs = T::regs(); - let bits = bits.max(unsafe { + let bits = bits.max({ let lcr = regs.uartlcr_h().read(); let width = lcr.wlen() as u32 + 5; let parity = lcr.pen() as u32; let stops = 1 + lcr.stp2() as u32; 2 * (1 + width + parity + stops) }); - let divx64 = unsafe { - ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32 - } as u64; + let divx64 = (((regs.uartibrd().read().baud_divint() as u32) << 6) + + regs.uartfbrd().read().baud_divfrac() as u32) as u64; let div_clk = clk_peri_freq() as u64 * 64; let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk; self.blocking_flush().unwrap(); while self.busy() {} - unsafe { - regs.uartlcr_h().write_set(|w| w.set_brk(true)); - } + regs.uartlcr_h().write_set(|w| w.set_brk(true)); Timer::after(Duration::from_micros(wait_usecs)).await; - unsafe { - regs.uartlcr_h().write_clear(|w| w.set_brk(true)); - } + regs.uartlcr_h().write_clear(|w| w.set_brk(true)); } } @@ -221,7 +214,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> { }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ) + crate::dma::write(ch, buffer, T::regs().uartdr().as_ptr() as *mut _, T::TX_DREQ) }; transfer.await; Ok(()) @@ -246,7 +239,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { debug_assert_eq!(has_irq, rx_dma.is_some()); if has_irq { // disable all error interrupts initially - unsafe { T::regs().uartimsc().write(|w| w.0 = 0) } + T::regs().uartimsc().write(|w| w.0 = 0); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; } @@ -267,11 +260,11 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result { let r = T::regs(); for (i, b) in buffer.iter_mut().enumerate() { - if unsafe { r.uartfr().read().rxfe() } { + if r.uartfr().read().rxfe() { return Ok(i); } - let dr = unsafe { r.uartdr().read() }; + let dr = r.uartdr().read(); if dr.oe() { return Err(Error::Overrun); @@ -292,15 +285,13 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> { fn drop(&mut self) { if let Some(_) = self.rx_dma { - unsafe { - T::Interrupt::disable(); - // clear dma flags. irq handlers use these to disambiguate among themselves. - T::regs().uartdmacr().write_clear(|reg| { - reg.set_rxdmae(true); - reg.set_txdmae(true); - reg.set_dmaonerr(true); - }); - } + T::Interrupt::disable(); + // clear dma flags. irq handlers use these to disambiguate among themselves. + T::regs().uartdmacr().write_clear(|reg| { + reg.set_rxdmae(true); + reg.set_txdmae(true); + reg.set_dmaonerr(true); + }); } } } @@ -355,14 +346,12 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { // clear error flags before we drain the fifo. errors that have accumulated // in the flags will also be present in the fifo. T::dma_state().rx_errs.store(0, Ordering::Relaxed); - unsafe { - T::regs().uarticr().write(|w| { - w.set_oeic(true); - w.set_beic(true); - w.set_peic(true); - w.set_feic(true); - }); - } + T::regs().uarticr().write(|w| { + w.set_oeic(true); + w.set_beic(true); + w.set_peic(true); + w.set_feic(true); + }); // then drain the fifo. we need to read at most 32 bytes. errors that apply // to fifo bytes will be reported directly. @@ -379,20 +368,20 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { // interrupt flags will have been raised, and those will be picked up immediately // by the interrupt handler. let ch = self.rx_dma.as_mut().unwrap(); + T::regs().uartimsc().write_set(|w| { + w.set_oeim(true); + w.set_beim(true); + w.set_peim(true); + w.set_feim(true); + }); + T::regs().uartdmacr().write_set(|reg| { + reg.set_rxdmae(true); + reg.set_dmaonerr(true); + }); let transfer = unsafe { - T::regs().uartimsc().write_set(|w| { - w.set_oeim(true); - w.set_beim(true); - w.set_peim(true); - w.set_feim(true); - }); - T::regs().uartdmacr().write_set(|reg| { - reg.set_rxdmae(true); - reg.set_dmaonerr(true); - }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ) + crate::dma::read(ch, T::regs().uartdr().as_ptr() as *const _, buffer, T::RX_DREQ) }; // wait for either the transfer to complete or an error to happen. @@ -575,81 +564,79 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> { config: Config, ) { let r = T::regs(); - unsafe { - if let Some(pin) = &tx { - pin.io().ctrl().write(|w| { - w.set_funcsel(2); - w.set_outover(if config.invert_tx { - Outover::INVERT - } else { - Outover::NORMAL - }); + if let Some(pin) = &tx { + pin.io().ctrl().write(|w| { + w.set_funcsel(2); + w.set_outover(if config.invert_tx { + Outover::INVERT + } else { + Outover::NORMAL }); - pin.pad_ctrl().write(|w| w.set_ie(true)); - } - if let Some(pin) = &rx { - pin.io().ctrl().write(|w| { - w.set_funcsel(2); - w.set_inover(if config.invert_rx { - Inover::INVERT - } else { - Inover::NORMAL - }); - }); - pin.pad_ctrl().write(|w| w.set_ie(true)); - } - if let Some(pin) = &cts { - pin.io().ctrl().write(|w| { - w.set_funcsel(2); - w.set_inover(if config.invert_cts { - Inover::INVERT - } else { - Inover::NORMAL - }); - }); - pin.pad_ctrl().write(|w| w.set_ie(true)); - } - if let Some(pin) = &rts { - pin.io().ctrl().write(|w| { - w.set_funcsel(2); - w.set_outover(if config.invert_rts { - Outover::INVERT - } else { - Outover::NORMAL - }); - }); - pin.pad_ctrl().write(|w| w.set_ie(true)); - } - - Self::set_baudrate_inner(config.baudrate); - - let (pen, eps) = match config.parity { - Parity::ParityNone => (false, false), - Parity::ParityOdd => (true, false), - Parity::ParityEven => (true, true), - }; - - r.uartlcr_h().write(|w| { - w.set_wlen(config.data_bits.bits()); - w.set_stp2(config.stop_bits == StopBits::STOP2); - w.set_pen(pen); - w.set_eps(eps); - w.set_fen(true); - }); - - r.uartifls().write(|w| { - w.set_rxiflsel(0b000); - w.set_txiflsel(0b000); - }); - - r.uartcr().write(|w| { - w.set_uarten(true); - w.set_rxe(true); - w.set_txe(true); - w.set_ctsen(cts.is_some()); - w.set_rtsen(rts.is_some()); }); + pin.pad_ctrl().write(|w| w.set_ie(true)); } + if let Some(pin) = &rx { + pin.io().ctrl().write(|w| { + w.set_funcsel(2); + w.set_inover(if config.invert_rx { + Inover::INVERT + } else { + Inover::NORMAL + }); + }); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + if let Some(pin) = &cts { + pin.io().ctrl().write(|w| { + w.set_funcsel(2); + w.set_inover(if config.invert_cts { + Inover::INVERT + } else { + Inover::NORMAL + }); + }); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + if let Some(pin) = &rts { + pin.io().ctrl().write(|w| { + w.set_funcsel(2); + w.set_outover(if config.invert_rts { + Outover::INVERT + } else { + Outover::NORMAL + }); + }); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + + Self::set_baudrate_inner(config.baudrate); + + let (pen, eps) = match config.parity { + Parity::ParityNone => (false, false), + Parity::ParityOdd => (true, false), + Parity::ParityEven => (true, true), + }; + + r.uartlcr_h().write(|w| { + w.set_wlen(config.data_bits.bits()); + w.set_stp2(config.stop_bits == StopBits::STOP2); + w.set_pen(pen); + w.set_eps(eps); + w.set_fen(true); + }); + + r.uartifls().write(|w| { + w.set_rxiflsel(0b000); + w.set_txiflsel(0b000); + }); + + r.uartcr().write(|w| { + w.set_uarten(true); + w.set_rxe(true); + w.set_txe(true); + w.set_ctsen(cts.is_some()); + w.set_rtsen(rts.is_some()); + }); } /// sets baudrate on runtime @@ -674,15 +661,13 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> { baud_fbrd = 0; } - unsafe { - // Load PL011's baud divisor registers - r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd)); - r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd)); + // Load PL011's baud divisor registers + r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd)); + r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd)); - // PL011 needs a (dummy) line control register write to latch in the - // divisors. We don't want to actually change LCR contents here. - r.uartlcr_h().modify(|_| {}); - } + // PL011 needs a (dummy) line control register write to latch in the + // divisors. We don't want to actually change LCR contents here. + r.uartlcr_h().modify(|_| {}); } } @@ -731,24 +716,22 @@ mod eh02 { type Error = Error; fn read(&mut self) -> Result> { let r = T::regs(); - unsafe { - if r.uartfr().read().rxfe() { - return Err(nb::Error::WouldBlock); - } + if r.uartfr().read().rxfe() { + return Err(nb::Error::WouldBlock); + } - let dr = r.uartdr().read(); + let dr = r.uartdr().read(); - if dr.oe() { - Err(nb::Error::Other(Error::Overrun)) - } else if dr.be() { - Err(nb::Error::Other(Error::Break)) - } else if dr.pe() { - Err(nb::Error::Other(Error::Parity)) - } else if dr.fe() { - Err(nb::Error::Other(Error::Framing)) - } else { - Ok(dr.data()) - } + if dr.oe() { + Err(nb::Error::Other(Error::Overrun)) + } else if dr.be() { + Err(nb::Error::Other(Error::Break)) + } else if dr.pe() { + Err(nb::Error::Other(Error::Parity)) + } else if dr.fe() { + Err(nb::Error::Other(Error::Framing)) + } else { + Ok(dr.data()) } } } @@ -758,22 +741,18 @@ mod eh02 { fn write(&mut self, word: u8) -> Result<(), nb::Error> { let r = T::regs(); - unsafe { - if r.uartfr().read().txff() { - return Err(nb::Error::WouldBlock); - } - - r.uartdr().write(|w| w.set_data(word)); + if r.uartfr().read().txff() { + return Err(nb::Error::WouldBlock); } + + r.uartdr().write(|w| w.set_data(word)); Ok(()) } fn flush(&mut self) -> Result<(), nb::Error> { let r = T::regs(); - unsafe { - if !r.uartfr().read().txfe() { - return Err(nb::Error::WouldBlock); - } + if !r.uartfr().read().txfe() { + return Err(nb::Error::WouldBlock); } Ok(()) } @@ -854,22 +833,20 @@ mod eh1 { impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> { fn read(&mut self) -> nb::Result { let r = T::regs(); - unsafe { - let dr = r.uartdr().read(); + let dr = r.uartdr().read(); - if dr.oe() { - Err(nb::Error::Other(Error::Overrun)) - } else if dr.be() { - Err(nb::Error::Other(Error::Break)) - } else if dr.pe() { - Err(nb::Error::Other(Error::Parity)) - } else if dr.fe() { - Err(nb::Error::Other(Error::Framing)) - } else if dr.fe() { - Ok(dr.data()) - } else { - Err(nb::Error::WouldBlock) - } + if dr.oe() { + Err(nb::Error::Other(Error::Overrun)) + } else if dr.be() { + Err(nb::Error::Other(Error::Break)) + } else if dr.pe() { + Err(nb::Error::Other(Error::Parity)) + } else if dr.fe() { + Err(nb::Error::Other(Error::Framing)) + } else if dr.fe() { + Ok(dr.data()) + } else { + Err(nb::Error::WouldBlock) } } } diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index 9fb0dfb70..1900ab416 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -39,7 +39,7 @@ impl crate::usb::Instance for peripherals::USB { const EP_COUNT: usize = 16; const EP_MEMORY_SIZE: usize = 4096; -const EP_MEMORY: *mut u8 = pac::USBCTRL_DPRAM.0; +const EP_MEMORY: *mut u8 = pac::USBCTRL_DPRAM.as_ptr() as *mut u8; const NEW_AW: AtomicWaker = AtomicWaker::new(); static BUS_WAKER: AtomicWaker = NEW_AW; @@ -111,7 +111,7 @@ impl<'d, T: Instance> Driver<'d, T> { let regs = T::regs(); unsafe { // zero fill regs - let p = regs.0 as *mut u32; + let p = regs.as_ptr() as *mut u32; for i in 0..0x9c / 4 { p.add(i).write_volatile(0) } @@ -121,20 +121,20 @@ impl<'d, T: Instance> Driver<'d, T> { for i in 0..0x100 / 4 { p.add(i).write_volatile(0) } - - regs.usb_muxing().write(|w| { - w.set_to_phy(true); - w.set_softcon(true); - }); - regs.usb_pwr().write(|w| { - w.set_vbus_detect(true); - w.set_vbus_detect_override_en(true); - }); - regs.main_ctrl().write(|w| { - w.set_controller_en(true); - }); } + regs.usb_muxing().write(|w| { + w.set_to_phy(true); + w.set_softcon(true); + }); + regs.usb_pwr().write(|w| { + w.set_vbus_detect(true); + w.set_vbus_detect_override_en(true); + }); + regs.main_ctrl().write(|w| { + w.set_controller_en(true); + }); + // Initialize the bus so that it signals that power is available BUS_WAKER.wake(); @@ -213,22 +213,18 @@ impl<'d, T: Instance> Driver<'d, T> { }; match D::dir() { - Direction::Out => unsafe { - T::dpram().ep_out_control(index - 1).write(|w| { - w.set_enable(false); - w.set_buffer_address(addr); - w.set_interrupt_per_buff(true); - w.set_endpoint_type(ep_type_reg); - }) - }, - Direction::In => unsafe { - T::dpram().ep_in_control(index - 1).write(|w| { - w.set_enable(false); - w.set_buffer_address(addr); - w.set_interrupt_per_buff(true); - w.set_endpoint_type(ep_type_reg); - }) - }, + Direction::Out => T::dpram().ep_out_control(index - 1).write(|w| { + w.set_enable(false); + w.set_buffer_address(addr); + w.set_interrupt_per_buff(true); + w.set_endpoint_type(ep_type_reg); + }), + Direction::In => T::dpram().ep_in_control(index - 1).write(|w| { + w.set_enable(false); + w.set_buffer_address(addr); + w.set_interrupt_per_buff(true); + w.set_endpoint_type(ep_type_reg); + }), } Ok(Endpoint { @@ -315,22 +311,21 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { let regs = T::regs(); - unsafe { - regs.inte().write(|w| { - w.set_bus_reset(true); - w.set_buff_status(true); - w.set_dev_resume_from_host(true); - w.set_dev_suspend(true); - w.set_setup_req(true); - }); - regs.int_ep_ctrl().write(|w| { - w.set_int_ep_active(0xFFFE); // all EPs - }); - regs.sie_ctrl().write(|w| { - w.set_ep0_int_1buf(true); - w.set_pullup_en(true); - }) - } + regs.inte().write(|w| { + w.set_bus_reset(true); + w.set_buff_status(true); + w.set_dev_resume_from_host(true); + w.set_dev_suspend(true); + w.set_setup_req(true); + }); + regs.int_ep_ctrl().write(|w| { + w.set_int_ep_active(0xFFFE); // all EPs + }); + regs.sie_ctrl().write(|w| { + w.set_ep0_int_1buf(true); + w.set_pullup_en(true); + }); + trace!("enabled"); ( @@ -355,7 +350,7 @@ pub struct Bus<'d, T: Instance> { impl<'d, T: Instance> driver::Bus for Bus<'d, T> { async fn poll(&mut self) -> Event { - poll_fn(move |cx| unsafe { + poll_fn(move |cx| { BUS_WAKER.register(cx.waker()); if !self.inited { @@ -425,14 +420,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { let n = ep_addr.index(); match ep_addr.direction() { - Direction::In => unsafe { + Direction::In => { T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { w.set_pid(0, true); // first packet is DATA0, but PID is flipped before }); EP_IN_WAKERS[n].wake(); - }, - Direction::Out => unsafe { + } + Direction::Out => { T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { @@ -446,7 +441,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { w.set_available(0, true); }); EP_OUT_WAKERS[n].wake(); - }, + } } } @@ -504,7 +499,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> { let index = self.info.addr.index(); poll_fn(|cx| { EP_IN_WAKERS[index].register(cx.waker()); - let val = unsafe { T::dpram().ep_in_control(self.info.addr.index() - 1).read() }; + let val = T::dpram().ep_in_control(self.info.addr.index() - 1).read(); if val.enable() { Poll::Ready(()) } else { @@ -526,7 +521,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, Out> { let index = self.info.addr.index(); poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); - let val = unsafe { T::dpram().ep_out_control(self.info.addr.index() - 1).read() }; + let val = T::dpram().ep_out_control(self.info.addr.index() - 1).read(); if val.enable() { Poll::Ready(()) } else { @@ -542,7 +537,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { async fn read(&mut self, buf: &mut [u8]) -> Result { trace!("READ WAITING, buf.len() = {}", buf.len()); let index = self.info.addr.index(); - let val = poll_fn(|cx| unsafe { + let val = poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); let val = T::dpram().ep_out_buffer_control(index).read(); if val.available(0) { @@ -561,19 +556,17 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { trace!("READ OK, rx_len = {}", rx_len); - unsafe { - let pid = !val.pid(0); - T::dpram().ep_out_buffer_control(index).write(|w| { - w.set_pid(0, pid); - w.set_length(0, self.info.max_packet_size); - }); - cortex_m::asm::delay(12); - T::dpram().ep_out_buffer_control(index).write(|w| { - w.set_pid(0, pid); - w.set_length(0, self.info.max_packet_size); - w.set_available(0, true); - }); - } + let pid = !val.pid(0); + T::dpram().ep_out_buffer_control(index).write(|w| { + w.set_pid(0, pid); + w.set_length(0, self.info.max_packet_size); + }); + cortex_m::asm::delay(12); + T::dpram().ep_out_buffer_control(index).write(|w| { + w.set_pid(0, pid); + w.set_length(0, self.info.max_packet_size); + w.set_available(0, true); + }); Ok(rx_len) } @@ -588,7 +581,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { trace!("WRITE WAITING"); let index = self.info.addr.index(); - let val = poll_fn(|cx| unsafe { + let val = poll_fn(|cx| { EP_IN_WAKERS[index].register(cx.waker()); let val = T::dpram().ep_in_buffer_control(index).read(); if val.available(0) { @@ -601,21 +594,19 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { self.buf.write(buf); - unsafe { - let pid = !val.pid(0); - T::dpram().ep_in_buffer_control(index).write(|w| { - w.set_pid(0, pid); - w.set_length(0, buf.len() as _); - w.set_full(0, true); - }); - cortex_m::asm::delay(12); - T::dpram().ep_in_buffer_control(index).write(|w| { - w.set_pid(0, pid); - w.set_length(0, buf.len() as _); - w.set_full(0, true); - w.set_available(0, true); - }); - } + let pid = !val.pid(0); + T::dpram().ep_in_buffer_control(index).write(|w| { + w.set_pid(0, pid); + w.set_length(0, buf.len() as _); + w.set_full(0, true); + }); + cortex_m::asm::delay(12); + T::dpram().ep_in_buffer_control(index).write(|w| { + w.set_pid(0, pid); + w.set_length(0, buf.len() as _); + w.set_full(0, true); + w.set_available(0, true); + }); trace!("WRITE OK"); @@ -637,9 +628,9 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { loop { trace!("SETUP read waiting"); let regs = T::regs(); - unsafe { regs.inte().write_set(|w| w.set_setup_req(true)) }; + regs.inte().write_set(|w| w.set_setup_req(true)); - poll_fn(|cx| unsafe { + poll_fn(|cx| { EP_OUT_WAKERS[0].register(cx.waker()); let regs = T::regs(); if regs.sie_status().read().setup_rec() { @@ -654,13 +645,11 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { EndpointBuffer::::new(0, 8).read(&mut buf); let regs = T::regs(); - unsafe { - regs.sie_status().write(|w| w.set_setup_rec(true)); + regs.sie_status().write(|w| w.set_setup_rec(true)); - // set PID to 0, so (after toggling) first DATA is PID 1 - T::dpram().ep_in_buffer_control(0).write(|w| w.set_pid(0, false)); - T::dpram().ep_out_buffer_control(0).write(|w| w.set_pid(0, false)); - } + // set PID to 0, so (after toggling) first DATA is PID 1 + T::dpram().ep_in_buffer_control(0).write(|w| w.set_pid(0, false)); + T::dpram().ep_out_buffer_control(0).write(|w| w.set_pid(0, false)); trace!("SETUP read ok"); return buf; @@ -668,23 +657,21 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } async fn data_out(&mut self, buf: &mut [u8], first: bool, last: bool) -> Result { - unsafe { - let bufcontrol = T::dpram().ep_out_buffer_control(0); - let pid = !bufcontrol.read().pid(0); - bufcontrol.write(|w| { - w.set_length(0, self.max_packet_size); - w.set_pid(0, pid); - }); - cortex_m::asm::delay(12); - bufcontrol.write(|w| { - w.set_length(0, self.max_packet_size); - w.set_pid(0, pid); - w.set_available(0, true); - }); - } + let bufcontrol = T::dpram().ep_out_buffer_control(0); + let pid = !bufcontrol.read().pid(0); + bufcontrol.write(|w| { + w.set_length(0, self.max_packet_size); + w.set_pid(0, pid); + }); + cortex_m::asm::delay(12); + bufcontrol.write(|w| { + w.set_length(0, self.max_packet_size); + w.set_pid(0, pid); + w.set_available(0, true); + }); trace!("control: data_out len={} first={} last={}", buf.len(), first, last); - let val = poll_fn(|cx| unsafe { + let val = poll_fn(|cx| { EP_OUT_WAKERS[0].register(cx.waker()); let val = T::dpram().ep_out_buffer_control(0).read(); if val.available(0) { @@ -714,24 +701,22 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } EndpointBuffer::::new(0x100, 64).write(data); - unsafe { - let bufcontrol = T::dpram().ep_in_buffer_control(0); - let pid = !bufcontrol.read().pid(0); - bufcontrol.write(|w| { - w.set_length(0, data.len() as _); - w.set_pid(0, pid); - w.set_full(0, true); - }); - cortex_m::asm::delay(12); - bufcontrol.write(|w| { - w.set_length(0, data.len() as _); - w.set_pid(0, pid); - w.set_full(0, true); - w.set_available(0, true); - }); - } + let bufcontrol = T::dpram().ep_in_buffer_control(0); + let pid = !bufcontrol.read().pid(0); + bufcontrol.write(|w| { + w.set_length(0, data.len() as _); + w.set_pid(0, pid); + w.set_full(0, true); + }); + cortex_m::asm::delay(12); + bufcontrol.write(|w| { + w.set_length(0, data.len() as _); + w.set_pid(0, pid); + w.set_full(0, true); + w.set_available(0, true); + }); - poll_fn(|cx| unsafe { + poll_fn(|cx| { EP_IN_WAKERS[0].register(cx.waker()); let bufcontrol = T::dpram().ep_in_buffer_control(0); if bufcontrol.read().available(0) { @@ -745,19 +730,17 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { if last { // prepare status phase right away. - unsafe { - let bufcontrol = T::dpram().ep_out_buffer_control(0); - bufcontrol.write(|w| { - w.set_length(0, 0); - w.set_pid(0, true); - }); - cortex_m::asm::delay(12); - bufcontrol.write(|w| { - w.set_length(0, 0); - w.set_pid(0, true); - w.set_available(0, true); - }); - } + let bufcontrol = T::dpram().ep_out_buffer_control(0); + bufcontrol.write(|w| { + w.set_length(0, 0); + w.set_pid(0, true); + }); + cortex_m::asm::delay(12); + bufcontrol.write(|w| { + w.set_length(0, 0); + w.set_pid(0, true); + w.set_available(0, true); + }); } Ok(()) @@ -767,26 +750,24 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { trace!("control: accept"); let bufcontrol = T::dpram().ep_in_buffer_control(0); - unsafe { - bufcontrol.write(|w| { - w.set_length(0, 0); - w.set_pid(0, true); - w.set_full(0, true); - }); - cortex_m::asm::delay(12); - bufcontrol.write(|w| { - w.set_length(0, 0); - w.set_pid(0, true); - w.set_full(0, true); - w.set_available(0, true); - }); - } + bufcontrol.write(|w| { + w.set_length(0, 0); + w.set_pid(0, true); + w.set_full(0, true); + }); + cortex_m::asm::delay(12); + bufcontrol.write(|w| { + w.set_length(0, 0); + w.set_pid(0, true); + w.set_full(0, true); + w.set_available(0, true); + }); // wait for completion before returning, needed so // set_address() doesn't happen early. poll_fn(|cx| { EP_IN_WAKERS[0].register(cx.waker()); - if unsafe { bufcontrol.read().available(0) } { + if bufcontrol.read().available(0) { Poll::Pending } else { Poll::Ready(()) @@ -799,14 +780,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { trace!("control: reject"); let regs = T::regs(); - unsafe { - regs.ep_stall_arm().write_set(|w| { - w.set_ep0_in(true); - w.set_ep0_out(true); - }); - T::dpram().ep_out_buffer_control(0).write(|w| w.set_stall(true)); - T::dpram().ep_in_buffer_control(0).write(|w| w.set_stall(true)); - } + regs.ep_stall_arm().write_set(|w| { + w.set_ep0_in(true); + w.set_ep0_out(true); + }); + T::dpram().ep_out_buffer_control(0).write(|w| w.set_stall(true)); + T::dpram().ep_in_buffer_control(0).write(|w| w.set_stall(true)); } async fn accept_set_address(&mut self, addr: u8) { @@ -814,6 +793,6 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { let regs = T::regs(); trace!("setting addr: {}", addr); - unsafe { regs.addr_endp().write(|w| w.set_address(addr)) } + regs.addr_endp().write(|w| w.set_address(addr)) } } diff --git a/embassy-rp/src/watchdog.rs b/embassy-rp/src/watchdog.rs index 78a295ae7..d37795cc9 100644 --- a/embassy-rp/src/watchdog.rs +++ b/embassy-rp/src/watchdog.rs @@ -35,45 +35,37 @@ impl Watchdog { /// * `cycles` - Total number of tick cycles before the next tick is generated. /// It is expected to be the frequency in MHz of clk_ref. pub fn enable_tick_generation(&mut self, cycles: u8) { - unsafe { - let watchdog = pac::WATCHDOG; - watchdog.tick().write(|w| { - w.set_enable(true); - w.set_cycles(cycles.into()) - }); - } + let watchdog = pac::WATCHDOG; + watchdog.tick().write(|w| { + w.set_enable(true); + w.set_cycles(cycles.into()) + }); } /// Defines whether or not the watchdog timer should be paused when processor(s) are in debug mode /// or when JTAG is accessing bus fabric pub fn pause_on_debug(&mut self, pause: bool) { - unsafe { - let watchdog = pac::WATCHDOG; - watchdog.ctrl().write(|w| { - w.set_pause_dbg0(pause); - w.set_pause_dbg1(pause); - w.set_pause_jtag(pause); - }) - } + let watchdog = pac::WATCHDOG; + watchdog.ctrl().write(|w| { + w.set_pause_dbg0(pause); + w.set_pause_dbg1(pause); + w.set_pause_jtag(pause); + }) } fn load_counter(&self, counter: u32) { - unsafe { - let watchdog = pac::WATCHDOG; - watchdog.load().write_value(pac::watchdog::regs::Load(counter)); - } + let watchdog = pac::WATCHDOG; + watchdog.load().write_value(pac::watchdog::regs::Load(counter)); } fn enable(&self, bit: bool) { - unsafe { - let watchdog = pac::WATCHDOG; - watchdog.ctrl().write(|w| w.set_enable(bit)) - } + let watchdog = pac::WATCHDOG; + watchdog.ctrl().write(|w| w.set_enable(bit)) } // Configure which hardware will be reset by the watchdog // (everything except ROSC, XOSC) - unsafe fn configure_wdog_reset_triggers(&self) { + fn configure_wdog_reset_triggers(&self) { let psm = pac::PSM; psm.wdsel().write_value(pac::psm::regs::Wdsel( 0x0001ffff & !(0x01 << 0usize) & !(0x01 << 1usize), @@ -100,23 +92,19 @@ impl Watchdog { self.load_value = delay_us * 2; self.enable(false); - unsafe { - self.configure_wdog_reset_triggers(); - } + self.configure_wdog_reset_triggers(); self.load_counter(self.load_value); self.enable(true); } /// Trigger a system reset pub fn trigger_reset(&mut self) { - unsafe { - self.configure_wdog_reset_triggers(); - self.pause_on_debug(false); - self.enable(true); - let watchdog = pac::WATCHDOG; - watchdog.ctrl().write(|w| { - w.set_trigger(true); - }) - } + self.configure_wdog_reset_triggers(); + self.pause_on_debug(false); + self.enable(true); + let watchdog = pac::WATCHDOG; + watchdog.ctrl().write(|w| { + w.set_trigger(true); + }) } } diff --git a/tests/rp/src/bin/float.rs b/tests/rp/src/bin/float.rs index 6a982507a..0e0de85fa 100644 --- a/tests/rp/src/bin/float.rs +++ b/tests/rp/src/bin/float.rs @@ -18,11 +18,9 @@ async fn main(_spawner: Spawner) { const PI_F: f32 = 3.1415926535f32; const PI_D: f64 = 3.14159265358979323846f64; - unsafe { - pac::BUSCTRL - .perfsel(0) - .write(|r| r.set_perfsel(pac::busctrl::vals::Perfsel::ROM)); - } + pac::BUSCTRL + .perfsel(0) + .write(|r| r.set_perfsel(pac::busctrl::vals::Perfsel::ROM)); for i in 0..=360 { let rad_f = (i as f32) * PI_F / 180.0; @@ -46,7 +44,7 @@ async fn main(_spawner: Spawner) { Timer::after(Duration::from_millis(10)).await; } - let rom_accesses = unsafe { pac::BUSCTRL.perfctr(0).read().perfctr() }; + let rom_accesses = pac::BUSCTRL.perfctr(0).read().perfctr(); // every float operation used here uses at least 10 cycles defmt::assert!(rom_accesses >= 360 * 12 * 10); From af451b5462b4cbfaab6ac3ffe56ec9e981f460f7 Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 15 Jun 2023 21:02:10 -0500 Subject: [PATCH 81/98] stm32/wpan: move schi command into sys --- embassy-stm32-wpan/src/ble.rs | 4 ++-- embassy-stm32-wpan/src/cmd.rs | 8 +++++++ embassy-stm32-wpan/src/rc.rs | 7 +----- embassy-stm32-wpan/src/shci.rs | 39 ++++++++++------------------------ embassy-stm32-wpan/src/sys.rs | 33 ++++++++++++++++++++++++++-- tests/stm32/src/bin/tl_mbox.rs | 3 +++ 6 files changed, 56 insertions(+), 38 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index 57348a925..46a2f41c4 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -48,11 +48,11 @@ impl Ble { // TODO: ACL data ack to the user } - pub fn ble_send_cmd(buf: &[u8]) { + pub fn send_cmd(buf: &[u8]) { debug!("writing ble cmd"); unsafe { - let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; + let pcmd_buffer: *mut CmdPacket = BLE_CMD_BUFFER.as_mut_ptr(); let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs index 1f7dae7f7..a023201ba 100644 --- a/embassy-stm32-wpan/src/cmd.rs +++ b/embassy-stm32-wpan/src/cmd.rs @@ -26,6 +26,14 @@ pub struct CmdSerial { pub cmd: Cmd, } +#[derive(Copy, Clone, Default)] +#[repr(C, packed)] +pub struct CmdSerialStub { + pub ty: u8, + pub cmd_code: u16, + pub payload_len: u8, +} + #[derive(Copy, Clone, Default)] #[repr(C, packed)] pub struct CmdPacket { diff --git a/embassy-stm32-wpan/src/rc.rs b/embassy-stm32-wpan/src/rc.rs index aae2265ed..a217aa224 100644 --- a/embassy-stm32-wpan/src/rc.rs +++ b/embassy-stm32-wpan/src/rc.rs @@ -20,7 +20,7 @@ impl<'d> RadioCoprocessor<'d> { let cmd = TlPacketType::try_from(cmd_code).unwrap(); match &cmd { - TlPacketType::BleCmd => Ble::ble_send_cmd(buf), + TlPacketType::BleCmd => Ble::send_cmd(buf), _ => todo!(), } } @@ -33,11 +33,6 @@ impl<'d> RadioCoprocessor<'d> { let event = evt.evt(); evt.write(&mut self.rx_buf).unwrap(); - - if event.kind() == 18 { - shci::shci_ble_init(Default::default()); - self.rx_buf[0] = 0x04; - } } if self.mbox.pop_last_cc_evt().is_some() { diff --git a/embassy-stm32-wpan/src/shci.rs b/embassy-stm32-wpan/src/shci.rs index 8537995ff..6e58a7156 100644 --- a/embassy-stm32-wpan/src/shci.rs +++ b/embassy-stm32-wpan/src/shci.rs @@ -1,8 +1,10 @@ +use core::{mem, slice}; + use super::cmd::CmdPacket; use super::consts::TlPacketType; use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; -const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; +pub const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; #[derive(Debug, Clone, Copy)] #[repr(C, packed)] @@ -32,6 +34,12 @@ pub struct ShciBleInitCmdParam { pub hw_version: u8, } +impl ShciBleInitCmdParam { + pub fn payload<'a>(&self) -> &'a [u8] { + unsafe { slice::from_raw_parts(self as *const _ as *const u8, mem::size_of::()) } + } +} + impl Default for ShciBleInitCmdParam { fn default() -> Self { Self { @@ -66,35 +74,10 @@ pub struct ShciHeader { #[derive(Debug, Clone, Copy)] #[repr(C, packed)] pub struct ShciBleInitCmdPacket { - header: ShciHeader, - param: ShciBleInitCmdParam, + pub header: ShciHeader, + pub param: ShciBleInitCmdParam, } pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; #[allow(dead_code)] // Not used currently but reserved const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; - -pub fn shci_ble_init(param: ShciBleInitCmdParam) { - debug!("sending SHCI"); - - let mut packet = ShciBleInitCmdPacket { - header: ShciHeader::default(), - param, - }; - - let packet_ptr: *mut _ = &mut packet; - - unsafe { - let cmd_ptr: *mut CmdPacket = packet_ptr.cast(); - - (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; - (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::() as u8; - - let p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; - core::ptr::write(p_cmd_buffer, *cmd_ptr); - - p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; - - sys::Sys::send_cmd(); - } -} diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index 0cff5c746..76f65cbd8 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -1,7 +1,12 @@ +use core::ptr; +use core::sync::atomic::{compiler_fence, Ordering}; + use embassy_stm32::ipcc::Ipcc; -use crate::cmd::{CmdPacket, CmdSerial}; +use crate::cmd::{CmdPacket, CmdSerial, CmdSerialStub}; +use crate::consts::TlPacketType; use crate::evt::{CcEvt, EvtBox, EvtSerial}; +use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; use crate::tables::SysTable; use crate::unsafe_linked_list::LinkedListNode; use crate::{channels, EVT_CHANNEL, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; @@ -58,7 +63,31 @@ impl Sys { Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); } - pub fn send_cmd() { + pub fn shci_ble_init(param: ShciBleInitCmdParam) { + debug!("sending SHCI"); + + Self::send_cmd(SCHI_OPCODE_BLE_INIT, param.payload()); + } + + pub fn send_cmd(opcode: u16, payload: &[u8]) { + unsafe { + let p_cmd_serial = &mut (*SYS_CMD_BUF.as_mut_ptr()).cmdserial as *mut _ as *mut CmdSerialStub; + let p_payload = &mut (*SYS_CMD_BUF.as_mut_ptr()).cmdserial.cmd.payload as *mut _; + + ptr::write_volatile( + p_cmd_serial, + CmdSerialStub { + ty: TlPacketType::SysCmd as u8, + cmd_code: opcode, + payload_len: payload.len() as u8, + }, + ); + + ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len()); + } + + compiler_fence(Ordering::SeqCst); + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); } diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index 4669cbc62..5e7d11ef5 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -11,6 +11,7 @@ use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::Config; use embassy_stm32_wpan::rc::RadioCoprocessor; +use embassy_stm32_wpan::sys::Sys; use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; @@ -56,6 +57,8 @@ async fn main(_spawner: Spawner) { let response = rc.read().await; info!("coprocessor ready {}", response); + Sys::shci_ble_init(Default::default()); + rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); let response = rc.read().await; info!("ble reset rsp {}", response); From 54fc933932e9f8e510331401820b57ba32d8ade3 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Fri, 16 Jun 2023 12:59:23 +0200 Subject: [PATCH 82/98] embassy-executor: introduce `InterruptExecutor::spawner()` --- embassy-executor/src/arch/cortex_m.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs index d6a55c4c7..94c8134d6 100644 --- a/embassy-executor/src/arch/cortex_m.rs +++ b/embassy-executor/src/arch/cortex_m.rs @@ -205,5 +205,20 @@ mod interrupt { executor.spawner().make_send() } + + /// Get a SendSpawner for this executor + /// + /// This returns a [`SendSpawner`] you can use to spawn tasks on this + /// executor. + /// + /// This MUST only be called on an executor that has already been spawned. + /// The function will panic otherwise. + pub fn spawner(&'static self) -> crate::SendSpawner { + if !self.started.load(Ordering::Acquire) { + panic!("InterruptExecutor::spawner() called on uninitialized executor."); + } + let executor = unsafe { (&*self.executor.get()).assume_init_ref() }; + executor.spawner().make_send() + } } } From e1161dfc80e583719bf486d112fa84c948b71fc1 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 16 Jun 2023 20:15:03 -0500 Subject: [PATCH 83/98] stm32/wpan: improve linked list ergonomics --- embassy-stm32-wpan/src/ble.rs | 27 ++++++++---------- embassy-stm32-wpan/src/cmd.rs | 19 +++++++++++++ embassy-stm32-wpan/src/mm.rs | 11 ++----- embassy-stm32-wpan/src/rc.rs | 8 ++---- embassy-stm32-wpan/src/shci.rs | 4 +-- embassy-stm32-wpan/src/sys.rs | 30 +++++++------------- embassy-stm32-wpan/src/unsafe_linked_list.rs | 28 +++++++++++------- tests/stm32/src/bin/tl_mbox.rs | 5 +++- 8 files changed, 70 insertions(+), 62 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index 46a2f41c4..d8af861ae 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -1,6 +1,8 @@ +use core::mem::MaybeUninit; + use embassy_stm32::ipcc::Ipcc; -use crate::cmd::{CmdPacket, CmdSerial}; +use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::EvtBox; use crate::tables::BleTable; @@ -14,6 +16,11 @@ pub struct Ble; impl Ble { pub(super) fn enable() { unsafe { + // Ensure reproducible behavior + BLE_CMD_BUFFER + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { @@ -29,11 +36,8 @@ impl Ble { pub(super) fn evt_handler() { unsafe { - while !LinkedListNode::is_empty(EVT_QUEUE.as_mut_ptr()) { - let node_ptr = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()); - - let event = node_ptr.cast(); - let event = EvtBox::new(event); + while let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { + let event = EvtBox::new(node_ptr.cast()); EVT_CHANNEL.try_send(event).unwrap(); } @@ -48,18 +52,11 @@ impl Ble { // TODO: ACL data ack to the user } - pub fn send_cmd(buf: &[u8]) { + pub fn send_cmd(opcode: u16, payload: &[u8]) { debug!("writing ble cmd"); unsafe { - let pcmd_buffer: *mut CmdPacket = BLE_CMD_BUFFER.as_mut_ptr(); - let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; - let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); - - core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); - - let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; - cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; + CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); } Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs index a023201ba..581e5019b 100644 --- a/embassy-stm32-wpan/src/cmd.rs +++ b/embassy-stm32-wpan/src/cmd.rs @@ -1,3 +1,6 @@ +use core::ptr; + +use crate::consts::TlPacketType; use crate::evt::{EvtPacket, EvtSerial}; use crate::{PacketHeader, TL_EVT_HEADER_SIZE}; @@ -42,6 +45,22 @@ pub struct CmdPacket { } impl CmdPacket { + pub unsafe fn write_into(cmd_buf: *mut CmdPacket, packet_type: TlPacketType, cmd_code: u16, payload: &[u8]) { + let p_cmd_serial = &mut (*cmd_buf).cmdserial as *mut _ as *mut CmdSerialStub; + let p_payload = &mut (*cmd_buf).cmdserial.cmd.payload as *mut _; + + ptr::write_volatile( + p_cmd_serial, + CmdSerialStub { + ty: packet_type as u8, + cmd_code: cmd_code, + payload_len: payload.len() as u8, + }, + ); + + ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len()); + } + /// Writes an underlying CmdPacket into the provided buffer. /// Returns a number of bytes that were written. /// Returns an error if event kind is unknown or if provided buffer size is not enough. diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs index 06063b89a..1ea6edeff 100644 --- a/embassy-stm32-wpan/src/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -7,7 +7,7 @@ use crate::tables::MemManagerTable; use crate::unsafe_linked_list::LinkedListNode; use crate::{ channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF, - TL_MEM_MANAGER_TABLE, TL_REF_TABLE, + TL_MEM_MANAGER_TABLE, }; pub(super) struct MemoryManager; @@ -51,13 +51,8 @@ impl MemoryManager { /// gives free event buffers back to CPU2 from local buffer queue pub fn send_free_buf() { unsafe { - while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { - let node_ptr = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); - - LinkedListNode::insert_tail( - (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue, - node_ptr, - ); + while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { + LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); } } } diff --git a/embassy-stm32-wpan/src/rc.rs b/embassy-stm32-wpan/src/rc.rs index a217aa224..e67350f79 100644 --- a/embassy-stm32-wpan/src/rc.rs +++ b/embassy-stm32-wpan/src/rc.rs @@ -1,6 +1,6 @@ use crate::ble::Ble; use crate::consts::TlPacketType; -use crate::{shci, TlMbox, STATE}; +use crate::{TlMbox, STATE}; pub struct RadioCoprocessor<'d> { mbox: TlMbox<'d>, @@ -15,12 +15,12 @@ impl<'d> RadioCoprocessor<'d> { } } - pub fn write(&self, buf: &[u8]) { + pub fn write(&self, opcode: u16, buf: &[u8]) { let cmd_code = buf[0]; let cmd = TlPacketType::try_from(cmd_code).unwrap(); match &cmd { - TlPacketType::BleCmd => Ble::send_cmd(buf), + TlPacketType::BleCmd => Ble::send_cmd(opcode, buf), _ => todo!(), } } @@ -30,8 +30,6 @@ impl<'d> RadioCoprocessor<'d> { STATE.wait().await; while let Some(evt) = self.mbox.dequeue_event() { - let event = evt.evt(); - evt.write(&mut self.rx_buf).unwrap(); } diff --git a/embassy-stm32-wpan/src/shci.rs b/embassy-stm32-wpan/src/shci.rs index 6e58a7156..cdf027d5e 100644 --- a/embassy-stm32-wpan/src/shci.rs +++ b/embassy-stm32-wpan/src/shci.rs @@ -1,8 +1,6 @@ use core::{mem, slice}; -use super::cmd::CmdPacket; -use super::consts::TlPacketType; -use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; +use super::{TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE}; pub const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index 76f65cbd8..fb247f276 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -1,9 +1,9 @@ -use core::ptr; +use core::mem::MaybeUninit; use core::sync::atomic::{compiler_fence, Ordering}; use embassy_stm32::ipcc::Ipcc; -use crate::cmd::{CmdPacket, CmdSerial, CmdSerialStub}; +use crate::cmd::{CmdPacket, CmdSerial}; use crate::consts::TlPacketType; use crate::evt::{CcEvt, EvtBox, EvtSerial}; use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; @@ -16,6 +16,11 @@ pub struct Sys; impl Sys { pub fn enable() { unsafe { + // Ensure reproducible behavior + SYS_CMD_BUF + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { @@ -50,11 +55,8 @@ impl Sys { pub fn evt_handler() { unsafe { - while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - let node_ptr = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); - - let event = node_ptr.cast(); - let event = EvtBox::new(event); + while let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { + let event = EvtBox::new(node_ptr.cast()); EVT_CHANNEL.try_send(event).unwrap(); } @@ -71,19 +73,7 @@ impl Sys { pub fn send_cmd(opcode: u16, payload: &[u8]) { unsafe { - let p_cmd_serial = &mut (*SYS_CMD_BUF.as_mut_ptr()).cmdserial as *mut _ as *mut CmdSerialStub; - let p_payload = &mut (*SYS_CMD_BUF.as_mut_ptr()).cmdserial.cmd.payload as *mut _; - - ptr::write_volatile( - p_cmd_serial, - CmdSerialStub { - ty: TlPacketType::SysCmd as u8, - cmd_code: opcode, - payload_len: payload.len() as u8, - }, - ); - - ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len()); + CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload); } compiler_fence(Ordering::SeqCst); diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs index a312178b3..5b210aac4 100644 --- a/embassy-stm32-wpan/src/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -139,28 +139,36 @@ impl LinkedListNode { } /// Remove `list_head` and return a pointer to the `node`. - pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode) -> *mut LinkedListNode { + pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode) -> Option<*mut LinkedListNode> { interrupt::free(|_| { let list_head = ptr::read_volatile(p_list_head); - // Allowed because a removed node is not seen by another core - let p_node = list_head.next; - Self::remove_node(p_node); + if list_head.next == p_list_head { + None + } else { + // Allowed because a removed node is not seen by another core + let p_node = list_head.next; + Self::remove_node(p_node); - p_node + Some(p_node) + } }) } /// Remove `list_tail` and return a pointer to the `node`. - pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode) -> *mut LinkedListNode { + pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode) -> Option<*mut LinkedListNode> { interrupt::free(|_| { let list_tail = ptr::read_volatile(p_list_tail); - // Allowed because a removed node is not seen by another core - let p_node = list_tail.prev; - Self::remove_node(p_node); + if list_tail.prev == p_list_tail { + None + } else { + // Allowed because a removed node is not seen by another core + let p_node = list_tail.prev; + Self::remove_node(p_node); - p_node + Some(p_node) + } }) } diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index 5e7d11ef5..5a2309263 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -10,6 +10,7 @@ use common::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::Config; +use embassy_stm32_wpan::ble::Ble; use embassy_stm32_wpan::rc::RadioCoprocessor; use embassy_stm32_wpan::sys::Sys; use embassy_stm32_wpan::TlMbox; @@ -59,7 +60,9 @@ async fn main(_spawner: Spawner) { Sys::shci_ble_init(Default::default()); - rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); + // rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); + Ble::send_cmd(0x0c, &[]); + let response = rc.read().await; info!("ble reset rsp {}", response); From 9e8de5f596ffa9036c2343ccc1e69f471a4770eb Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 08:11:55 -0500 Subject: [PATCH 84/98] fut: add poll_once --- embassy-futures/src/block_on.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/embassy-futures/src/block_on.rs b/embassy-futures/src/block_on.rs index da90351ec..77695216c 100644 --- a/embassy-futures/src/block_on.rs +++ b/embassy-futures/src/block_on.rs @@ -31,3 +31,15 @@ pub fn block_on(mut fut: F) -> F::Output { } } } + +/// Poll a future once. +pub fn poll_once(mut fut: F) -> Poll { + // safety: we don't move the future after this line. + let mut fut = unsafe { Pin::new_unchecked(&mut fut) }; + + let raw_waker = RawWaker::new(ptr::null(), &VTABLE); + let waker = unsafe { Waker::from_raw(raw_waker) }; + let mut cx = Context::from_waker(&waker); + + fut.as_mut().poll(&mut cx) +} From 391f0b5d09dba018dd984a706dc8071f87e06dec Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 08:37:00 -0500 Subject: [PATCH 85/98] revert reset changes --- embassy-stm32-wpan/src/ble.rs | 5 ----- embassy-stm32-wpan/src/sys.rs | 5 ----- 2 files changed, 10 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index d8af861ae..3a6cc6f07 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -16,11 +16,6 @@ pub struct Ble; impl Ble { pub(super) fn enable() { unsafe { - // Ensure reproducible behavior - BLE_CMD_BUFFER - .as_mut_ptr() - .write_volatile(MaybeUninit::zeroed().assume_init()); - LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index fb247f276..36b4a144d 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -16,11 +16,6 @@ pub struct Sys; impl Sys { pub fn enable() { unsafe { - // Ensure reproducible behavior - SYS_CMD_BUF - .as_mut_ptr() - .write_volatile(MaybeUninit::zeroed().assume_init()); - LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { From 6ef060ca1719216751811336ebc4d41247daaeff Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 10:44:36 -0500 Subject: [PATCH 86/98] disable mm --- embassy-stm32-wpan/src/mm.rs | 46 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs index 1ea6edeff..4ccae06f4 100644 --- a/embassy-stm32-wpan/src/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -31,36 +31,36 @@ impl MemoryManager { } pub fn evt_drop(evt: *mut EvtPacket) { - unsafe { - let list_node = evt.cast(); - - LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); - - let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - - // postpone event buffer freeing to IPCC interrupt handler - if channel_is_busy { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); - } else { - Self::send_free_buf(); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - } - } + // unsafe { + // let list_node = evt.cast(); + // + // LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); + // + // let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + // + // // postpone event buffer freeing to IPCC interrupt handler + // if channel_is_busy { + // Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); + // } else { + // Self::send_free_buf(); + // Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + // } + // } } /// gives free event buffers back to CPU2 from local buffer queue pub fn send_free_buf() { - unsafe { - while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { - LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); - } - } + // unsafe { + // while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { + // LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); + // } + // } } /// free buffer channel interrupt handler pub fn free_buf_handler() { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); - Self::send_free_buf(); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + // Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); + // Self::send_free_buf(); + // Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); } } From 4c9b7befaa498e491f34140e1497dcb98da62713 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 10:50:06 -0500 Subject: [PATCH 87/98] stm32/ipcc: add clear debug --- embassy-stm32/src/ipcc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 8bb0774b8..28f51baa5 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -111,6 +111,7 @@ impl Ipcc { pub fn c1_clear_flag_channel(channel: IpccChannel) { let regs = IPCC::regs(); + trace!("ipcc: ch {}: clear rx", channel as u8); unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } } From b0a2f0c4fec5358063e6323bf9f9ee001341c473 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 11:02:31 -0500 Subject: [PATCH 88/98] stm32/wpan: debug remove node --- embassy-stm32-wpan/src/unsafe_linked_list.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs index 5b210aac4..a2d2840f0 100644 --- a/embassy-stm32-wpan/src/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -117,7 +117,10 @@ impl LinkedListNode { /// Remove `node` from the linked list pub unsafe fn remove_node(mut p_node: *mut LinkedListNode) { interrupt::free(|_| { + trace!("remove node: {:x}", p_node); let node = ptr::read_volatile(p_node); + trace!("remove node: prev/next {:x}/{:x}", node.prev, node.next); + if node.next != node.prev { let mut node_next = ptr::read_volatile(node.next); let mut node_prev = ptr::read_volatile(node.prev); From 6b5d55eb29aa55795cfdf98593feba2f53b85b9c Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 12:00:33 -0500 Subject: [PATCH 89/98] stm32/wpan: convert to new ipcc --- embassy-stm32-wpan/src/ble.rs | 54 ++-- embassy-stm32-wpan/src/evt.rs | 4 +- embassy-stm32-wpan/src/lib.rs | 60 +--- embassy-stm32-wpan/src/mm.rs | 66 +++-- embassy-stm32-wpan/src/rc.rs | 43 --- embassy-stm32-wpan/src/sys.rs | 91 +++--- embassy-stm32-wpan/src/unsafe_linked_list.rs | 8 +- embassy-stm32/src/ipcc.rs | 296 +++++++++++++------ tests/stm32/src/bin/tl_mbox.rs | 43 ++- 9 files changed, 330 insertions(+), 335 deletions(-) delete mode 100644 embassy-stm32-wpan/src/rc.rs diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index 3a6cc6f07..b7d152631 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -1,10 +1,11 @@ use core::mem::MaybeUninit; +use core::ptr; use embassy_stm32::ipcc::Ipcc; -use crate::cmd::CmdPacket; +use crate::cmd::{Cmd, CmdPacket, CmdSerial}; use crate::consts::TlPacketType; -use crate::evt::EvtBox; +use crate::evt::{EvtBox, EvtPacket}; use crate::tables::BleTable; use crate::unsafe_linked_list::LinkedListNode; use crate::{ @@ -25,45 +26,26 @@ impl Ble { phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), }); } - - Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); } - - pub(super) fn evt_handler() { - unsafe { - while let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { - let event = EvtBox::new(node_ptr.cast()); - - EVT_CHANNEL.try_send(event).unwrap(); + /// `HW_IPCC_BLE_EvtNot` + pub async fn read() -> EvtBox { + Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { + if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { + Some(EvtBox::new(node_ptr.cast())) + } else { + None } - } - - Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); + }) + .await } - pub(super) fn acl_data_handler() { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); - - // TODO: ACL data ack to the user - } - - pub fn send_cmd(opcode: u16, payload: &[u8]) { - debug!("writing ble cmd"); - - unsafe { + /// `TL_BLE_SendCmd` + pub async fn write(opcode: u16, payload: &[u8]) { + Ipcc::send(channels::cpu1::IPCC_BLE_CMD_CHANNEL, || unsafe { CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); - } - - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); + }) + .await; } - #[allow(dead_code)] // Not used currently but reserved - pub(super) fn ble_send_acl_data() { - let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; - - cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; - - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, true); - } + // TODO: acl commands } diff --git a/embassy-stm32-wpan/src/evt.rs b/embassy-stm32-wpan/src/evt.rs index b53fe506e..82f73a6f8 100644 --- a/embassy-stm32-wpan/src/evt.rs +++ b/embassy-stm32-wpan/src/evt.rs @@ -171,6 +171,8 @@ impl EvtBox { impl Drop for EvtBox { fn drop(&mut self) { - mm::MemoryManager::evt_drop(self.ptr); + trace!("evt box drop packet"); + + unsafe { mm::MemoryManager::drop_event_packet(self.ptr) }; } } diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 2852d6270..78516263c 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -7,11 +7,10 @@ use core::mem::MaybeUninit; use core::sync::atomic::{compiler_fence, Ordering}; use cmd::CmdPacket; -use embassy_futures::block_on; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::interrupt; use embassy_stm32::interrupt::typelevel::Interrupt; -use embassy_stm32::ipcc::{Config, Ipcc}; +use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32::peripherals::IPCC; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; @@ -29,50 +28,11 @@ pub mod cmd; pub mod consts; pub mod evt; pub mod mm; -pub mod rc; pub mod shci; pub mod sys; pub mod tables; pub mod unsafe_linked_list; -/// Interrupt handler. -pub struct ReceiveInterruptHandler {} - -impl interrupt::typelevel::Handler for ReceiveInterruptHandler { - unsafe fn on_interrupt() { - if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { - debug!("RX SYS evt"); - sys::Sys::evt_handler(); - } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { - debug!("RX BLE evt"); - ble::Ble::evt_handler(); - } - - STATE.signal(()); - } -} - -pub struct TransmitInterruptHandler {} - -impl interrupt::typelevel::Handler for TransmitInterruptHandler { - unsafe fn on_interrupt() { - if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { - debug!("TX SYS cmd rsp"); - let cc = sys::Sys::cmd_evt_handler(); - - LAST_CC_EVT.signal(cc); - } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { - debug!("TX MM release"); - mm::MemoryManager::free_buf_handler(); - } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL) { - debug!("TX HCI acl"); - ble::Ble::acl_data_handler(); - } - - STATE.signal(()); - } -} - #[link_section = "TL_REF_TABLE"] pub static mut TL_REF_TABLE: MaybeUninit = MaybeUninit::uninit(); @@ -289,22 +249,4 @@ impl<'d> TlMbox<'d> { None } } - - /// picks single [`EvtBox`] from internal event queue. - /// - /// Internal event queu is populated in IPCC_RX_IRQ handler - pub fn dequeue_event(&mut self) -> Option { - EVT_CHANNEL.try_recv().ok() - } - - /// retrieves last Command Complete event and removes it from mailbox - pub fn pop_last_cc_evt(&mut self) -> Option { - if LAST_CC_EVT.signaled() { - let cc = block_on(LAST_CC_EVT.wait()); - LAST_CC_EVT.reset(); - Some(cc) - } else { - None - } - } } diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs index 4ccae06f4..d0551d690 100644 --- a/embassy-stm32-wpan/src/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -1,6 +1,11 @@ //! Memory manager routines +use core::future::poll_fn; +use core::task::Poll; + +use cortex_m::interrupt; use embassy_stm32::ipcc::Ipcc; +use embassy_sync::waitqueue::AtomicWaker; use crate::evt::EvtPacket; use crate::tables::MemManagerTable; @@ -10,7 +15,9 @@ use crate::{ TL_MEM_MANAGER_TABLE, }; -pub(super) struct MemoryManager; +static MM_WAKER: AtomicWaker = AtomicWaker::new(); + +pub struct MemoryManager; impl MemoryManager { pub fn enable() { @@ -30,37 +37,36 @@ impl MemoryManager { } } - pub fn evt_drop(evt: *mut EvtPacket) { - // unsafe { - // let list_node = evt.cast(); - // - // LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); - // - // let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - // - // // postpone event buffer freeing to IPCC interrupt handler - // if channel_is_busy { - // Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); - // } else { - // Self::send_free_buf(); - // Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - // } - // } + /// SAFETY: passing a pointer to something other than an event packet is UB + pub unsafe fn drop_event_packet(evt: *mut EvtPacket) { + interrupt::free(|_| unsafe { + LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); + }); + + MM_WAKER.wake(); } - /// gives free event buffers back to CPU2 from local buffer queue - pub fn send_free_buf() { - // unsafe { - // while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { - // LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); - // } - // } - } + pub async fn run_queue() { + loop { + poll_fn(|cx| unsafe { + MM_WAKER.register(cx.waker()); + if LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { + Poll::Pending + } else { + Poll::Ready(()) + } + }) + .await; - /// free buffer channel interrupt handler - pub fn free_buf_handler() { - // Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); - // Self::send_free_buf(); - // Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + Ipcc::send(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, || { + interrupt::free(|_| unsafe { + // CS required while moving nodes + while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { + LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); + } + }) + }) + .await; + } } } diff --git a/embassy-stm32-wpan/src/rc.rs b/embassy-stm32-wpan/src/rc.rs deleted file mode 100644 index e67350f79..000000000 --- a/embassy-stm32-wpan/src/rc.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::ble::Ble; -use crate::consts::TlPacketType; -use crate::{TlMbox, STATE}; - -pub struct RadioCoprocessor<'d> { - mbox: TlMbox<'d>, - rx_buf: [u8; 500], -} - -impl<'d> RadioCoprocessor<'d> { - pub fn new(mbox: TlMbox<'d>) -> Self { - Self { - mbox, - rx_buf: [0u8; 500], - } - } - - pub fn write(&self, opcode: u16, buf: &[u8]) { - let cmd_code = buf[0]; - let cmd = TlPacketType::try_from(cmd_code).unwrap(); - - match &cmd { - TlPacketType::BleCmd => Ble::send_cmd(opcode, buf), - _ => todo!(), - } - } - - pub async fn read(&mut self) -> &[u8] { - loop { - STATE.wait().await; - - while let Some(evt) = self.mbox.dequeue_event() { - evt.write(&mut self.rx_buf).unwrap(); - } - - if self.mbox.pop_last_cc_evt().is_some() { - continue; - } - - return &self.rx_buf; - } - } -} diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index 36b4a144d..f10327b9d 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -1,19 +1,18 @@ use core::mem::MaybeUninit; -use core::sync::atomic::{compiler_fence, Ordering}; +use core::{mem, ptr}; -use embassy_stm32::ipcc::Ipcc; - -use crate::cmd::{CmdPacket, CmdSerial}; +use crate::cmd::{CmdPacket, CmdSerialStub}; use crate::consts::TlPacketType; -use crate::evt::{CcEvt, EvtBox, EvtSerial}; -use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; +use crate::evt::{CcEvt, EvtBox, EvtPacket, EvtSerial}; +use crate::shci::{ShciBleInitCmdPacket, ShciBleInitCmdParam, ShciHeader, SCHI_OPCODE_BLE_INIT}; use crate::tables::SysTable; use crate::unsafe_linked_list::LinkedListNode; -use crate::{channels, EVT_CHANNEL, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; +use crate::{channels, mm, Ipcc, EVT_CHANNEL, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; pub struct Sys; impl Sys { + /// TL_Sys_Init pub fn enable() { unsafe { LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); @@ -21,59 +20,47 @@ impl Sys { TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), - }) - } - - Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); - } - - pub fn cmd_evt_handler() -> CcEvt { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false); - - // ST's command response data structure is really convoluted. - // - // for command response events on SYS channel, the header is missing - // and one should: - // 1. interpret the content of CMD_BUFFER as CmdPacket - // 2. Access CmdPacket's cmdserial field and interpret its content as EvtSerial - // 3. Access EvtSerial's evt field (as Evt) and interpret its payload as CcEvt - // 4. CcEvt type is the actual SHCI response - // 5. profit - unsafe { - let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; - let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial; - let evt_serial: *const EvtSerial = cmd_serial.cast(); - let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); - *cc + }); } } - pub fn evt_handler() { - unsafe { - while let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - let event = EvtBox::new(node_ptr.cast()); + // pub async fn shci_c2_ble_init(&mut self, param: ShciBleInitCmdParam) -> SchiCommandStatus { + // let command_event = self + // .write_and_get_response(TlPacketType::SysCmd, ShciOpcode::BleInit as u16, param.payload()) + // .await; + // + // let payload = command_event.payload[0]; + // // info!("payload: {:x}", payload); + // + // payload.try_into().unwrap() + // } - EVT_CHANNEL.try_send(event).unwrap(); - } - } - - Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); - } - - pub fn shci_ble_init(param: ShciBleInitCmdParam) { - debug!("sending SHCI"); - - Self::send_cmd(SCHI_OPCODE_BLE_INIT, param.payload()); - } - - pub fn send_cmd(opcode: u16, payload: &[u8]) { + pub fn write(opcode: u16, payload: &[u8]) { unsafe { CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload); } + } - compiler_fence(Ordering::SeqCst); + pub async fn shci_c2_ble_init(param: ShciBleInitCmdParam) { + debug!("sending SHCI"); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); + Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || { + Self::write(SCHI_OPCODE_BLE_INIT, param.payload()); + }) + .await; + + Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; + } + + /// `HW_IPCC_SYS_EvtNot` + pub async fn read() -> EvtBox { + Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe { + if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { + Some(EvtBox::new(node_ptr.cast())) + } else { + None + } + }) + .await } } diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs index a2d2840f0..d8bc29763 100644 --- a/embassy-stm32-wpan/src/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -117,9 +117,11 @@ impl LinkedListNode { /// Remove `node` from the linked list pub unsafe fn remove_node(mut p_node: *mut LinkedListNode) { interrupt::free(|_| { - trace!("remove node: {:x}", p_node); - let node = ptr::read_volatile(p_node); - trace!("remove node: prev/next {:x}/{:x}", node.prev, node.next); + // trace!("remove node: {:x}", p_node); + // apparently linked list nodes are not always aligned. + // if more hardfaults occur, more of these may need to be converted to unaligned. + let node = ptr::read_unaligned(p_node); + // trace!("remove node: prev/next {:x}/{:x}", node.prev, node.next); if node.next != node.prev { let mut node_next = ptr::read_volatile(node.next); diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 28f51baa5..609c4d2c3 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -1,7 +1,77 @@ +use core::future::poll_fn; +use core::task::Poll; + +use atomic_polyfill::{compiler_fence, Ordering}; + use self::sealed::Instance; +use crate::interrupt; +use crate::interrupt::typelevel::Interrupt; use crate::peripherals::IPCC; use crate::rcc::sealed::RccPeripheral; +/// Interrupt handler. +pub struct ReceiveInterruptHandler {} + +impl interrupt::typelevel::Handler for ReceiveInterruptHandler { + unsafe fn on_interrupt() { + let regs = IPCC::regs(); + + let channels = [ + IpccChannel::Channel1, + IpccChannel::Channel2, + IpccChannel::Channel3, + IpccChannel::Channel4, + IpccChannel::Channel5, + IpccChannel::Channel6, + ]; + + // Status register gives channel occupied status. For rx, use cpu1. + let sr = unsafe { regs.cpu(1).sr().read() }; + regs.cpu(0).mr().modify(|w| { + for channel in channels { + if sr.chf(channel as usize) { + // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt + w.set_chom(channel as usize, true); + + // There shouldn't be a race because the channel is masked only if the interrupt has fired + IPCC::state().rx_waker_for(channel).wake(); + } + } + }) + } +} + +pub struct TransmitInterruptHandler {} + +impl interrupt::typelevel::Handler for TransmitInterruptHandler { + unsafe fn on_interrupt() { + let regs = IPCC::regs(); + + let channels = [ + IpccChannel::Channel1, + IpccChannel::Channel2, + IpccChannel::Channel3, + IpccChannel::Channel4, + IpccChannel::Channel5, + IpccChannel::Channel6, + ]; + + // Status register gives channel occupied status. For tx, use cpu0. + let sr = unsafe { regs.cpu(0).sr().read() }; + regs.cpu(0).mr().modify(|w| { + for channel in channels { + if !sr.chf(channel as usize) { + // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt + w.set_chfm(channel as usize, true); + + // There shouldn't be a race because the channel is masked only if the interrupt has fired + IPCC::state().tx_waker_for(channel).wake(); + } + } + }); + } +} + #[non_exhaustive] #[derive(Clone, Copy, Default)] pub struct Config { @@ -20,13 +90,6 @@ pub enum IpccChannel { Channel6 = 5, } -pub mod sealed { - pub trait Instance: crate::rcc::RccPeripheral { - fn regs() -> crate::pac::ipcc::Ipcc; - fn set_cpu2(enabled: bool); - } -} - pub struct Ipcc; impl Ipcc { @@ -45,115 +108,99 @@ impl Ipcc { w.set_txfie(true); }) } + + // enable interrupts + crate::interrupt::typelevel::IPCC_C1_RX::unpend(); + crate::interrupt::typelevel::IPCC_C1_TX::unpend(); + + unsafe { crate::interrupt::typelevel::IPCC_C1_RX::enable() }; + unsafe { crate::interrupt::typelevel::IPCC_C1_TX::enable() }; } - pub fn c1_set_rx_channel(channel: IpccChannel, enabled: bool) { + /// Send data to an IPCC channel. The closure is called to write the data when appropriate. + pub async fn send(channel: IpccChannel, f: impl FnOnce()) { let regs = IPCC::regs(); - // If bit is set to 1 then interrupt is disabled - unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, !enabled)) } - } + Self::flush(channel).await; + compiler_fence(Ordering::SeqCst); - pub fn c1_get_rx_channel(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); + f(); - // If bit is set to 1 then interrupt is disabled - unsafe { !regs.cpu(0).mr().read().chom(channel as usize) } - } - - #[allow(dead_code)] - pub fn c2_set_rx_channel(channel: IpccChannel, enabled: bool) { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { regs.cpu(1).mr().modify(|w| w.set_chom(channel as usize, !enabled)) } - } - - #[allow(dead_code)] - pub fn c2_get_rx_channel(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { !regs.cpu(1).mr().read().chom(channel as usize) } - } - - pub fn c1_set_tx_channel(channel: IpccChannel, enabled: bool) { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) } - } - - pub fn c1_get_tx_channel(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { !regs.cpu(0).mr().read().chfm(channel as usize) } - } - - #[allow(dead_code)] - pub fn c2_set_tx_channel(channel: IpccChannel, enabled: bool) { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { regs.cpu(1).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) } - } - - #[allow(dead_code)] - pub fn c2_get_tx_channel(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { !regs.cpu(1).mr().read().chfm(channel as usize) } - } - - /// clears IPCC receive channel status for CPU1 - pub fn c1_clear_flag_channel(channel: IpccChannel) { - let regs = IPCC::regs(); - - trace!("ipcc: ch {}: clear rx", channel as u8); - unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } - } - - #[allow(dead_code)] - /// clears IPCC receive channel status for CPU2 - pub fn c2_clear_flag_channel(channel: IpccChannel) { - let regs = IPCC::regs(); - - unsafe { regs.cpu(1).scr().write(|w| w.set_chc(channel as usize, true)) } - } - - pub fn c1_set_flag_channel(channel: IpccChannel) { - let regs = IPCC::regs(); + compiler_fence(Ordering::SeqCst); + trace!("ipcc: ch {}: send data", channel as u8); unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) } } - #[allow(dead_code)] - pub fn c2_set_flag_channel(channel: IpccChannel) { + /// Wait for the tx channel to become clear + pub async fn flush(channel: IpccChannel) { let regs = IPCC::regs(); - unsafe { regs.cpu(1).scr().write(|w| w.set_chs(channel as usize, true)) } + // This is a race, but is nice for debugging + if unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { + trace!("ipcc: ch {}: wait for tx free", channel as u8); + } + + poll_fn(|cx| { + IPCC::state().tx_waker_for(channel).register(cx.waker()); + // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt + unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)) } + + compiler_fence(Ordering::SeqCst); + + if !unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { + // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt + unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } + + Poll::Ready(()) + } else { + Poll::Pending + } + }) + .await; } - pub fn c1_is_active_flag(channel: IpccChannel) -> bool { + /// Receive data from an IPCC channel. The closure is called to read the data when appropriate. + pub async fn receive(channel: IpccChannel, mut f: impl FnMut() -> Option) -> R { let regs = IPCC::regs(); - unsafe { regs.cpu(0).sr().read().chf(channel as usize) } - } + loop { + // This is a race, but is nice for debugging + if !unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { + trace!("ipcc: ch {}: wait for rx occupied", channel as u8); + } - pub fn c2_is_active_flag(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); + poll_fn(|cx| { + IPCC::state().rx_waker_for(channel).register(cx.waker()); + // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt + unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)) } - unsafe { regs.cpu(1).sr().read().chf(channel as usize) } - } + compiler_fence(Ordering::SeqCst); - pub fn is_tx_pending(channel: IpccChannel) -> bool { - !Self::c1_is_active_flag(channel) && Self::c1_get_tx_channel(channel) - } + if unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { + // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt + unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } - pub fn is_rx_pending(channel: IpccChannel) -> bool { - Self::c2_is_active_flag(channel) && Self::c1_get_rx_channel(channel) + Poll::Ready(()) + } else { + Poll::Pending + } + }) + .await; + + trace!("ipcc: ch {}: read data", channel as u8); + compiler_fence(Ordering::SeqCst); + + match f() { + Some(ret) => return ret, + None => {} + } + + trace!("ipcc: ch {}: clear rx", channel as u8); + compiler_fence(Ordering::SeqCst); + // If the channel is clear and the read function returns none, fetch more data + unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } + } } } @@ -165,9 +212,66 @@ impl sealed::Instance for crate::peripherals::IPCC { fn set_cpu2(enabled: bool) { unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) } } + + fn state() -> &'static self::sealed::State { + static STATE: self::sealed::State = self::sealed::State::new(); + &STATE + } +} + +pub(crate) mod sealed { + use embassy_sync::waitqueue::AtomicWaker; + + use super::*; + + pub struct State { + rx_wakers: [AtomicWaker; 6], + tx_wakers: [AtomicWaker; 6], + } + + impl State { + pub const fn new() -> Self { + const WAKER: AtomicWaker = AtomicWaker::new(); + + Self { + rx_wakers: [WAKER; 6], + tx_wakers: [WAKER; 6], + } + } + + pub fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { + match channel { + IpccChannel::Channel1 => &self.rx_wakers[0], + IpccChannel::Channel2 => &self.rx_wakers[1], + IpccChannel::Channel3 => &self.rx_wakers[2], + IpccChannel::Channel4 => &self.rx_wakers[3], + IpccChannel::Channel5 => &self.rx_wakers[4], + IpccChannel::Channel6 => &self.rx_wakers[5], + } + } + + pub fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { + match channel { + IpccChannel::Channel1 => &self.tx_wakers[0], + IpccChannel::Channel2 => &self.tx_wakers[1], + IpccChannel::Channel3 => &self.tx_wakers[2], + IpccChannel::Channel4 => &self.tx_wakers[3], + IpccChannel::Channel5 => &self.tx_wakers[4], + IpccChannel::Channel6 => &self.tx_wakers[5], + } + } + } + + pub trait Instance: crate::rcc::RccPeripheral { + fn regs() -> crate::pac::ipcc::Ipcc; + fn set_cpu2(enabled: bool); + fn state() -> &'static State; + } } unsafe fn _configure_pwr() { + // TODO: move this to RCC + let pwr = crate::pac::PWR; let rcc = crate::pac::RCC; diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index 5a2309263..bb38204b6 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -8,27 +8,41 @@ mod common; use common::*; use embassy_executor::Spawner; +use embassy_futures::poll_once; use embassy_stm32::bind_interrupts; -use embassy_stm32::ipcc::Config; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32_wpan::ble::Ble; -use embassy_stm32_wpan::rc::RadioCoprocessor; use embassy_stm32_wpan::sys::Sys; -use embassy_stm32_wpan::TlMbox; +use embassy_stm32_wpan::{mm, TlMbox}; use embassy_time::{Duration, Timer}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; - IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; }); +#[embassy_executor::task] +async fn run_mm_queue() { + mm::MemoryManager::run_queue().await; +} + #[embassy_executor::main] -async fn main(_spawner: Spawner) { +async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); info!("Hello World!"); + spawner.spawn(run_mm_queue()).unwrap(); + let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); + let mut rx_buf = [0u8; 500]; + let ready_event = Sys::read().await; + let _ = poll_once(Sys::read()); // clear rx not + ready_event.write(&mut rx_buf).unwrap(); + + info!("coprocessor ready {}", rx_buf); + loop { let wireless_fw_info = mbox.wireless_fw_info(); match wireless_fw_info { @@ -53,19 +67,18 @@ async fn main(_spawner: Spawner) { Timer::after(Duration::from_millis(50)).await; } - let mut rc = RadioCoprocessor::new(mbox); + Sys::shci_c2_ble_init(Default::default()).await; - let response = rc.read().await; - info!("coprocessor ready {}", response); + info!("starting ble..."); + Ble::write(0x0c, &[]).await; - Sys::shci_ble_init(Default::default()); + info!("waiting for ble..."); + let ble_event = Ble::read().await; + ble_event.write(&mut rx_buf).unwrap(); - // rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); - Ble::send_cmd(0x0c, &[]); - - let response = rc.read().await; - info!("ble reset rsp {}", response); + info!("ble event: {}", rx_buf); + // Timer::after(Duration::from_secs(3)).await; info!("Test OK"); cortex_m::asm::bkpt(); } From faa58b907418ce63fef4d3283765067c9e5e3d0b Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 12:06:00 -0500 Subject: [PATCH 90/98] rustfmt --- embassy-stm32-wpan/src/ble.rs | 11 +++-------- embassy-stm32-wpan/src/lib.rs | 4 ++++ embassy-stm32-wpan/src/sys.rs | 11 ++++------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index b7d152631..86a6331fb 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -1,16 +1,11 @@ -use core::mem::MaybeUninit; -use core::ptr; - use embassy_stm32::ipcc::Ipcc; -use crate::cmd::{Cmd, CmdPacket, CmdSerial}; +use crate::cmd::CmdPacket; use crate::consts::TlPacketType; -use crate::evt::{EvtBox, EvtPacket}; +use crate::evt::EvtBox; use crate::tables::BleTable; use crate::unsafe_linked_list::LinkedListNode; -use crate::{ - channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_CHANNEL, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_REF_TABLE, -}; +use crate::{channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; pub struct Ble; diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 78516263c..2f694acf8 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -127,10 +127,14 @@ static mut BLE_CMD_BUFFER: MaybeUninit = MaybeUninit::uninit(); // fuck these "magic" numbers from ST ---v---v static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); +// TODO: remove these items + +#[allow(dead_code)] /// current event that is produced during IPCC IRQ handler execution /// on SYS channel static EVT_CHANNEL: Channel = Channel::new(); +#[allow(dead_code)] /// last received Command Complete event static LAST_CC_EVT: Signal = Signal::new(); diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index f10327b9d..78c357b3f 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -1,13 +1,10 @@ -use core::mem::MaybeUninit; -use core::{mem, ptr}; - -use crate::cmd::{CmdPacket, CmdSerialStub}; +use crate::cmd::CmdPacket; use crate::consts::TlPacketType; -use crate::evt::{CcEvt, EvtBox, EvtPacket, EvtSerial}; -use crate::shci::{ShciBleInitCmdPacket, ShciBleInitCmdParam, ShciHeader, SCHI_OPCODE_BLE_INIT}; +use crate::evt::EvtBox; +use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; use crate::tables::SysTable; use crate::unsafe_linked_list::LinkedListNode; -use crate::{channels, mm, Ipcc, EVT_CHANNEL, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; +use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; pub struct Sys; From 4d2d7d7684dd23a9a9bd9e5467068e3c389db3cb Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 12:13:51 -0500 Subject: [PATCH 91/98] stm32/wpan: fix examples --- examples/stm32wb/src/bin/tl_mbox.rs | 5 +++-- examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | 26 +++++++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index ae36a7e79..a28a8e21b 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -6,13 +6,14 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::Config; +use embassy_stm32::ipcc::{ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; - IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; }); #[embassy_executor::main] diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 3132ab3e4..91a0f9c0a 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs @@ -5,14 +5,15 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; -use embassy_stm32::ipcc::Config; -use embassy_stm32_wpan::rc::RadioCoprocessor; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::ble::Ble; +use embassy_stm32_wpan::sys::Sys; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; - IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; }); #[embassy_executor::main] @@ -45,16 +46,19 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::init(p.IPCC, Irqs, config); + let _ = TlMbox::init(p.IPCC, Irqs, config); - let mut rc = RadioCoprocessor::new(mbox); + let mut rx_buf = [0u8; 500]; + Sys::shci_c2_ble_init(Default::default()).await; - let response = rc.read().await; - info!("coprocessor ready {}", response); + info!("starting ble..."); + Ble::write(0x0c, &[]).await; - rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); - let response = rc.read().await; - info!("ble reset rsp {}", response); + info!("waiting for ble..."); + let ble_event = Ble::read().await; + ble_event.write(&mut rx_buf).unwrap(); + + info!("ble event: {}", rx_buf); info!("Test OK"); cortex_m::asm::bkpt(); From 041a4a4208dae563ab22f9986391509f4b90f740 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 12:15:00 -0500 Subject: [PATCH 92/98] rustfmt --- examples/stm32wb/src/bin/tl_mbox.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index a28a8e21b..b010fdff1 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -5,8 +5,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; -use embassy_stm32::ipcc::Config; -use embassy_stm32::ipcc::{ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; From c7b0df569b02bee80de808a5b0ad69df3d32d84c Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 14:38:36 -0500 Subject: [PATCH 93/98] stm32/wpan: modify evtbox to use slice view --- embassy-stm32-wpan/src/cmd.rs | 54 ++++----- embassy-stm32-wpan/src/evt.rs | 135 ++++++++++++---------- examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | 4 +- tests/stm32/src/bin/tl_mbox.rs | 14 ++- 4 files changed, 112 insertions(+), 95 deletions(-) diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs index 581e5019b..edca82390 100644 --- a/embassy-stm32-wpan/src/cmd.rs +++ b/embassy-stm32-wpan/src/cmd.rs @@ -1,8 +1,7 @@ use core::ptr; use crate::consts::TlPacketType; -use crate::evt::{EvtPacket, EvtSerial}; -use crate::{PacketHeader, TL_EVT_HEADER_SIZE}; +use crate::PacketHeader; #[derive(Copy, Clone)] #[repr(C, packed)] @@ -60,31 +59,6 @@ impl CmdPacket { ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len()); } - - /// Writes an underlying CmdPacket into the provided buffer. - /// Returns a number of bytes that were written. - /// Returns an error if event kind is unknown or if provided buffer size is not enough. - #[allow(clippy::result_unit_err)] - pub fn write(&self, buf: &mut [u8]) -> Result { - unsafe { - let cmd_ptr: *const CmdPacket = self; - let self_as_evt_ptr: *const EvtPacket = cmd_ptr.cast(); - let evt_serial: *const EvtSerial = &(*self_as_evt_ptr).evt_serial; - - let acl_data: *const AclDataPacket = cmd_ptr.cast(); - let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; - let acl_serial_buf: *const u8 = acl_serial.cast(); - - let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; - if len > buf.len() { - return Err(()); - } - - core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); - - Ok(len) - } - } } #[derive(Copy, Clone)] @@ -96,9 +70,35 @@ pub struct AclDataSerial { pub acl_data: [u8; 1], } +#[derive(Copy, Clone)] +#[repr(C, packed)] +pub struct AclDataSerialStub { + pub ty: u8, + pub handle: u16, + pub length: u16, +} + #[derive(Copy, Clone)] #[repr(C, packed)] pub struct AclDataPacket { pub header: PacketHeader, pub acl_data_serial: AclDataSerial, } + +impl AclDataPacket { + pub unsafe fn write_into(cmd_buf: *mut AclDataPacket, packet_type: TlPacketType, handle: u16, payload: &[u8]) { + let p_cmd_serial = &mut (*cmd_buf).acl_data_serial as *mut _ as *mut AclDataSerialStub; + let p_payload = &mut (*cmd_buf).acl_data_serial.acl_data as *mut _; + + ptr::write_volatile( + p_cmd_serial, + AclDataSerialStub { + ty: packet_type as u8, + handle: handle, + length: payload.len() as u16, + }, + ); + + ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len()); + } +} diff --git a/embassy-stm32-wpan/src/evt.rs b/embassy-stm32-wpan/src/evt.rs index 82f73a6f8..3a9d03576 100644 --- a/embassy-stm32-wpan/src/evt.rs +++ b/embassy-stm32-wpan/src/evt.rs @@ -1,8 +1,6 @@ -use core::mem::MaybeUninit; +use core::{ptr, slice}; -use super::cmd::{AclDataPacket, AclDataSerial}; -use super::consts::TlPacketType; -use super::{PacketHeader, TL_EVT_HEADER_SIZE}; +use super::PacketHeader; use crate::mm; /** @@ -63,6 +61,12 @@ pub struct EvtSerial { pub evt: Evt, } +#[derive(Copy, Clone, Default)] +pub struct EvtStub { + pub kind: u8, + pub evt_code: u8, +} + /// This format shall be used for all events (asynchronous and command response) reported /// by the CPU2 except for the command response of a system command where the header is not there /// and the format to be used shall be `EvtSerial`. @@ -101,72 +105,85 @@ impl EvtBox { Self { ptr } } - /// copies event data from inner pointer and returns an event structure - pub fn evt(&self) -> EvtPacket { - let mut evt = MaybeUninit::uninit(); + /// Returns information about the event + pub fn stub(&self) -> EvtStub { unsafe { - self.ptr.copy_to(evt.as_mut_ptr(), 1); - evt.assume_init() + let p_evt_stub = &(*self.ptr).evt_serial as *const _ as *const EvtStub; + + ptr::read_volatile(p_evt_stub) } } - /// writes an underlying [`EvtPacket`] into the provided buffer. - /// Returns the number of bytes that were written. - /// Returns an error if event kind is unknown or if provided buffer size is not enough. - #[allow(clippy::result_unit_err)] - pub fn write(&self, buf: &mut [u8]) -> Result { + pub fn payload<'a>(&self) -> &'a [u8] { unsafe { - let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; + let p_payload_len = &(*self.ptr).evt_serial.evt.payload_len as *const u8; + let p_payload = &(*self.ptr).evt_serial.evt.payload as *const u8; - let evt_data: *const EvtPacket = self.ptr.cast(); - let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; - let evt_serial_buf: *const u8 = evt_serial.cast(); + let payload_len = ptr::read_volatile(p_payload_len); - let acl_data: *const AclDataPacket = self.ptr.cast(); - let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; - let acl_serial_buf: *const u8 = acl_serial.cast(); - - if let TlPacketType::AclData = evt_kind { - let len = (*acl_serial).length as usize + 5; - if len > buf.len() { - return Err(()); - } - - core::ptr::copy(evt_serial_buf, buf.as_mut_ptr(), len); - - Ok(len) - } else { - let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; - if len > buf.len() { - return Err(()); - } - - core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); - - Ok(len) - } + slice::from_raw_parts(p_payload, payload_len as usize) } } - /// returns the size of a buffer required to hold this event - #[allow(clippy::result_unit_err)] - pub fn size(&self) -> Result { - unsafe { - let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; + // TODO: bring back acl - let evt_data: *const EvtPacket = self.ptr.cast(); - let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; - - let acl_data: *const AclDataPacket = self.ptr.cast(); - let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; - - if let TlPacketType::AclData = evt_kind { - Ok((*acl_serial).length as usize + 5) - } else { - Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) - } - } - } + // /// writes an underlying [`EvtPacket`] into the provided buffer. + // /// Returns the number of bytes that were written. + // /// Returns an error if event kind is unknown or if provided buffer size is not enough. + // #[allow(clippy::result_unit_err)] + // pub fn write(&self, buf: &mut [u8]) -> Result { + // unsafe { + // let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; + // + // let evt_data: *const EvtPacket = self.ptr.cast(); + // let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; + // let evt_serial_buf: *const u8 = evt_serial.cast(); + // + // let acl_data: *const AclDataPacket = self.ptr.cast(); + // let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + // let acl_serial_buf: *const u8 = acl_serial.cast(); + // + // if let TlPacketType::AclData = evt_kind { + // let len = (*acl_serial).length as usize + 5; + // if len > buf.len() { + // return Err(()); + // } + // + // core::ptr::copy(evt_serial_buf, buf.as_mut_ptr(), len); + // + // Ok(len) + // } else { + // let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; + // if len > buf.len() { + // return Err(()); + // } + // + // core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); + // + // Ok(len) + // } + // } + // } + // + // /// returns the size of a buffer required to hold this event + // #[allow(clippy::result_unit_err)] + // pub fn size(&self) -> Result { + // unsafe { + // let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; + // + // let evt_data: *const EvtPacket = self.ptr.cast(); + // let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; + // + // let acl_data: *const AclDataPacket = self.ptr.cast(); + // let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + // + // if let TlPacketType::AclData = evt_kind { + // Ok((*acl_serial).length as usize + 5) + // } else { + // Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) + // } + // } + // } } impl Drop for EvtBox { diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 91a0f9c0a..84a4f78e4 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs @@ -48,7 +48,6 @@ async fn main(_spawner: Spawner) { let config = Config::default(); let _ = TlMbox::init(p.IPCC, Irqs, config); - let mut rx_buf = [0u8; 500]; Sys::shci_c2_ble_init(Default::default()).await; info!("starting ble..."); @@ -56,9 +55,8 @@ async fn main(_spawner: Spawner) { info!("waiting for ble..."); let ble_event = Ble::read().await; - ble_event.write(&mut rx_buf).unwrap(); - info!("ble event: {}", rx_buf); + info!("ble event: {}", ble_event.payload()); info!("Test OK"); cortex_m::asm::bkpt(); diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index bb38204b6..259889e35 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -6,6 +6,8 @@ #[path = "../common.rs"] mod common; +use core::mem; + use common::*; use embassy_executor::Spawner; use embassy_futures::poll_once; @@ -36,12 +38,13 @@ async fn main(spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); - let mut rx_buf = [0u8; 500]; let ready_event = Sys::read().await; let _ = poll_once(Sys::read()); // clear rx not - ready_event.write(&mut rx_buf).unwrap(); - info!("coprocessor ready {}", rx_buf); + info!("coprocessor ready {}", ready_event.payload()); + + // test memory manager + mem::drop(ready_event); loop { let wireless_fw_info = mbox.wireless_fw_info(); @@ -74,11 +77,10 @@ async fn main(spawner: Spawner) { info!("waiting for ble..."); let ble_event = Ble::read().await; - ble_event.write(&mut rx_buf).unwrap(); - info!("ble event: {}", rx_buf); + info!("ble event: {}", ble_event.payload()); - // Timer::after(Duration::from_secs(3)).await; + Timer::after(Duration::from_millis(150)).await; info!("Test OK"); cortex_m::asm::bkpt(); } From 6d7d617f40399c5ffaa588f9e5dfefd34164c531 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 15:18:15 -0500 Subject: [PATCH 94/98] stm32/wpan: add ble acl_write --- embassy-stm32-wpan/src/ble.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index 86a6331fb..a39198d06 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -42,5 +42,16 @@ impl Ble { .await; } - // TODO: acl commands + /// `TL_BLE_SendAclData` + pub async fn acl_write(handle: u16, payload: &[u8]) { + Ipcc::send(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, || unsafe { + CmdPacket::write_into( + HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _, + TlPacketType::AclData, + handle, + payload, + ); + }) + .await; + } } From 443550b353c733aee7d122468a82df432014d8fe Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 17 Jun 2023 15:37:34 -0500 Subject: [PATCH 95/98] stm32/wpan: use new ownership model --- embassy-stm32-wpan/src/ble.rs | 16 ++++--- embassy-stm32-wpan/src/lib.rs | 31 +++++++------- embassy-stm32-wpan/src/mm.rs | 13 ++++-- embassy-stm32-wpan/src/sys.rs | 43 +++++++++++-------- examples/stm32wb/src/bin/tl_mbox.rs | 2 +- examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | 13 +++--- tests/stm32/src/bin/tl_mbox.rs | 51 +++++++++-------------- 7 files changed, 88 insertions(+), 81 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index a39198d06..f0bd6f48c 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -1,3 +1,5 @@ +use core::marker::PhantomData; + use embassy_stm32::ipcc::Ipcc; use crate::cmd::CmdPacket; @@ -7,10 +9,12 @@ use crate::tables::BleTable; use crate::unsafe_linked_list::LinkedListNode; use crate::{channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; -pub struct Ble; +pub struct Ble { + phantom: PhantomData, +} impl Ble { - pub(super) fn enable() { + pub(crate) fn new() -> Self { unsafe { LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); @@ -21,9 +25,11 @@ impl Ble { phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), }); } + + Self { phantom: PhantomData } } /// `HW_IPCC_BLE_EvtNot` - pub async fn read() -> EvtBox { + pub async fn read(&self) -> EvtBox { Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { Some(EvtBox::new(node_ptr.cast())) @@ -35,7 +41,7 @@ impl Ble { } /// `TL_BLE_SendCmd` - pub async fn write(opcode: u16, payload: &[u8]) { + pub async fn write(&self, opcode: u16, payload: &[u8]) { Ipcc::send(channels::cpu1::IPCC_BLE_CMD_CHANNEL, || unsafe { CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); }) @@ -43,7 +49,7 @@ impl Ble { } /// `TL_BLE_SendAclData` - pub async fn acl_write(handle: u16, payload: &[u8]) { + pub async fn acl_write(&self, handle: u16, payload: &[u8]) { Ipcc::send(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, || unsafe { CmdPacket::write_into( HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _, diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 2f694acf8..833db0df3 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -6,6 +6,7 @@ pub mod fmt; use core::mem::MaybeUninit; use core::sync::atomic::{compiler_fence, Ordering}; +use ble::Ble; use cmd::CmdPacket; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::interrupt; @@ -16,9 +17,10 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_sync::signal::Signal; use evt::{CcEvt, EvtBox}; +use mm::MemoryManager; +use sys::Sys; use tables::{ BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable, - WirelessFwInfoTable, }; use unsafe_linked_list::LinkedListNode; @@ -142,6 +144,10 @@ static STATE: Signal = Signal::new(); pub struct TlMbox<'d> { _ipcc: PeripheralRef<'d, IPCC>, + + pub sys_subsystem: Sys, + pub mm_subsystem: MemoryManager, + pub ble_subsystem: Ble, } impl<'d> TlMbox<'d> { @@ -226,9 +232,9 @@ impl<'d> TlMbox<'d> { Ipcc::enable(config); - sys::Sys::enable(); - ble::Ble::enable(); - mm::MemoryManager::enable(); + let sys = sys::Sys::new(); + let ble = ble::Ble::new(); + let mm = mm::MemoryManager::new(); // enable interrupts interrupt::typelevel::IPCC_C1_RX::unpend(); @@ -239,18 +245,11 @@ impl<'d> TlMbox<'d> { STATE.reset(); - Self { _ipcc: ipcc } - } - - /// Returns CPU2 wireless firmware information (if present). - pub fn wireless_fw_info(&self) -> Option { - let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table }; - - // Zero version indicates that CPU2 wasn't active and didn't fill the information table - if info.version != 0 { - Some(*info) - } else { - None + Self { + _ipcc: ipcc, + sys_subsystem: sys, + ble_subsystem: ble, + mm_subsystem: mm, } } } diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs index d0551d690..21f42409a 100644 --- a/embassy-stm32-wpan/src/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -1,6 +1,7 @@ //! Memory manager routines use core::future::poll_fn; +use core::marker::PhantomData; use core::task::Poll; use cortex_m::interrupt; @@ -17,10 +18,12 @@ use crate::{ static MM_WAKER: AtomicWaker = AtomicWaker::new(); -pub struct MemoryManager; +pub struct MemoryManager { + phantom: PhantomData, +} impl MemoryManager { - pub fn enable() { + pub(crate) fn new() -> Self { unsafe { LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); @@ -35,10 +38,12 @@ impl MemoryManager { tracespoolsize: 0, }); } + + Self { phantom: PhantomData } } /// SAFETY: passing a pointer to something other than an event packet is UB - pub unsafe fn drop_event_packet(evt: *mut EvtPacket) { + pub(crate) unsafe fn drop_event_packet(evt: *mut EvtPacket) { interrupt::free(|_| unsafe { LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); }); @@ -46,7 +51,7 @@ impl MemoryManager { MM_WAKER.wake(); } - pub async fn run_queue() { + pub async fn run_queue(&self) { loop { poll_fn(|cx| unsafe { MM_WAKER.register(cx.waker()); diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index 78c357b3f..a185cd4f1 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -1,16 +1,20 @@ +use core::marker::PhantomData; + use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::EvtBox; use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; -use crate::tables::SysTable; +use crate::tables::{SysTable, WirelessFwInfoTable}; use crate::unsafe_linked_list::LinkedListNode; -use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; +use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; -pub struct Sys; +pub struct Sys { + phantom: PhantomData, +} impl Sys { /// TL_Sys_Init - pub fn enable() { + pub(crate) fn new() -> Self { unsafe { LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); @@ -19,30 +23,33 @@ impl Sys { sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), }); } + + Self { phantom: PhantomData } } - // pub async fn shci_c2_ble_init(&mut self, param: ShciBleInitCmdParam) -> SchiCommandStatus { - // let command_event = self - // .write_and_get_response(TlPacketType::SysCmd, ShciOpcode::BleInit as u16, param.payload()) - // .await; - // - // let payload = command_event.payload[0]; - // // info!("payload: {:x}", payload); - // - // payload.try_into().unwrap() - // } + /// Returns CPU2 wireless firmware information (if present). + pub fn wireless_fw_info(&self) -> Option { + let info = unsafe { TL_DEVICE_INFO_TABLE.as_mut_ptr().read_volatile().wireless_fw_info_table }; - pub fn write(opcode: u16, payload: &[u8]) { + // Zero version indicates that CPU2 wasn't active and didn't fill the information table + if info.version != 0 { + Some(info) + } else { + None + } + } + + pub fn write(&self, opcode: u16, payload: &[u8]) { unsafe { CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload); } } - pub async fn shci_c2_ble_init(param: ShciBleInitCmdParam) { + pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) { debug!("sending SHCI"); Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || { - Self::write(SCHI_OPCODE_BLE_INIT, param.payload()); + self.write(SCHI_OPCODE_BLE_INIT, param.payload()); }) .await; @@ -50,7 +57,7 @@ impl Sys { } /// `HW_IPCC_SYS_EvtNot` - pub async fn read() -> EvtBox { + pub async fn read(&self) -> EvtBox { Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe { if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { Some(EvtBox::new(node_ptr.cast())) diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index b010fdff1..9fc4b8aac 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) { let mbox = TlMbox::init(p.IPCC, Irqs, config); loop { - let wireless_fw_info = mbox.wireless_fw_info(); + let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info(); match wireless_fw_info { None => info!("not yet initialized"), Some(fw_info) => { diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 84a4f78e4..439bd01ac 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs @@ -6,8 +6,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::ble::Ble; -use embassy_stm32_wpan::sys::Sys; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -46,15 +44,18 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let _ = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config); - Sys::shci_c2_ble_init(Default::default()).await; + let sys_event = mbox.sys_subsystem.read().await; + info!("sys event: {}", sys_event.payload()); + + mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("starting ble..."); - Ble::write(0x0c, &[]).await; + mbox.ble_subsystem.write(0x0c, &[]).await; info!("waiting for ble..."); - let ble_event = Ble::read().await; + let ble_event = mbox.ble_subsystem.read().await; info!("ble event: {}", ble_event.payload()); diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index 259889e35..f6641ae31 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -13,8 +13,6 @@ use embassy_executor::Spawner; use embassy_futures::poll_once; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::ble::Ble; -use embassy_stm32_wpan::sys::Sys; use embassy_stm32_wpan::{mm, TlMbox}; use embassy_time::{Duration, Timer}; @@ -24,8 +22,8 @@ bind_interrupts!(struct Irqs{ }); #[embassy_executor::task] -async fn run_mm_queue() { - mm::MemoryManager::run_queue().await; +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; } #[embassy_executor::main] @@ -33,50 +31,41 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); info!("Hello World!"); - spawner.spawn(run_mm_queue()).unwrap(); - let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); - let ready_event = Sys::read().await; - let _ = poll_once(Sys::read()); // clear rx not + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + + let ready_event = mbox.sys_subsystem.read().await; + let _ = poll_once(mbox.sys_subsystem.read()); // clear rx not info!("coprocessor ready {}", ready_event.payload()); // test memory manager mem::drop(ready_event); - loop { - let wireless_fw_info = mbox.wireless_fw_info(); - match wireless_fw_info { - None => {} - Some(fw_info) => { - let version_major = fw_info.version_major(); - let version_minor = fw_info.version_minor(); - let subversion = fw_info.subversion(); + let fw_info = mbox.sys_subsystem.wireless_fw_info().unwrap(); + let version_major = fw_info.version_major(); + let version_minor = fw_info.version_minor(); + let subversion = fw_info.subversion(); - let sram2a_size = fw_info.sram2a_size(); - let sram2b_size = fw_info.sram2b_size(); + let sram2a_size = fw_info.sram2a_size(); + let sram2b_size = fw_info.sram2b_size(); - info!( - "version {}.{}.{} - SRAM2a {} - SRAM2b {}", - version_major, version_minor, subversion, sram2a_size, sram2b_size - ); + info!( + "version {}.{}.{} - SRAM2a {} - SRAM2b {}", + version_major, version_minor, subversion, sram2a_size, sram2b_size + ); - break; - } - } + Timer::after(Duration::from_millis(50)).await; - Timer::after(Duration::from_millis(50)).await; - } - - Sys::shci_c2_ble_init(Default::default()).await; + mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("starting ble..."); - Ble::write(0x0c, &[]).await; + mbox.ble_subsystem.write(0x0c, &[]).await; info!("waiting for ble..."); - let ble_event = Ble::read().await; + let ble_event = mbox.ble_subsystem.read().await; info!("ble event: {}", ble_event.payload()); From b4f96e192cd8c86f437e1d155388a860dcd3e1fd Mon Sep 17 00:00:00 2001 From: Peter Gibson Date: Sun, 18 Jun 2023 08:45:58 +1000 Subject: [PATCH 96/98] Don't read data register to clear flags on usart v3 ^& v4 --- embassy-stm32/src/usart/buffered.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 530760bd1..086196a2c 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -21,8 +21,10 @@ impl interrupt::typelevel::Handler for Interrupt // RX unsafe { let sr = sr(r).read(); - // Reading DR clears the rxne, error and idle interrupt flags on v1. - let dr = if sr.ore() || sr.idle() || sr.rxne() { + // On v1 & v2, reading DR clears the rxne, error and idle interrupt + // flags. Keep this close to the SR read to reduce the chance of a + // flag being set in-between. + let dr = if sr.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr.ore() || sr.idle()) { Some(rdr(r).read_volatile()) } else { None From 558918651ee99024876fb1f85a559d46edba9548 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 19 Jun 2023 03:07:26 +0200 Subject: [PATCH 97/98] stm32: update stm32-metapac. --- .../layer-by-layer/blinky-irq/src/main.rs | 24 +- embassy-lora/src/iv.rs | 16 +- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/build.rs | 6 +- embassy-stm32/src/adc/f1.rs | 86 +-- embassy-stm32/src/adc/v1.rs | 50 +- embassy-stm32/src/adc/v2.rs | 83 +-- embassy-stm32/src/adc/v3.rs | 178 +++-- embassy-stm32/src/adc/v4.rs | 170 ++--- embassy-stm32/src/can/bxcan.rs | 16 +- embassy-stm32/src/crc/v1.rs | 10 +- embassy-stm32/src/crc/v2v3.rs | 98 ++- embassy-stm32/src/dac.rs | 72 +- embassy-stm32/src/dcmi.rs | 102 +-- embassy-stm32/src/dma/bdma.rs | 56 +- embassy-stm32/src/dma/dma.rs | 84 +-- embassy-stm32/src/dma/dmamux.rs | 2 +- embassy-stm32/src/dma/gpdma.rs | 24 +- embassy-stm32/src/eth/v1/mod.rs | 391 +++++------ embassy-stm32/src/eth/v1/rx_desc.rs | 13 +- embassy-stm32/src/eth/v1/tx_desc.rs | 11 +- embassy-stm32/src/eth/v2/descriptors.rs | 29 +- embassy-stm32/src/eth/v2/mod.rs | 381 +++++----- embassy-stm32/src/exti.rs | 6 +- embassy-stm32/src/flash/f4.rs | 30 +- embassy-stm32/src/fmc.rs | 8 +- embassy-stm32/src/gpio.rs | 36 +- embassy-stm32/src/i2c/v1.rs | 164 ++--- embassy-stm32/src/i2c/v2.rs | 382 +++++----- embassy-stm32/src/i2s.rs | 34 +- embassy-stm32/src/ipcc.rs | 40 +- embassy-stm32/src/lib.rs | 56 +- embassy-stm32/src/pwm/complementary_pwm.rs | 44 +- embassy-stm32/src/pwm/mod.rs | 58 +- embassy-stm32/src/pwm/simple_pwm.rs | 34 +- embassy-stm32/src/qspi/mod.rs | 232 +++---- embassy-stm32/src/rcc/f4.rs | 16 +- embassy-stm32/src/rcc/f7.rs | 4 +- embassy-stm32/src/rcc/g0.rs | 2 +- embassy-stm32/src/rcc/h5.rs | 15 +- embassy-stm32/src/rcc/h7.rs | 22 +- embassy-stm32/src/rng.rs | 44 +- embassy-stm32/src/rtc/datetime.rs | 40 +- embassy-stm32/src/rtc/mod.rs | 34 +- embassy-stm32/src/rtc/v2.rs | 240 ++++--- embassy-stm32/src/rtc/v3.rs | 205 +++--- embassy-stm32/src/sdmmc/mod.rs | 657 +++++++++--------- embassy-stm32/src/spi/mod.rs | 280 ++++---- embassy-stm32/src/time_driver.rs | 20 +- embassy-stm32/src/timer/mod.rs | 64 +- embassy-stm32/src/usart/buffered.rs | 148 ++-- embassy-stm32/src/usart/mod.rs | 421 +++++------ embassy-stm32/src/usart/ringbuffered.rs | 81 +-- embassy-stm32/src/usb/usb.rs | 402 +++++------ embassy-stm32/src/usb_otg/mod.rs | 2 +- embassy-stm32/src/usb_otg/usb.rs | 606 ++++++++-------- embassy-stm32/src/wdg/mod.rs | 12 +- examples/stm32f0/src/bin/wdg.rs | 4 +- examples/stm32f4/src/bin/wdt.rs | 8 +- examples/stm32g4/src/bin/usb_serial.rs | 4 +- examples/stm32h5/src/bin/usb_serial.rs | 8 +- .../stm32h7/src/bin/low_level_timer_api.rs | 54 +- examples/stm32h7/src/bin/wdg.rs | 4 +- examples/stm32l4/src/bin/adc.rs | 10 +- examples/stm32l4/src/bin/dac.rs | 8 +- examples/stm32wl/src/bin/lora_lorawan.rs | 2 +- examples/stm32wl/src/bin/random.rs | 8 +- tests/stm32/src/bin/rtc.rs | 6 +- 68 files changed, 2893 insertions(+), 3568 deletions(-) diff --git a/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs b/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs index 743d0c342..aecba0755 100644 --- a/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs +++ b/docs/modules/ROOT/examples/layer-by-layer/blinky-irq/src/main.rs @@ -20,13 +20,13 @@ fn main() -> ! { let led = Output::new(p.PB14, Level::Low, Speed::Low); let mut button = Input::new(p.PC13, Pull::Up); - cortex_m::interrupt::free(|cs| unsafe { + cortex_m::interrupt::free(|cs| { enable_interrupt(&mut button); LED.borrow(cs).borrow_mut().replace(led); BUTTON.borrow(cs).borrow_mut().replace(button); - NVIC::unmask(pac::Interrupt::EXTI15_10); + unsafe { NVIC::unmask(pac::Interrupt::EXTI15_10) }; }); loop { @@ -64,25 +64,21 @@ const PORT: u8 = 2; const PIN: usize = 13; fn check_interrupt(_pin: &mut Input<'static, P>) -> bool { let exti = pac::EXTI; - unsafe { - let pin = PIN; - let lines = exti.pr(0).read(); - lines.line(pin) - } + let pin = PIN; + let lines = exti.pr(0).read(); + lines.line(pin) } fn clear_interrupt(_pin: &mut Input<'static, P>) { let exti = pac::EXTI; - unsafe { - let pin = PIN; - let mut lines = exti.pr(0).read(); - lines.set_line(pin, true); - exti.pr(0).write_value(lines); - } + let pin = PIN; + let mut lines = exti.pr(0).read(); + lines.set_line(pin, true); + exti.pr(0).write_value(lines); } fn enable_interrupt(_pin: &mut Input<'static, P>) { - cortex_m::interrupt::free(|_| unsafe { + cortex_m::interrupt::free(|_| { let rcc = pac::RCC; rcc.apb2enr().modify(|w| w.set_syscfgen(true)); diff --git a/embassy-lora/src/iv.rs b/embassy-lora/src/iv.rs index 2e0b68d1a..136973fe3 100644 --- a/embassy-lora/src/iv.rs +++ b/embassy-lora/src/iv.rs @@ -68,29 +68,23 @@ where } async fn set_nss_low(&mut self) -> Result<(), RadioError> { let pwr = pac::PWR; - unsafe { - pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW)); - } + pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW)); Ok(()) } async fn set_nss_high(&mut self) -> Result<(), RadioError> { let pwr = pac::PWR; - unsafe { - pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH)); - } + pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH)); Ok(()) } async fn reset(&mut self, _delay: &mut impl DelayUs) -> Result<(), RadioError> { let rcc = pac::RCC; - unsafe { - rcc.csr().modify(|w| w.set_rfrst(true)); - rcc.csr().modify(|w| w.set_rfrst(false)); - } + rcc.csr().modify(|w| w.set_rfrst(true)); + rcc.csr().modify(|w| w.set_rfrst(false)); Ok(()) } async fn wait_on_busy(&mut self) -> Result<(), RadioError> { let pwr = pac::PWR; - while unsafe { pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY } {} + while pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY {} Ok(()) } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index f876c7146..3d9ee8261 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -57,7 +57,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = "9" +stm32-metapac = "10" vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -74,7 +74,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { version = "9", default-features = false, features = ["metadata"]} +stm32-metapac = { version = "10", default-features = false, features = ["metadata"]} [features] default = ["rt"] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 9e597f187..f71074bcf 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -322,7 +322,7 @@ fn main() { let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase()); let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase()); quote! { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true)); crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false)); }); @@ -353,13 +353,13 @@ fn main() { }) } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); #after_enable }) } fn disable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); }) } diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index d30ec001d..2322204d5 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs @@ -32,26 +32,22 @@ impl<'d, T: Instance> Adc<'d, T> { into_ref!(adc); T::enable(); T::reset(); - unsafe { - T::regs().cr2().modify(|reg| reg.set_adon(true)); - } + T::regs().cr2().modify(|reg| reg.set_adon(true)); // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) // for at least two ADC clock cycles delay.delay_us((1_000_000 * 2) / Self::freq().0 + 1); - unsafe { - // Reset calibration - T::regs().cr2().modify(|reg| reg.set_rstcal(true)); - while T::regs().cr2().read().rstcal() { - // spin - } + // Reset calibration + T::regs().cr2().modify(|reg| reg.set_rstcal(true)); + while T::regs().cr2().read().rstcal() { + // spin + } - // Calibrate - T::regs().cr2().modify(|reg| reg.set_cal(true)); - while T::regs().cr2().read().cal() { - // spin - } + // Calibrate + T::regs().cr2().modify(|reg| reg.set_cal(true)); + while T::regs().cr2().read().cal() { + // spin } // One cycle after calibration @@ -81,20 +77,16 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn enable_vref(&self, _delay: &mut impl DelayUs) -> Vref { - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_tsvrefe(true); - }) - } + T::regs().cr2().modify(|reg| { + reg.set_tsvrefe(true); + }); Vref {} } pub fn enable_temperature(&self) -> Temperature { - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_tsvrefe(true); - }) - } + T::regs().cr2().modify(|reg| { + reg.set_tsvrefe(true); + }); Temperature {} } @@ -104,41 +96,37 @@ impl<'d, T: Instance> Adc<'d, T> { /// Perform a single conversion. fn convert(&mut self) -> u16 { - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_adon(true); - reg.set_swstart(true); - }); - while T::regs().cr2().read().swstart() {} - while !T::regs().sr().read().eoc() {} + T::regs().cr2().modify(|reg| { + reg.set_adon(true); + reg.set_swstart(true); + }); + while T::regs().cr2().read().swstart() {} + while !T::regs().sr().read().eoc() {} - T::regs().dr().read().0 as u16 - } + T::regs().dr().read().0 as u16 } pub fn read(&mut self, pin: &mut impl AdcPin) -> u16 { - unsafe { - Self::set_channel_sample_time(pin.channel(), self.sample_time); - T::regs().cr1().modify(|reg| { - reg.set_scan(false); - reg.set_discen(false); - }); - T::regs().sqr1().modify(|reg| reg.set_l(0)); + Self::set_channel_sample_time(pin.channel(), self.sample_time); + T::regs().cr1().modify(|reg| { + reg.set_scan(false); + reg.set_discen(false); + }); + T::regs().sqr1().modify(|reg| reg.set_l(0)); - T::regs().cr2().modify(|reg| { - reg.set_cont(false); - reg.set_exttrig(true); - reg.set_swstart(false); - reg.set_extsel(crate::pac::adc::vals::Extsel::SWSTART); - }); - } + T::regs().cr2().modify(|reg| { + reg.set_cont(false); + reg.set_exttrig(true); + reg.set_swstart(false); + reg.set_extsel(crate::pac::adc::vals::Extsel::SWSTART); + }); // Configure the channel to sample - unsafe { T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())) } + T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())); self.convert() } - unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { let sample_time = sample_time.into(); if ch <= 9 { T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index 82a8c3efb..d9af0c55e 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs @@ -57,18 +57,14 @@ impl<'d, T: Instance> Adc<'d, T> { // // 6.3.20 Vbat monitoring characteristics // ts_vbat ≥ 4μs - unsafe { - T::regs().ccr().modify(|reg| reg.set_vbaten(true)); - } + T::regs().ccr().modify(|reg| reg.set_vbaten(true)); Vbat } pub fn enable_vref(&self, delay: &mut impl DelayUs) -> Vref { // Table 28. Embedded internal reference voltage // tstart = 10μs - unsafe { - T::regs().ccr().modify(|reg| reg.set_vrefen(true)); - } + T::regs().ccr().modify(|reg| reg.set_vrefen(true)); delay.delay_us(10); Vref } @@ -79,27 +75,23 @@ impl<'d, T: Instance> Adc<'d, T> { // 6.3.19 Temperature sensor characteristics // tstart ≤ 10μs // ts_temp ≥ 4μs - unsafe { - T::regs().ccr().modify(|reg| reg.set_tsen(true)); - } + T::regs().ccr().modify(|reg| reg.set_tsen(true)); delay.delay_us(10); Temperature } fn calibrate(&self) { - unsafe { - // A.7.1 ADC calibration code example - if T::regs().cr().read().aden() { - T::regs().cr().modify(|reg| reg.set_addis(true)); - } - while T::regs().cr().read().aden() { - // spin - } - T::regs().cfgr1().modify(|reg| reg.set_dmaen(false)); - T::regs().cr().modify(|reg| reg.set_adcal(true)); - while T::regs().cr().read().adcal() { - // spin - } + // A.7.1 ADC calibration code example + if T::regs().cr().read().aden() { + T::regs().cr().modify(|reg| reg.set_addis(true)); + } + while T::regs().cr().read().aden() { + // spin + } + T::regs().cfgr1().modify(|reg| reg.set_dmaen(false)); + T::regs().cr().modify(|reg| reg.set_adcal(true)); + while T::regs().cr().read().adcal() { + // spin } } @@ -108,9 +100,7 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn set_resolution(&mut self, resolution: Resolution) { - unsafe { - T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); - } + T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); } pub fn read

(&mut self, pin: &mut P) -> u16 @@ -118,18 +108,16 @@ impl<'d, T: Instance> Adc<'d, T> { P: AdcPin + crate::gpio::sealed::Pin, { let channel = pin.channel(); - unsafe { - pin.set_as_analog(); - self.read_channel(channel) - } + pin.set_as_analog(); + self.read_channel(channel) } pub fn read_internal(&mut self, channel: &mut impl InternalChannel) -> u16 { let channel = channel.channel(); - unsafe { self.read_channel(channel) } + self.read_channel(channel) } - unsafe fn read_channel(&mut self, channel: u8) -> u16 { + fn read_channel(&mut self, channel: u8) -> u16 { // A.7.2 ADC enable sequence code example if T::regs().isr().read().adrdy() { T::regs().isr().modify(|reg| reg.set_adrdy(true)); diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index 11a51f993..091c1d447 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs @@ -100,13 +100,10 @@ where T::reset(); let presc = Prescaler::from_pclk2(T::frequency()); - unsafe { - T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); - - T::regs().cr2().modify(|reg| { - reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); - }); - } + T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); + T::regs().cr2().modify(|reg| { + reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); + }); delay.delay_us(ADC_POWERUP_TIME_US); @@ -121,19 +118,15 @@ where } pub fn set_resolution(&mut self, resolution: Resolution) { - unsafe { - T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); - } + T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); } /// Enables internal voltage reference and returns [VrefInt], which can be used in /// [Adc::read_internal()] to perform conversion. pub fn enable_vrefint(&self) -> VrefInt { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); + }); VrefInt {} } @@ -144,11 +137,9 @@ where /// On STM32F42 and STM32F43 this can not be used together with [Vbat]. If both are enabled, /// temperature sensor will return vbat value. pub fn enable_temperature(&self) -> Temperature { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); + }); Temperature {} } @@ -156,37 +147,33 @@ where /// Enables vbat input and returns [Vbat], which can be used in /// [Adc::read_internal()] to perform conversion. pub fn enable_vbat(&self) -> Vbat { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); + }); Vbat {} } /// Perform a single conversion. fn convert(&mut self) -> u16 { - unsafe { - // clear end of conversion flag - T::regs().sr().modify(|reg| { - reg.set_eoc(crate::pac::adc::vals::Eoc::NOTCOMPLETE); - }); + // clear end of conversion flag + T::regs().sr().modify(|reg| { + reg.set_eoc(crate::pac::adc::vals::Eoc::NOTCOMPLETE); + }); - // Start conversion - T::regs().cr2().modify(|reg| { - reg.set_swstart(true); - }); + // Start conversion + T::regs().cr2().modify(|reg| { + reg.set_swstart(true); + }); - while T::regs().sr().read().strt() == crate::pac::adc::vals::Strt::NOTSTARTED { - // spin //wait for actual start - } - while T::regs().sr().read().eoc() == crate::pac::adc::vals::Eoc::NOTCOMPLETE { - // spin //wait for finish - } - - T::regs().dr().read().0 as u16 + while T::regs().sr().read().strt() == crate::pac::adc::vals::Strt::NOTSTARTED { + // spin //wait for actual start } + while T::regs().sr().read().eoc() == crate::pac::adc::vals::Eoc::NOTCOMPLETE { + // spin //wait for finish + } + + T::regs().dr().read().0 as u16 } pub fn read

(&mut self, pin: &mut P) -> u16 @@ -194,18 +181,16 @@ where P: AdcPin, P: crate::gpio::sealed::Pin, { - unsafe { - pin.set_as_analog(); + pin.set_as_analog(); - self.read_channel(pin.channel()) - } + self.read_channel(pin.channel()) } pub fn read_internal(&mut self, channel: &mut impl InternalChannel) -> u16 { - unsafe { self.read_channel(channel.channel()) } + self.read_channel(channel.channel()) } - unsafe fn read_channel(&mut self, channel: u8) -> u16 { + fn read_channel(&mut self, channel: u8) -> u16 { // Configure ADC // Select channel @@ -219,7 +204,7 @@ where val } - unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { let sample_time = sample_time.into(); if ch <= 9 { T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 90aa7d3b9..94cdc86cd 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -12,7 +12,7 @@ pub const VREF_CALIB_MV: u32 = 3000; /// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock /// configuration. fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { #[cfg(stm32h7)] crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true)); #[cfg(stm32g0)] @@ -62,29 +62,25 @@ impl<'d, T: Instance> Adc<'d, T> { pub fn new(adc: impl Peripheral

+ 'd, delay: &mut impl DelayUs) -> Self { into_ref!(adc); enable(); - unsafe { - T::regs().cr().modify(|reg| { - #[cfg(not(adc_g0))] - reg.set_deeppwd(false); - reg.set_advregen(true); - }); + T::regs().cr().modify(|reg| { + #[cfg(not(adc_g0))] + reg.set_deeppwd(false); + reg.set_advregen(true); + }); - #[cfg(adc_g0)] - T::regs().cfgr1().modify(|reg| { - reg.set_chselrmod(false); - }); - } + #[cfg(adc_g0)] + T::regs().cfgr1().modify(|reg| { + reg.set_chselrmod(false); + }); delay.delay_us(20); - unsafe { - T::regs().cr().modify(|reg| { - reg.set_adcal(true); - }); + T::regs().cr().modify(|reg| { + reg.set_adcal(true); + }); - while T::regs().cr().read().adcal() { - // spin - } + while T::regs().cr().read().adcal() { + // spin } delay.delay_us(1); @@ -96,11 +92,9 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn enable_vrefint(&self, delay: &mut impl DelayUs) -> VrefInt { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vrefen(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vrefen(true); + }); // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us // to stabilize the internal voltage reference, we wait a little more. @@ -112,21 +106,17 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn enable_temperature(&self) -> Temperature { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_ch17sel(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_ch17sel(true); + }); Temperature {} } pub fn enable_vbat(&self) -> Vbat { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_ch18sel(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_ch18sel(true); + }); Vbat {} } @@ -136,12 +126,10 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn set_resolution(&mut self, resolution: Resolution) { - unsafe { - #[cfg(not(stm32g0))] - T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); - #[cfg(stm32g0)] - T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); - } + #[cfg(not(stm32g0))] + T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); + #[cfg(stm32g0)] + T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); } /* @@ -155,77 +143,73 @@ impl<'d, T: Instance> Adc<'d, T> { /// Perform a single conversion. fn convert(&mut self) -> u16 { - unsafe { - T::regs().isr().modify(|reg| { - reg.set_eos(true); - reg.set_eoc(true); - }); + T::regs().isr().modify(|reg| { + reg.set_eos(true); + reg.set_eoc(true); + }); - // Start conversion - T::regs().cr().modify(|reg| { - reg.set_adstart(true); - }); + // Start conversion + T::regs().cr().modify(|reg| { + reg.set_adstart(true); + }); - while !T::regs().isr().read().eos() { - // spin - } - - T::regs().dr().read().0 as u16 + while !T::regs().isr().read().eos() { + // spin } + + T::regs().dr().read().0 as u16 } pub fn read(&mut self, pin: &mut impl AdcPin) -> u16 { - unsafe { - // Make sure bits are off - while T::regs().cr().read().addis() { - // spin - } - - // Enable ADC - T::regs().isr().modify(|reg| { - reg.set_adrdy(true); - }); - T::regs().cr().modify(|reg| { - reg.set_aden(true); - }); - - while !T::regs().isr().read().adrdy() { - // spin - } - - // Configure channel - Self::set_channel_sample_time(pin.channel(), self.sample_time); - - // Select channel - #[cfg(not(stm32g0))] - T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); - #[cfg(stm32g0)] - T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel())); - - // Some models are affected by an erratum: - // If we perform conversions slower than 1 kHz, the first read ADC value can be - // corrupted, so we discard it and measure again. - // - // STM32L471xx: Section 2.7.3 - // STM32G4: Section 2.7.3 - #[cfg(any(rcc_l4, rcc_g4))] - let _ = self.convert(); - - let val = self.convert(); - - T::regs().cr().modify(|reg| reg.set_addis(true)); - - val + // Make sure bits are off + while T::regs().cr().read().addis() { + // spin } + + // Enable ADC + T::regs().isr().modify(|reg| { + reg.set_adrdy(true); + }); + T::regs().cr().modify(|reg| { + reg.set_aden(true); + }); + + while !T::regs().isr().read().adrdy() { + // spin + } + + // Configure channel + Self::set_channel_sample_time(pin.channel(), self.sample_time); + + // Select channel + #[cfg(not(stm32g0))] + T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); + #[cfg(stm32g0)] + T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel())); + + // Some models are affected by an erratum: + // If we perform conversions slower than 1 kHz, the first read ADC value can be + // corrupted, so we discard it and measure again. + // + // STM32L471xx: Section 2.7.3 + // STM32G4: Section 2.7.3 + #[cfg(any(rcc_l4, rcc_g4))] + let _ = self.convert(); + + let val = self.convert(); + + T::regs().cr().modify(|reg| reg.set_addis(true)); + + val } #[cfg(stm32g0)] - unsafe fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); } #[cfg(not(stm32g0))] - unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { let sample_time = sample_time.into(); if ch <= 9 { T::regs().smpr1().modify(|reg| reg.set_smp(ch as _, sample_time)); diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index 4707b7c95..c51c6840f 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -46,8 +46,8 @@ foreach_peripheral!( (adc, ADC1) => { impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC1 { fn frequency() -> crate::time::Hertz { - critical_section::with(|_| unsafe { - match crate::rcc::get_freqs().adc { + critical_section::with(|_| { + match unsafe { crate::rcc::get_freqs() }.adc { Some(ck) => ck, None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") } @@ -55,7 +55,7 @@ foreach_peripheral!( } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) }); ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); @@ -63,7 +63,7 @@ foreach_peripheral!( fn disable() { if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); }) } @@ -72,7 +72,7 @@ foreach_peripheral!( fn reset() { if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); }); @@ -85,8 +85,8 @@ foreach_peripheral!( (adc, ADC2) => { impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC2 { fn frequency() -> crate::time::Hertz { - critical_section::with(|_| unsafe { - match crate::rcc::get_freqs().adc { + critical_section::with(|_| { + match unsafe { crate::rcc::get_freqs() }.adc { Some(ck) => ck, None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") } @@ -94,7 +94,7 @@ foreach_peripheral!( } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) }); ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); @@ -102,7 +102,7 @@ foreach_peripheral!( fn disable() { if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); }) } @@ -111,7 +111,7 @@ foreach_peripheral!( fn reset() { if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); }); @@ -124,8 +124,8 @@ foreach_peripheral!( (adc, ADC3) => { impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC3 { fn frequency() -> crate::time::Hertz { - critical_section::with(|_| unsafe { - match crate::rcc::get_freqs().adc { + critical_section::with(|_| { + match unsafe { crate::rcc::get_freqs() }.adc { Some(ck) => ck, None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") } @@ -133,22 +133,22 @@ foreach_peripheral!( } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(true)) }); } fn disable() { - critical_section::with(|_| unsafe { - crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false)); - }) + critical_section::with(|_| { + crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false)); + }) } fn reset() { - critical_section::with(|_| unsafe { - crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true)); - crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false)); - }); + critical_section::with(|_| { + crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true)); + crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false)); + }); } } @@ -232,9 +232,7 @@ impl<'d, T: Instance> Adc<'d, T> { let prescaler = Prescaler::from_ker_ck(T::frequency()); - unsafe { - T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); - } + T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); let frequency = Hertz(T::frequency().0 / prescaler.divisor()); info!("ADC frequency set to {} Hz", frequency.0); @@ -251,9 +249,7 @@ impl<'d, T: Instance> Adc<'d, T> { } else { Boost::LT50 }; - unsafe { - T::regs().cr().modify(|w| w.set_boost(boost)); - } + T::regs().cr().modify(|w| w.set_boost(boost)); let mut s = Self { adc, @@ -272,84 +268,68 @@ impl<'d, T: Instance> Adc<'d, T> { } fn power_up(&mut self, delay: &mut impl DelayUs) { - unsafe { - T::regs().cr().modify(|reg| { - reg.set_deeppwd(false); - reg.set_advregen(true); - }); - } + T::regs().cr().modify(|reg| { + reg.set_deeppwd(false); + reg.set_advregen(true); + }); delay.delay_us(10); } fn configure_differential_inputs(&mut self) { - unsafe { - T::regs().difsel().modify(|w| { - for n in 0..20 { - w.set_difsel(n, Difsel::SINGLEENDED); - } - }) - }; + T::regs().difsel().modify(|w| { + for n in 0..20 { + w.set_difsel(n, Difsel::SINGLEENDED); + } + }); } fn calibrate(&mut self) { - unsafe { - T::regs().cr().modify(|w| { - w.set_adcaldif(Adcaldif::SINGLEENDED); - w.set_adcallin(true); - }); + T::regs().cr().modify(|w| { + w.set_adcaldif(Adcaldif::SINGLEENDED); + w.set_adcallin(true); + }); - T::regs().cr().modify(|w| w.set_adcal(true)); + T::regs().cr().modify(|w| w.set_adcal(true)); - while T::regs().cr().read().adcal() {} - } + while T::regs().cr().read().adcal() {} } fn enable(&mut self) { - unsafe { - T::regs().isr().write(|w| w.set_adrdy(true)); - T::regs().cr().modify(|w| w.set_aden(true)); - while !T::regs().isr().read().adrdy() {} - T::regs().isr().write(|w| w.set_adrdy(true)); - } + T::regs().isr().write(|w| w.set_adrdy(true)); + T::regs().cr().modify(|w| w.set_aden(true)); + while !T::regs().isr().read().adrdy() {} + T::regs().isr().write(|w| w.set_adrdy(true)); } fn configure(&mut self) { // single conversion mode, software trigger - unsafe { - T::regs().cfgr().modify(|w| { - w.set_cont(false); - w.set_exten(Exten::DISABLED); - }) - } + T::regs().cfgr().modify(|w| { + w.set_cont(false); + w.set_exten(Exten::DISABLED); + }); } pub fn enable_vrefint(&self) -> VrefInt { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vrefen(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vrefen(true); + }); VrefInt {} } pub fn enable_temperature(&self) -> Temperature { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vsenseen(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vsenseen(true); + }); Temperature {} } pub fn enable_vbat(&self) -> Vbat { - unsafe { - T::common_regs().ccr().modify(|reg| { - reg.set_vbaten(true); - }); - } + T::common_regs().ccr().modify(|reg| { + reg.set_vbaten(true); + }); Vbat {} } @@ -359,30 +339,26 @@ impl<'d, T: Instance> Adc<'d, T> { } pub fn set_resolution(&mut self, resolution: Resolution) { - unsafe { - T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); - } + T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); } /// Perform a single conversion. fn convert(&mut self) -> u16 { - unsafe { - T::regs().isr().modify(|reg| { - reg.set_eos(true); - reg.set_eoc(true); - }); + T::regs().isr().modify(|reg| { + reg.set_eos(true); + reg.set_eoc(true); + }); - // Start conversion - T::regs().cr().modify(|reg| { - reg.set_adstart(true); - }); + // Start conversion + T::regs().cr().modify(|reg| { + reg.set_adstart(true); + }); - while !T::regs().isr().read().eos() { - // spin - } - - T::regs().dr().read().0 as u16 + while !T::regs().isr().read().eos() { + // spin } + + T::regs().dr().read().0 as u16 } pub fn read

(&mut self, pin: &mut P) -> u16 @@ -390,18 +366,16 @@ impl<'d, T: Instance> Adc<'d, T> { P: AdcPin, P: crate::gpio::sealed::Pin, { - unsafe { - pin.set_as_analog(); + pin.set_as_analog(); - self.read_channel(pin.channel()) - } + self.read_channel(pin.channel()) } pub fn read_internal(&mut self, channel: &mut impl InternalChannel) -> u16 { - unsafe { self.read_channel(channel.channel()) } + self.read_channel(channel.channel()) } - unsafe fn read_channel(&mut self, channel: u8) -> u16 { + fn read_channel(&mut self, channel: u8) -> u16 { // Configure channel Self::set_channel_sample_time(channel, self.sample_time); @@ -417,7 +391,7 @@ impl<'d, T: Instance> Adc<'d, T> { self.convert() } - unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { + fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { let sample_time = sample_time.into(); if ch <= 9 { T::regs().smpr(0).modify(|reg| reg.set_smp(ch as _, sample_time)); diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index bd92b35a0..85f6e99ac 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -20,10 +20,8 @@ impl<'d, T: Instance> Can<'d, T> { ) -> Self { into_ref!(peri, rx, tx); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); T::enable(); T::reset(); @@ -42,10 +40,8 @@ impl<'d, T: Instance> Can<'d, T> { ) -> Self { into_ref!(peri, rx, tx); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); T::enable(); T::reset(); @@ -60,7 +56,7 @@ impl<'d, T: Instance> Drop for Can<'d, T> { fn drop(&mut self) { // Cannot call `free()` because it moves the instance. // Manually reset the peripheral. - unsafe { T::regs().mcr().write(|w| w.set_reset(true)) } + T::regs().mcr().write(|w| w.set_reset(true)); T::disable(); } } @@ -98,7 +94,7 @@ unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> { foreach_peripheral!( (can, $inst:ident) => { impl sealed::Instance for peripherals::$inst { - const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.0 as *mut _; + const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _; fn regs() -> &'static crate::pac::can::Can { &crate::pac::$inst diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs index 393089eed..3946a2d47 100644 --- a/embassy-stm32/src/crc/v1.rs +++ b/embassy-stm32/src/crc/v1.rs @@ -27,26 +27,24 @@ impl<'d> Crc<'d> { /// Resets the CRC unit to default value (0xFFFF_FFFF) pub fn reset(&mut self) { - unsafe { PAC_CRC.cr().write(|w| w.set_reset(true)) }; + PAC_CRC.cr().write(|w| w.set_reset(true)); } /// Feeds a word to the peripheral and returns the current CRC value pub fn feed_word(&mut self, word: u32) -> u32 { // write a single byte to the device, and return the result - unsafe { - PAC_CRC.dr().write_value(word); - } + PAC_CRC.dr().write_value(word); self.read() } /// Feed a slice of words to the peripheral and return the result. pub fn feed_words(&mut self, words: &[u32]) -> u32 { for word in words { - unsafe { PAC_CRC.dr().write_value(*word) } + PAC_CRC.dr().write_value(*word); } self.read() } pub fn read(&self) -> u32 { - unsafe { PAC_CRC.dr().read() } + PAC_CRC.dr().read() } } diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs index 8acb3a770..f337055a7 100644 --- a/embassy-stm32/src/crc/v2v3.rs +++ b/embassy-stm32/src/crc/v2v3.rs @@ -85,95 +85,79 @@ impl<'d> Crc<'d> { } pub fn reset(&mut self) { - unsafe { - PAC_CRC.cr().modify(|w| w.set_reset(true)); - } + PAC_CRC.cr().modify(|w| w.set_reset(true)); } /// Reconfigures the CRC peripheral. Doesn't reset. fn reconfigure(&mut self) { - unsafe { - // Init CRC value - PAC_CRC.init().write_value(self._config.crc_init_value); - #[cfg(crc_v3)] - PAC_CRC.pol().write_value(self._config.crc_poly); + // Init CRC value + PAC_CRC.init().write_value(self._config.crc_init_value); + #[cfg(crc_v3)] + PAC_CRC.pol().write_value(self._config.crc_poly); - // configure CR components - // (reverse I/O, polysize, poly) - PAC_CRC.cr().write(|w| { - // configure reverse output - w.set_rev_out(match self._config.reverse_out { - true => vals::RevOut::REVERSED, - false => vals::RevOut::NORMAL, - }); - // configure reverse input - w.set_rev_in(match self._config.reverse_in { - InputReverseConfig::None => vals::RevIn::NORMAL, - InputReverseConfig::Byte => vals::RevIn::BYTE, - InputReverseConfig::Halfword => vals::RevIn::HALFWORD, - InputReverseConfig::Word => vals::RevIn::WORD, - }); - // configure the polynomial. - #[cfg(crc_v3)] - w.set_polysize(match self._config.poly_size { - PolySize::Width7 => vals::Polysize::POLYSIZE7, - PolySize::Width8 => vals::Polysize::POLYSIZE8, - PolySize::Width16 => vals::Polysize::POLYSIZE16, - PolySize::Width32 => vals::Polysize::POLYSIZE32, - }); - }) - } + // configure CR components + // (reverse I/O, polysize, poly) + PAC_CRC.cr().write(|w| { + // configure reverse output + w.set_rev_out(match self._config.reverse_out { + true => vals::RevOut::REVERSED, + false => vals::RevOut::NORMAL, + }); + // configure reverse input + w.set_rev_in(match self._config.reverse_in { + InputReverseConfig::None => vals::RevIn::NORMAL, + InputReverseConfig::Byte => vals::RevIn::BYTE, + InputReverseConfig::Halfword => vals::RevIn::HALFWORD, + InputReverseConfig::Word => vals::RevIn::WORD, + }); + // configure the polynomial. + #[cfg(crc_v3)] + w.set_polysize(match self._config.poly_size { + PolySize::Width7 => vals::Polysize::POLYSIZE7, + PolySize::Width8 => vals::Polysize::POLYSIZE8, + PolySize::Width16 => vals::Polysize::POLYSIZE16, + PolySize::Width32 => vals::Polysize::POLYSIZE32, + }); + }); self.reset(); } /// Feeds a byte into the CRC peripheral. Returns the computed checksum. pub fn feed_byte(&mut self, byte: u8) -> u32 { - unsafe { - PAC_CRC.dr8().write_value(byte); - PAC_CRC.dr().read() - } + PAC_CRC.dr8().write_value(byte); + PAC_CRC.dr().read() } /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { for byte in bytes { - unsafe { - PAC_CRC.dr8().write_value(*byte); - } + PAC_CRC.dr8().write_value(*byte); } - unsafe { PAC_CRC.dr().read() } + PAC_CRC.dr().read() } /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. pub fn feed_halfword(&mut self, halfword: u16) -> u32 { - unsafe { - PAC_CRC.dr16().write_value(halfword); - PAC_CRC.dr().read() - } + PAC_CRC.dr16().write_value(halfword); + PAC_CRC.dr().read() } /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { for halfword in halfwords { - unsafe { - PAC_CRC.dr16().write_value(*halfword); - } + PAC_CRC.dr16().write_value(*halfword); } - unsafe { PAC_CRC.dr().read() } + PAC_CRC.dr().read() } /// Feeds a words into the CRC peripheral. Returns the computed checksum. pub fn feed_word(&mut self, word: u32) -> u32 { - unsafe { - PAC_CRC.dr().write_value(word as u32); - PAC_CRC.dr().read() - } + PAC_CRC.dr().write_value(word as u32); + PAC_CRC.dr().read() } /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. pub fn feed_words(&mut self, words: &[u32]) -> u32 { for word in words { - unsafe { - PAC_CRC.dr().write_value(*word as u32); - } + PAC_CRC.dr().write_value(*word as u32); } - unsafe { PAC_CRC.dr().read() } + PAC_CRC.dr().read() } } diff --git a/embassy-stm32/src/dac.rs b/embassy-stm32/src/dac.rs index 60e856c78..631118877 100644 --- a/embassy-stm32/src/dac.rs +++ b/embassy-stm32/src/dac.rs @@ -121,13 +121,11 @@ impl<'d, T: Instance> Dac<'d, T> { T::enable(); T::reset(); - unsafe { - T::regs().cr().modify(|reg| { - for ch in 0..channels { - reg.set_en(ch as usize, true); - } - }); - } + T::regs().cr().modify(|reg| { + for ch in 0..channels { + reg.set_en(ch as usize, true); + } + }); Self { channels, _peri: peri } } @@ -143,11 +141,9 @@ impl<'d, T: Instance> Dac<'d, T> { fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { self.check_channel_exists(ch)?; - unsafe { - T::regs().cr().modify(|reg| { - reg.set_en(ch.index(), on); - }) - } + T::regs().cr().modify(|reg| { + reg.set_en(ch.index(), on); + }); Ok(()) } @@ -162,56 +158,42 @@ impl<'d, T: Instance> Dac<'d, T> { pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { self.check_channel_exists(Channel::Ch1)?; unwrap!(self.disable_channel(Channel::Ch1)); - unsafe { - T::regs().cr().modify(|reg| { - reg.set_tsel1(trigger.tsel()); - }) - } + T::regs().cr().modify(|reg| { + reg.set_tsel1(trigger.tsel()); + }); Ok(()) } pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { self.check_channel_exists(Channel::Ch2)?; unwrap!(self.disable_channel(Channel::Ch2)); - unsafe { - T::regs().cr().modify(|reg| { - reg.set_tsel2(trigger.tsel()); - }) - } + T::regs().cr().modify(|reg| { + reg.set_tsel2(trigger.tsel()); + }); Ok(()) } pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { self.check_channel_exists(ch)?; - unsafe { - T::regs().swtrigr().write(|reg| { - reg.set_swtrig(ch.index(), true); - }); - } + T::regs().swtrigr().write(|reg| { + reg.set_swtrig(ch.index(), true); + }); Ok(()) } pub fn trigger_all(&mut self) { - unsafe { - T::regs().swtrigr().write(|reg| { - reg.set_swtrig(Channel::Ch1.index(), true); - reg.set_swtrig(Channel::Ch2.index(), true); - }) - } + T::regs().swtrigr().write(|reg| { + reg.set_swtrig(Channel::Ch1.index(), true); + reg.set_swtrig(Channel::Ch2.index(), true); + }); } pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { self.check_channel_exists(ch)?; match value { - Value::Bit8(v) => unsafe { - T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)); - }, - Value::Bit12(v, Alignment::Left) => unsafe { - T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)); - }, - Value::Bit12(v, Alignment::Right) => unsafe { - T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)); - }, + Value::Bit8(v) => T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)), + Value::Bit12(v, Alignment::Left) => T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)), + Value::Bit12(v, Alignment::Right) => T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)), } Ok(()) } @@ -239,20 +221,20 @@ foreach_peripheral!( } fn reset() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); }) } fn enable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); }) } fn disable() { - critical_section::with(|_| unsafe { + critical_section::with(|_| { crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)); }) } diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 41305d273..78b026cb6 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -96,8 +96,7 @@ impl Default for Config { macro_rules! config_pins { ($($pin:ident),*) => { into_ref!($($pin),*); - // NOTE(unsafe) Exclusive access to the registers - critical_section::with(|_| unsafe { + critical_section::with(|_| { $( $pin.set_as_af($pin.af_num(), AFType::Input); $pin.set_speed(Speed::VeryHigh); @@ -334,17 +333,15 @@ where T::reset(); T::enable(); - unsafe { - peri.regs().cr().modify(|r| { - r.set_cm(true); // disable continuous mode (snapshot mode) - r.set_ess(use_embedded_synchronization); - r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge); - r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High); - r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High); - r.set_fcrc(0x00); // capture every frame - r.set_edm(edm); // extended data mode - }); - } + peri.regs().cr().modify(|r| { + r.set_cm(true); // disable continuous mode (snapshot mode) + r.set_ess(use_embedded_synchronization); + r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge); + r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High); + r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High); + r.set_fcrc(0x00); // capture every frame + r.set_edm(edm); // extended data mode + }); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; @@ -352,7 +349,7 @@ where Self { inner: peri, dma } } - unsafe fn toggle(enable: bool) { + fn toggle(enable: bool) { crate::pac::DCMI.cr().modify(|r| { r.set_enable(enable); r.set_capture(enable); @@ -360,23 +357,19 @@ where } fn enable_irqs() { - unsafe { - crate::pac::DCMI.ier().modify(|r| { - r.set_err_ie(true); - r.set_ovr_ie(true); - r.set_frame_ie(true); - }); - } + crate::pac::DCMI.ier().modify(|r| { + r.set_err_ie(true); + r.set_ovr_ie(true); + r.set_frame_ie(true); + }); } fn clear_interrupt_flags() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_ovr_isc(true); - r.set_err_isc(true); - r.set_frame_isc(true); - }) - } + crate::pac::DCMI.icr().write(|r| { + r.set_ovr_isc(true); + r.set_err_isc(true); + r.set_frame_isc(true); + }) } /// This method starts the capture and finishes when both the dma transfer and DCMI finish the frame transfer. @@ -392,41 +385,30 @@ where return self.capture_giant(buffer).await; } } + async fn capture_small(&mut self, buffer: &mut [u32]) -> Result<(), Error> { let r = self.inner.regs(); - let src = r.dr().ptr() as *mut u32; + let src = r.dr().as_ptr() as *mut u32; let request = self.dma.request(); let dma_read = unsafe { Transfer::new_read(&mut self.dma, request, src, buffer, Default::default()) }; Self::clear_interrupt_flags(); Self::enable_irqs(); - unsafe { Self::toggle(true) }; + Self::toggle(true); let result = poll_fn(|cx| { STATE.waker.register(cx.waker()); - let ris = unsafe { crate::pac::DCMI.ris().read() }; + let ris = crate::pac::DCMI.ris().read(); if ris.err_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_err_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_err_isc(true)); Poll::Ready(Err(Error::PeripheralError)) } else if ris.ovr_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_ovr_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_ovr_isc(true)); Poll::Ready(Err(Error::Overrun)) } else if ris.frame_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_frame_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_frame_isc(true)); Poll::Ready(Ok(())) } else { Poll::Pending @@ -435,7 +417,7 @@ where let (_, result) = embassy_futures::join::join(dma_read, result).await; - unsafe { Self::toggle(false) }; + Self::toggle(false); result } @@ -468,7 +450,7 @@ where let request = channel.request(); let r = self.inner.regs(); - let src = r.dr().ptr() as *mut u32; + let src = r.dr().as_ptr() as *mut u32; let mut transfer = unsafe { crate::dma::DoubleBuffered::new_read( @@ -526,38 +508,26 @@ where let result = poll_fn(|cx| { STATE.waker.register(cx.waker()); - let ris = unsafe { crate::pac::DCMI.ris().read() }; + let ris = crate::pac::DCMI.ris().read(); if ris.err_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_err_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_err_isc(true)); Poll::Ready(Err(Error::PeripheralError)) } else if ris.ovr_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_ovr_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_ovr_isc(true)); Poll::Ready(Err(Error::Overrun)) } else if ris.frame_ris() { - unsafe { - crate::pac::DCMI.icr().write(|r| { - r.set_frame_isc(true); - }) - }; + crate::pac::DCMI.icr().write(|r| r.set_frame_isc(true)); Poll::Ready(Ok(())) } else { Poll::Pending } }); - unsafe { Self::toggle(true) }; + Self::toggle(true); let (_, result) = embassy_futures::join::join(dma_result, result).await; - unsafe { Self::toggle(false) }; + Self::toggle(false); result } diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index c0a503e25..5fcb30f65 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -107,7 +107,7 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index let cr = dma.ch(channel_num).cr(); if isr.teif(channel_num) { - panic!("DMA: error on BDMA@{:08x} channel {}", dma.0 as u32, channel_num); + panic!("DMA: error on BDMA@{:08x} channel {}", dma.as_ptr() as u32, channel_num); } if isr.htif(channel_num) && cr.read().htie() { @@ -291,29 +291,25 @@ impl<'a, C: Channel> Transfer<'a, C> { } fn clear_irqs(&mut self) { - unsafe { - self.channel.regs().ifcr().write(|w| { - w.set_tcif(self.channel.num(), true); - w.set_teif(self.channel.num(), true); - }) - } + self.channel.regs().ifcr().write(|w| { + w.set_tcif(self.channel.num(), true); + w.set_teif(self.channel.num(), true); + }); } pub fn request_stop(&mut self) { let ch = self.channel.regs().ch(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().ch(self.channel.num()); - let en = unsafe { ch.cr().read() }.en(); + let en = ch.cr().read().en(); let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; en && !tcif } @@ -322,7 +318,7 @@ impl<'a, C: Channel> Transfer<'a, C> { /// Note: this will be zero for transfers that completed without cancellation. pub fn get_remaining_transfers(&self) -> u16 { let ch = self.channel.regs().ch(self.channel.num()); - unsafe { ch.ndtr().read() }.ndt() + ch.ndtr().read().ndt() } pub fn blocking_wait(mut self) { @@ -366,7 +362,7 @@ struct DmaCtrlImpl<'a, C: Channel>(PeripheralRef<'a, C>); impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { fn get_remaining_transfers(&self) -> usize { let ch = self.0.regs().ch(self.0.num()); - unsafe { ch.ndtr().read() }.ndt() as usize + ch.ndtr().read().ndt() as usize } fn get_complete_count(&self) -> usize { @@ -442,7 +438,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { pub fn start(&mut self) { let ch = self.channel.regs().ch(self.channel.num()); - unsafe { ch.cr().write_value(self.cr) } + ch.cr().write_value(self.cr) } pub fn clear(&mut self) { @@ -469,31 +465,27 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { fn clear_irqs(&mut self) { let dma = self.channel.regs(); - unsafe { - dma.ifcr().write(|w| { - w.set_htif(self.channel.num(), true); - w.set_tcif(self.channel.num(), true); - w.set_teif(self.channel.num(), true); - }) - } + dma.ifcr().write(|w| { + w.set_htif(self.channel.num(), true); + w.set_tcif(self.channel.num(), true); + w.set_teif(self.channel.num(), true); + }); } pub fn request_stop(&mut self) { let ch = self.channel.regs().ch(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_htie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_htie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().ch(self.channel.num()); - unsafe { ch.cr().read() }.en() + ch.cr().read().en() } } diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 874cb013a..8abe541d3 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -183,7 +183,7 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: usize, index: let isr = dma.isr(channel_num / 4).read(); if isr.teif(channel_num % 4) { - panic!("DMA: error on DMA@{:08x} channel {}", dma.0 as u32, channel_num); + panic!("DMA: error on DMA@{:08x} channel {}", dma.as_ptr() as u32, channel_num); } if isr.htif(channel_num % 4) && cr.read().htie() { @@ -387,36 +387,32 @@ impl<'a, C: Channel> Transfer<'a, C> { let isrn = self.channel.num() / 4; let isrbit = self.channel.num() % 4; - unsafe { - self.channel.regs().ifcr(isrn).write(|w| { - w.set_tcif(isrbit, true); - w.set_teif(isrbit, true); - }) - } + self.channel.regs().ifcr(isrn).write(|w| { + w.set_tcif(isrbit, true); + w.set_teif(isrbit, true); + }); } pub fn request_stop(&mut self) { let ch = self.channel.regs().st(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().read() }.en() + ch.cr().read().en() } /// Gets the total remaining transfers for the channel /// Note: this will be zero for transfers that completed without cancellation. pub fn get_remaining_transfers(&self) -> u16 { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.ndtr().read() }.ndt() + ch.ndtr().read().ndt() } pub fn blocking_wait(mut self) { @@ -537,13 +533,11 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { let isrn = channel_number / 4; let isrbit = channel_number % 4; - unsafe { - dma.ifcr(isrn).write(|w| { - w.set_htif(isrbit, true); - w.set_tcif(isrbit, true); - w.set_teif(isrbit, true); - }) - } + dma.ifcr(isrn).write(|w| { + w.set_htif(isrbit, true); + w.set_tcif(isrbit, true); + w.set_teif(isrbit, true); + }); } pub unsafe fn set_buffer0(&mut self, buffer: *mut W) { @@ -558,7 +552,7 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { pub fn is_buffer0_accessible(&mut self) -> bool { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().read() }.ct() == vals::Ct::MEMORY1 + ch.cr().read().ct() == vals::Ct::MEMORY1 } pub fn set_waker(&mut self, waker: &Waker) { @@ -569,24 +563,22 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { let ch = self.channel.regs().st(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().read() }.en() + ch.cr().read().en() } /// Gets the total remaining transfers for the channel /// Note: this will be zero for transfers that completed without cancellation. pub fn get_remaining_transfers(&self) -> u16 { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.ndtr().read() }.ndt() + ch.ndtr().read().ndt() } } @@ -607,7 +599,7 @@ struct DmaCtrlImpl<'a, C: Channel>(PeripheralRef<'a, C>); impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { fn get_remaining_transfers(&self) -> usize { let ch = self.0.regs().st(self.0.num()); - unsafe { ch.ndtr().read() }.ndt() as usize + ch.ndtr().read().ndt() as usize } fn get_complete_count(&self) -> usize { @@ -698,7 +690,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { pub fn start(&mut self) { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().write_value(self.cr) } + ch.cr().write_value(self.cr); } pub fn clear(&mut self) { @@ -729,31 +721,27 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { let isrn = channel_number / 4; let isrbit = channel_number % 4; - unsafe { - dma.ifcr(isrn).write(|w| { - w.set_htif(isrbit, true); - w.set_tcif(isrbit, true); - w.set_teif(isrbit, true); - }) - } + dma.ifcr(isrn).write(|w| { + w.set_htif(isrbit, true); + w.set_tcif(isrbit, true); + w.set_teif(isrbit, true); + }); } pub fn request_stop(&mut self) { let ch = self.channel.regs().st(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_teie(true); - w.set_htie(true); - w.set_tcie(true); - }) - } + ch.cr().write(|w| { + w.set_teie(true); + w.set_htie(true); + w.set_tcie(true); + }); } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().st(self.channel.num()); - unsafe { ch.cr().read() }.en() + ch.cr().read().en() } } diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs index a8c4c5827..36fc03403 100644 --- a/embassy-stm32/src/dma/dmamux.rs +++ b/embassy-stm32/src/dma/dmamux.rs @@ -2,7 +2,7 @@ use crate::{pac, peripherals}; -pub(crate) unsafe fn configure_dmamux(channel: &mut M, request: u8) { +pub(crate) fn configure_dmamux(channel: &mut M, request: u8) { let ch_mux_regs = channel.mux_regs().ccr(channel.mux_num()); ch_mux_regs.write(|reg| { reg.set_nbreq(0); diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index 3f0d5e8fa..c600df92d 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -92,13 +92,15 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::gpdma::Gpdma, channel_num: usize, in if sr.dtef() { panic!( "DMA: data transfer error on DMA@{:08x} channel {}", - dma.0 as u32, channel_num + dma.as_ptr() as u32, + channel_num ); } if sr.usef() { panic!( "DMA: user settings error on DMA@{:08x} channel {}", - dma.0 as u32, channel_num + dma.as_ptr() as u32, + channel_num ); } @@ -298,26 +300,24 @@ impl<'a, C: Channel> Transfer<'a, C> { let ch = self.channel.regs().ch(self.channel.num()); // Disable the channel. Keep the IEs enabled so the irqs still fire. - unsafe { - ch.cr().write(|w| { - w.set_tcie(true); - w.set_useie(true); - w.set_dteie(true); - w.set_suspie(true); - }) - } + ch.cr().write(|w| { + w.set_tcie(true); + w.set_useie(true); + w.set_dteie(true); + w.set_suspie(true); + }) } pub fn is_running(&mut self) -> bool { let ch = self.channel.regs().ch(self.channel.num()); - !unsafe { ch.sr().read() }.tcf() + !ch.sr().read().tcf() } /// Gets the total remaining transfers for the channel /// Note: this will be zero for transfers that completed without cancellation. pub fn get_remaining_transfers(&self) -> u16 { let ch = self.channel.regs().ch(self.channel.num()); - unsafe { ch.br1().read() }.bndt() + ch.br1().read().bndt() } pub fn blocking_wait(mut self) { diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 540cdd027..b53c2d0fa 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -29,18 +29,16 @@ impl interrupt::typelevel::Handler for InterruptHandl WAKER.wake(); // TODO: Check and clear more flags - unsafe { - let dma = ETH.ethernet_dma(); + let dma = ETH.ethernet_dma(); - dma.dmasr().modify(|w| { - w.set_ts(true); - w.set_rs(true); - w.set_nis(true); - }); - // Delay two peripheral's clock - dma.dmasr().read(); - dma.dmasr().read(); - } + dma.dmasr().modify(|w| { + w.set_ts(true); + w.set_rs(true); + w.set_nis(true); + }); + // Delay two peripheral's clock + dma.dmasr().read(); + dma.dmasr().read(); } } @@ -59,7 +57,6 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { #[cfg(eth_v1a)] macro_rules! config_in_pins { ($($pin:ident),*) => { - // NOTE(unsafe) Exclusive access to the registers critical_section::with(|_| { $( // TODO properly create a set_as_input function @@ -72,7 +69,6 @@ macro_rules! config_in_pins { #[cfg(eth_v1a)] macro_rules! config_af_pins { ($($pin:ident),*) => { - // NOTE(unsafe) Exclusive access to the registers critical_section::with(|_| { $( // We are lucky here, this configures to max speed (50MHz) @@ -85,7 +81,6 @@ macro_rules! config_af_pins { #[cfg(any(eth_v1b, eth_v1c))] macro_rules! config_pins { ($($pin:ident),*) => { - // NOTE(unsafe) Exclusive access to the registers critical_section::with(|_| { $( $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); @@ -116,222 +111,208 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { ) -> Self { into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - unsafe { - // Enable the necessary Clocks - // NOTE(unsafe) We have exclusive access to the registers - #[cfg(eth_v1a)] - critical_section::with(|_| { - RCC.apb2enr().modify(|w| w.set_afioen(true)); + // Enable the necessary Clocks + #[cfg(eth_v1a)] + critical_section::with(|_| { + RCC.apb2enr().modify(|w| w.set_afioen(true)); - // Select RMII (Reduced Media Independent Interface) - // Must be done prior to enabling peripheral clock - AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); + // Select RMII (Reduced Media Independent Interface) + // Must be done prior to enabling peripheral clock + AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); - RCC.ahbenr().modify(|w| { - w.set_ethen(true); - w.set_ethtxen(true); - w.set_ethrxen(true); - }); + RCC.ahbenr().modify(|w| { + w.set_ethen(true); + w.set_ethtxen(true); + w.set_ethrxen(true); + }); + }); + + #[cfg(any(eth_v1b, eth_v1c))] + critical_section::with(|_| { + RCC.apb2enr().modify(|w| w.set_syscfgen(true)); + RCC.ahb1enr().modify(|w| { + w.set_ethen(true); + w.set_ethtxen(true); + w.set_ethrxen(true); }); - #[cfg(any(eth_v1b, eth_v1c))] - critical_section::with(|_| { - RCC.apb2enr().modify(|w| w.set_syscfgen(true)); - RCC.ahb1enr().modify(|w| { - w.set_ethen(true); - w.set_ethtxen(true); - w.set_ethrxen(true); - }); + // RMII (Reduced Media Independent Interface) + SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); + }); - // RMII (Reduced Media Independent Interface) - SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); - }); - - #[cfg(eth_v1a)] - { - config_in_pins!(ref_clk, rx_d0, rx_d1); - config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); - } - - #[cfg(any(eth_v1b, eth_v1c))] - config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - - // NOTE(unsafe) We have exclusive access to the registers - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - - // Reset and wait - dma.dmabmr().modify(|w| w.set_sr(true)); - while dma.dmabmr().read().sr() {} - - mac.maccr().modify(|w| { - w.set_ifg(Ifg::IFG96); // inter frame gap 96 bit times - w.set_apcs(Apcs::STRIP); // automatic padding and crc stripping - w.set_fes(Fes::FES100); // fast ethernet speed - w.set_dm(Dm::FULLDUPLEX); // full duplex - // TODO: Carrier sense ? ECRSFD - }); - - // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, - // so the LR write must happen after the HR write. - mac.maca0hr() - .modify(|w| w.set_maca0h(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); - mac.maca0lr().write(|w| { - w.set_maca0l( - u32::from(mac_addr[0]) - | (u32::from(mac_addr[1]) << 8) - | (u32::from(mac_addr[2]) << 16) - | (u32::from(mac_addr[3]) << 24), - ) - }); - - // pause time - mac.macfcr().modify(|w| w.set_pt(0x100)); - - // Transfer and Forward, Receive and Forward - dma.dmaomr().modify(|w| { - w.set_tsf(Tsf::STOREFORWARD); - w.set_rsf(Rsf::STOREFORWARD); - }); - - dma.dmabmr().modify(|w| { - w.set_pbl(Pbl::PBL32) // programmable burst length - 32 ? - }); - - // TODO MTU size setting not found for v1 ethernet, check if correct - - // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called - let hclk = crate::rcc::get_freqs().ahb1; - let hclk_mhz = hclk.0 / 1_000_000; - - // Set the MDC clock frequency in the range 1MHz - 2.5MHz - let clock_range = match hclk_mhz { - 0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."), - 25..=34 => Cr::CR_20_35, // Divide by 16 - 35..=59 => Cr::CR_35_60, // Divide by 26 - 60..=99 => Cr::CR_60_100, // Divide by 42 - 100..=149 => Cr::CR_100_150, // Divide by 62 - 150..=216 => Cr::CR_150_168, // Divide by 102 - _ => { - panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") - } - }; - - let pins = [ - ref_clk.map_into(), - mdio.map_into(), - mdc.map_into(), - crs.map_into(), - rx_d0.map_into(), - rx_d1.map_into(), - tx_d0.map_into(), - tx_d1.map_into(), - tx_en.map_into(), - ]; - - let mut this = Self { - _peri: peri, - pins, - _phy: phy, - clock_range, - phy_addr, - mac_addr, - tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), - rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), - }; - - fence(Ordering::SeqCst); - - let mac = ETH.ethernet_mac(); - let dma = ETH.ethernet_dma(); - - mac.maccr().modify(|w| { - w.set_re(true); - w.set_te(true); - }); - dma.dmaomr().modify(|w| { - w.set_ftf(Ftf::FLUSH); // flush transmit fifo (queue) - w.set_st(St::STARTED); // start transmitting channel - w.set_sr(DmaomrSr::STARTED); // start receiving channel - }); - - this.rx.demand_poll(); - - // Enable interrupts - dma.dmaier().modify(|w| { - w.set_nise(true); - w.set_rie(true); - w.set_tie(true); - }); - - P::phy_reset(&mut this); - P::phy_init(&mut this); - - interrupt::ETH.unpend(); - interrupt::ETH.enable(); - - this + #[cfg(eth_v1a)] + { + config_in_pins!(ref_clk, rx_d0, rx_d1); + config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); } + + #[cfg(any(eth_v1b, eth_v1c))] + config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); + + let dma = ETH.ethernet_dma(); + let mac = ETH.ethernet_mac(); + + // Reset and wait + dma.dmabmr().modify(|w| w.set_sr(true)); + while dma.dmabmr().read().sr() {} + + mac.maccr().modify(|w| { + w.set_ifg(Ifg::IFG96); // inter frame gap 96 bit times + w.set_apcs(Apcs::STRIP); // automatic padding and crc stripping + w.set_fes(Fes::FES100); // fast ethernet speed + w.set_dm(Dm::FULLDUPLEX); // full duplex + // TODO: Carrier sense ? ECRSFD + }); + + // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, + // so the LR write must happen after the HR write. + mac.maca0hr() + .modify(|w| w.set_maca0h(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); + mac.maca0lr().write(|w| { + w.set_maca0l( + u32::from(mac_addr[0]) + | (u32::from(mac_addr[1]) << 8) + | (u32::from(mac_addr[2]) << 16) + | (u32::from(mac_addr[3]) << 24), + ) + }); + + // pause time + mac.macfcr().modify(|w| w.set_pt(0x100)); + + // Transfer and Forward, Receive and Forward + dma.dmaomr().modify(|w| { + w.set_tsf(Tsf::STOREFORWARD); + w.set_rsf(Rsf::STOREFORWARD); + }); + + dma.dmabmr().modify(|w| { + w.set_pbl(Pbl::PBL32) // programmable burst length - 32 ? + }); + + // TODO MTU size setting not found for v1 ethernet, check if correct + + // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called + let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; + let hclk_mhz = hclk.0 / 1_000_000; + + // Set the MDC clock frequency in the range 1MHz - 2.5MHz + let clock_range = match hclk_mhz { + 0..=24 => panic!("Invalid HCLK frequency - should be at least 25 MHz."), + 25..=34 => Cr::CR_20_35, // Divide by 16 + 35..=59 => Cr::CR_35_60, // Divide by 26 + 60..=99 => Cr::CR_60_100, // Divide by 42 + 100..=149 => Cr::CR_100_150, // Divide by 62 + 150..=216 => Cr::CR_150_168, // Divide by 102 + _ => { + panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") + } + }; + + let pins = [ + ref_clk.map_into(), + mdio.map_into(), + mdc.map_into(), + crs.map_into(), + rx_d0.map_into(), + rx_d1.map_into(), + tx_d0.map_into(), + tx_d1.map_into(), + tx_en.map_into(), + ]; + + let mut this = Self { + _peri: peri, + pins, + _phy: phy, + clock_range, + phy_addr, + mac_addr, + tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), + rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), + }; + + fence(Ordering::SeqCst); + + let mac = ETH.ethernet_mac(); + let dma = ETH.ethernet_dma(); + + mac.maccr().modify(|w| { + w.set_re(true); + w.set_te(true); + }); + dma.dmaomr().modify(|w| { + w.set_ftf(Ftf::FLUSH); // flush transmit fifo (queue) + w.set_st(St::STARTED); // start transmitting channel + w.set_sr(DmaomrSr::STARTED); // start receiving channel + }); + + this.rx.demand_poll(); + + // Enable interrupts + dma.dmaier().modify(|w| { + w.set_nise(true); + w.set_rie(true); + w.set_tie(true); + }); + + P::phy_reset(&mut this); + P::phy_init(&mut this); + + interrupt::ETH.unpend(); + unsafe { interrupt::ETH.enable() }; + + this } } unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { fn smi_read(&mut self, reg: u8) -> u16 { - // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` - unsafe { - let mac = ETH.ethernet_mac(); + let mac = ETH.ethernet_mac(); - mac.macmiiar().modify(|w| { - w.set_pa(self.phy_addr); - w.set_mr(reg); - w.set_mw(Mw::READ); // read operation - w.set_cr(self.clock_range); - w.set_mb(MbProgress::BUSY); // indicate that operation is in progress - }); - while mac.macmiiar().read().mb() == MbProgress::BUSY {} - mac.macmiidr().read().md() - } + mac.macmiiar().modify(|w| { + w.set_pa(self.phy_addr); + w.set_mr(reg); + w.set_mw(Mw::READ); // read operation + w.set_cr(self.clock_range); + w.set_mb(MbProgress::BUSY); // indicate that operation is in progress + }); + while mac.macmiiar().read().mb() == MbProgress::BUSY {} + mac.macmiidr().read().md() } fn smi_write(&mut self, reg: u8, val: u16) { - // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` - unsafe { - let mac = ETH.ethernet_mac(); + let mac = ETH.ethernet_mac(); - mac.macmiidr().write(|w| w.set_md(val)); - mac.macmiiar().modify(|w| { - w.set_pa(self.phy_addr); - w.set_mr(reg); - w.set_mw(Mw::WRITE); // write - w.set_cr(self.clock_range); - w.set_mb(MbProgress::BUSY); - }); - while mac.macmiiar().read().mb() == MbProgress::BUSY {} - } + mac.macmiidr().write(|w| w.set_md(val)); + mac.macmiiar().modify(|w| { + w.set_pa(self.phy_addr); + w.set_mr(reg); + w.set_mw(Mw::WRITE); // write + w.set_cr(self.clock_range); + w.set_mb(MbProgress::BUSY); + }); + while mac.macmiiar().read().mb() == MbProgress::BUSY {} } } impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { fn drop(&mut self) { - // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers - unsafe { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); + let dma = ETH.ethernet_dma(); + let mac = ETH.ethernet_mac(); - // Disable the TX DMA and wait for any previous transmissions to be completed - dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); + // Disable the TX DMA and wait for any previous transmissions to be completed + dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); - // Disable MAC transmitter and receiver - mac.maccr().modify(|w| { - w.set_re(false); - w.set_te(false); - }); + // Disable MAC transmitter and receiver + mac.maccr().modify(|w| { + w.set_re(false); + w.set_te(false); + }); - dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED)); - } + dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED)); - // NOTE(unsafe) Exclusive access to the regs - critical_section::with(|_| unsafe { + critical_section::with(|_| { for pin in self.pins.iter_mut() { pin.set_as_disconnected(); } diff --git a/embassy-stm32/src/eth/v1/rx_desc.rs b/embassy-stm32/src/eth/v1/rx_desc.rs index 8b8566d92..01a073bb9 100644 --- a/embassy-stm32/src/eth/v1/rx_desc.rs +++ b/embassy-stm32/src/eth/v1/rx_desc.rs @@ -146,12 +146,9 @@ impl<'a> RDesRing<'a> { } // Register rx descriptor start - // NOTE (unsafe) Used for atomic writes - unsafe { - ETH.ethernet_dma() - .dmardlar() - .write(|w| w.0 = descriptors.as_ptr() as u32); - }; + ETH.ethernet_dma() + .dmardlar() + .write(|w| w.0 = descriptors.as_ptr() as u32); // We already have fences in `set_owned`, which is called in `setup` Self { @@ -162,12 +159,12 @@ impl<'a> RDesRing<'a> { } pub(crate) fn demand_poll(&self) { - unsafe { ETH.ethernet_dma().dmarpdr().write(|w| w.set_rpd(Rpd::POLL)) }; + ETH.ethernet_dma().dmarpdr().write(|w| w.set_rpd(Rpd::POLL)); } /// Get current `RunningState` fn running_state(&self) -> RunningState { - match unsafe { ETH.ethernet_dma().dmasr().read().rps() } { + match ETH.ethernet_dma().dmasr().read().rps() { // Reset or Stop Receive Command issued Rps::STOPPED => RunningState::Stopped, // Fetching receive transfer descriptor diff --git a/embassy-stm32/src/eth/v1/tx_desc.rs b/embassy-stm32/src/eth/v1/tx_desc.rs index 0e63c5443..1317d20f4 100644 --- a/embassy-stm32/src/eth/v1/tx_desc.rs +++ b/embassy-stm32/src/eth/v1/tx_desc.rs @@ -120,12 +120,9 @@ impl<'a> TDesRing<'a> { } // Register txdescriptor start - // NOTE (unsafe) Used for atomic writes - unsafe { - ETH.ethernet_dma() - .dmatdlar() - .write(|w| w.0 = descriptors.as_ptr() as u32); - } + ETH.ethernet_dma() + .dmatdlar() + .write(|w| w.0 = descriptors.as_ptr() as u32); Self { descriptors, @@ -169,6 +166,6 @@ impl<'a> TDesRing<'a> { self.index = 0 } // Request the DMA engine to poll the latest tx descriptor - unsafe { ETH.ethernet_dma().dmatpdr().modify(|w| w.0 = 1) } + ETH.ethernet_dma().dmatpdr().modify(|w| w.0 = 1) } } diff --git a/embassy-stm32/src/eth/v2/descriptors.rs b/embassy-stm32/src/eth/v2/descriptors.rs index 2426596fb..e9799adf1 100644 --- a/embassy-stm32/src/eth/v2/descriptors.rs +++ b/embassy-stm32/src/eth/v2/descriptors.rs @@ -73,14 +73,10 @@ impl<'a> TDesRing<'a> { // Initialize the pointers in the DMA engine. (There will be a memory barrier later // before the DMA engine is enabled.) - // NOTE (unsafe) Used for atomic writes - unsafe { - let dma = ETH.ethernet_dma(); - - dma.dmactx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); - dma.dmactx_rlr().write(|w| w.set_tdrl((descriptors.len() as u16) - 1)); - dma.dmactx_dtpr().write(|w| w.0 = 0); - } + let dma = ETH.ethernet_dma(); + dma.dmactx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); + dma.dmactx_rlr().write(|w| w.set_tdrl((descriptors.len() as u16) - 1)); + dma.dmactx_dtpr().write(|w| w.0 = 0); Self { descriptors, @@ -129,8 +125,7 @@ impl<'a> TDesRing<'a> { } // signal DMA it can try again. - // NOTE(unsafe) Atomic write - unsafe { ETH.ethernet_dma().dmactx_dtpr().write(|w| w.0 = 0) } + ETH.ethernet_dma().dmactx_dtpr().write(|w| w.0 = 0) } } @@ -199,13 +194,10 @@ impl<'a> RDesRing<'a> { desc.set_ready(buffers[i].0.as_mut_ptr()); } - unsafe { - let dma = ETH.ethernet_dma(); - - dma.dmacrx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); - dma.dmacrx_rlr().write(|w| w.set_rdrl((descriptors.len() as u16) - 1)); - dma.dmacrx_dtpr().write(|w| w.0 = 0); - } + let dma = ETH.ethernet_dma(); + dma.dmacrx_dlar().write(|w| w.0 = descriptors.as_mut_ptr() as u32); + dma.dmacrx_rlr().write(|w| w.set_rdrl((descriptors.len() as u16) - 1)); + dma.dmacrx_dtpr().write(|w| w.0 = 0); Self { descriptors, @@ -254,8 +246,7 @@ impl<'a> RDesRing<'a> { fence(Ordering::Release); // signal DMA it can try again. - // NOTE(unsafe) Atomic write - unsafe { ETH.ethernet_dma().dmacrx_dtpr().write(|w| w.0 = 0) } + ETH.ethernet_dma().dmacrx_dtpr().write(|w| w.0 = 0); // Increment index. self.index += 1; diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 3e45eafd5..600e1d3bc 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -20,18 +20,16 @@ impl interrupt::typelevel::Handler for InterruptHandl WAKER.wake(); // TODO: Check and clear more flags - unsafe { - let dma = ETH.ethernet_dma(); + let dma = ETH.ethernet_dma(); - dma.dmacsr().modify(|w| { - w.set_ti(true); - w.set_ri(true); - w.set_nis(true); - }); - // Delay two peripheral's clock - dma.dmacsr().read(); - dma.dmacsr().read(); - } + dma.dmacsr().modify(|w| { + w.set_ti(true); + w.set_ri(true); + w.set_nis(true); + }); + // Delay two peripheral's clock + dma.dmacsr().read(); + dma.dmacsr().read(); } } @@ -50,7 +48,6 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { macro_rules! config_pins { ($($pin:ident),*) => { - // NOTE(unsafe) Exclusive access to the registers critical_section::with(|_| { $( $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); @@ -80,239 +77,225 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { ) -> Self { into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - unsafe { - // Enable the necessary Clocks - // NOTE(unsafe) We have exclusive access to the registers - #[cfg(not(rcc_h5))] - critical_section::with(|_| { - crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true)); - crate::pac::RCC.ahb1enr().modify(|w| { - w.set_eth1macen(true); - w.set_eth1txen(true); - w.set_eth1rxen(true); - }); - - // RMII - crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); + // Enable the necessary Clocks + #[cfg(not(rcc_h5))] + critical_section::with(|_| { + crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true)); + crate::pac::RCC.ahb1enr().modify(|w| { + w.set_eth1macen(true); + w.set_eth1txen(true); + w.set_eth1rxen(true); }); - #[cfg(rcc_h5)] - critical_section::with(|_| { - crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true)); + // RMII + crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); + }); - crate::pac::RCC.ahb1enr().modify(|w| { - w.set_ethen(true); - w.set_ethtxen(true); - w.set_ethrxen(true); - }); + #[cfg(rcc_h5)] + critical_section::with(|_| { + crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true)); - // RMII - crate::pac::SBS - .pmcr() - .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4)); + crate::pac::RCC.ahb1enr().modify(|w| { + w.set_ethen(true); + w.set_ethtxen(true); + w.set_ethrxen(true); }); - config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); + // RMII + crate::pac::SBS + .pmcr() + .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4)); + }); - // NOTE(unsafe) We have exclusive access to the registers - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); + config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - // Reset and wait - dma.dmamr().modify(|w| w.set_swr(true)); - while dma.dmamr().read().swr() {} + let dma = ETH.ethernet_dma(); + let mac = ETH.ethernet_mac(); + let mtl = ETH.ethernet_mtl(); - mac.maccr().modify(|w| { - w.set_ipg(0b000); // 96 bit times - w.set_acs(true); - w.set_fes(true); - w.set_dm(true); - // TODO: Carrier sense ? ECRSFD - }); + // Reset and wait + dma.dmamr().modify(|w| w.set_swr(true)); + while dma.dmamr().read().swr() {} - // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, - // so the LR write must happen after the HR write. - mac.maca0hr() - .modify(|w| w.set_addrhi(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); - mac.maca0lr().write(|w| { - w.set_addrlo( - u32::from(mac_addr[0]) - | (u32::from(mac_addr[1]) << 8) - | (u32::from(mac_addr[2]) << 16) - | (u32::from(mac_addr[3]) << 24), - ) - }); + mac.maccr().modify(|w| { + w.set_ipg(0b000); // 96 bit times + w.set_acs(true); + w.set_fes(true); + w.set_dm(true); + // TODO: Carrier sense ? ECRSFD + }); - mac.macqtx_fcr().modify(|w| w.set_pt(0x100)); + // Note: Writing to LR triggers synchronisation of both LR and HR into the MAC core, + // so the LR write must happen after the HR write. + mac.maca0hr() + .modify(|w| w.set_addrhi(u16::from(mac_addr[4]) | (u16::from(mac_addr[5]) << 8))); + mac.maca0lr().write(|w| { + w.set_addrlo( + u32::from(mac_addr[0]) + | (u32::from(mac_addr[1]) << 8) + | (u32::from(mac_addr[2]) << 16) + | (u32::from(mac_addr[3]) << 24), + ) + }); - // disable all MMC RX interrupts - mac.mmc_rx_interrupt_mask().write(|w| { - w.set_rxcrcerpim(true); - w.set_rxalgnerpim(true); - w.set_rxucgpim(true); - w.set_rxlpiuscim(true); - w.set_rxlpitrcim(true) - }); + mac.macqtx_fcr().modify(|w| w.set_pt(0x100)); - // disable all MMC TX interrupts - mac.mmc_tx_interrupt_mask().write(|w| { - w.set_txscolgpim(true); - w.set_txmcolgpim(true); - w.set_txgpktim(true); - w.set_txlpiuscim(true); - w.set_txlpitrcim(true); - }); + // disable all MMC RX interrupts + mac.mmc_rx_interrupt_mask().write(|w| { + w.set_rxcrcerpim(true); + w.set_rxalgnerpim(true); + w.set_rxucgpim(true); + w.set_rxlpiuscim(true); + w.set_rxlpitrcim(true) + }); - mtl.mtlrx_qomr().modify(|w| w.set_rsf(true)); - mtl.mtltx_qomr().modify(|w| w.set_tsf(true)); + // disable all MMC TX interrupts + mac.mmc_tx_interrupt_mask().write(|w| { + w.set_txscolgpim(true); + w.set_txmcolgpim(true); + w.set_txgpktim(true); + w.set_txlpiuscim(true); + w.set_txlpitrcim(true); + }); - dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ? - dma.dmacrx_cr().modify(|w| { - w.set_rxpbl(1); // 32 ? - w.set_rbsz(MTU as u16); - }); + mtl.mtlrx_qomr().modify(|w| w.set_rsf(true)); + mtl.mtltx_qomr().modify(|w| w.set_tsf(true)); - // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called - let hclk = crate::rcc::get_freqs().ahb1; - let hclk_mhz = hclk.0 / 1_000_000; + dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ? + dma.dmacrx_cr().modify(|w| { + w.set_rxpbl(1); // 32 ? + w.set_rbsz(MTU as u16); + }); - // Set the MDC clock frequency in the range 1MHz - 2.5MHz - let clock_range = match hclk_mhz { - 0..=34 => 2, // Divide by 16 - 35..=59 => 3, // Divide by 26 - 60..=99 => 0, // Divide by 42 - 100..=149 => 1, // Divide by 62 - 150..=249 => 4, // Divide by 102 - 250..=310 => 5, // Divide by 124 - _ => { - panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") - } - }; + // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called + let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; + let hclk_mhz = hclk.0 / 1_000_000; - let pins = [ - ref_clk.map_into(), - mdio.map_into(), - mdc.map_into(), - crs.map_into(), - rx_d0.map_into(), - rx_d1.map_into(), - tx_d0.map_into(), - tx_d1.map_into(), - tx_en.map_into(), - ]; + // Set the MDC clock frequency in the range 1MHz - 2.5MHz + let clock_range = match hclk_mhz { + 0..=34 => 2, // Divide by 16 + 35..=59 => 3, // Divide by 26 + 60..=99 => 0, // Divide by 42 + 100..=149 => 1, // Divide by 62 + 150..=249 => 4, // Divide by 102 + 250..=310 => 5, // Divide by 124 + _ => { + panic!("HCLK results in MDC clock > 2.5MHz even for the highest CSR clock divider") + } + }; - let mut this = Self { - _peri: peri, - tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), - rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), - pins, - _phy: phy, - clock_range, - phy_addr, - mac_addr, - }; + let pins = [ + ref_clk.map_into(), + mdio.map_into(), + mdc.map_into(), + crs.map_into(), + rx_d0.map_into(), + rx_d1.map_into(), + tx_d0.map_into(), + tx_d1.map_into(), + tx_en.map_into(), + ]; - fence(Ordering::SeqCst); + let mut this = Self { + _peri: peri, + tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), + rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), + pins, + _phy: phy, + clock_range, + phy_addr, + mac_addr, + }; - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); - let dma = ETH.ethernet_dma(); + fence(Ordering::SeqCst); - mac.maccr().modify(|w| { - w.set_re(true); - w.set_te(true); - }); - mtl.mtltx_qomr().modify(|w| w.set_ftq(true)); + let mac = ETH.ethernet_mac(); + let mtl = ETH.ethernet_mtl(); + let dma = ETH.ethernet_dma(); - dma.dmactx_cr().modify(|w| w.set_st(true)); - dma.dmacrx_cr().modify(|w| w.set_sr(true)); + mac.maccr().modify(|w| { + w.set_re(true); + w.set_te(true); + }); + mtl.mtltx_qomr().modify(|w| w.set_ftq(true)); - // Enable interrupts - dma.dmacier().modify(|w| { - w.set_nie(true); - w.set_rie(true); - w.set_tie(true); - }); + dma.dmactx_cr().modify(|w| w.set_st(true)); + dma.dmacrx_cr().modify(|w| w.set_sr(true)); - P::phy_reset(&mut this); - P::phy_init(&mut this); + // Enable interrupts + dma.dmacier().modify(|w| { + w.set_nie(true); + w.set_rie(true); + w.set_tie(true); + }); - interrupt::ETH.unpend(); - interrupt::ETH.enable(); + P::phy_reset(&mut this); + P::phy_init(&mut this); - this - } + interrupt::ETH.unpend(); + unsafe { interrupt::ETH.enable() }; + + this } } unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { fn smi_read(&mut self, reg: u8) -> u16 { - // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` - unsafe { - let mac = ETH.ethernet_mac(); + let mac = ETH.ethernet_mac(); - mac.macmdioar().modify(|w| { - w.set_pa(self.phy_addr); - w.set_rda(reg); - w.set_goc(0b11); // read - w.set_cr(self.clock_range); - w.set_mb(true); - }); - while mac.macmdioar().read().mb() {} - mac.macmdiodr().read().md() - } + mac.macmdioar().modify(|w| { + w.set_pa(self.phy_addr); + w.set_rda(reg); + w.set_goc(0b11); // read + w.set_cr(self.clock_range); + w.set_mb(true); + }); + while mac.macmdioar().read().mb() {} + mac.macmdiodr().read().md() } fn smi_write(&mut self, reg: u8, val: u16) { - // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` - unsafe { - let mac = ETH.ethernet_mac(); + let mac = ETH.ethernet_mac(); - mac.macmdiodr().write(|w| w.set_md(val)); - mac.macmdioar().modify(|w| { - w.set_pa(self.phy_addr); - w.set_rda(reg); - w.set_goc(0b01); // write - w.set_cr(self.clock_range); - w.set_mb(true); - }); - while mac.macmdioar().read().mb() {} - } + mac.macmdiodr().write(|w| w.set_md(val)); + mac.macmdioar().modify(|w| { + w.set_pa(self.phy_addr); + w.set_rda(reg); + w.set_goc(0b01); // write + w.set_cr(self.clock_range); + w.set_mb(true); + }); + while mac.macmdioar().read().mb() {} } } impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { fn drop(&mut self) { - // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers - unsafe { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); + let dma = ETH.ethernet_dma(); + let mac = ETH.ethernet_mac(); + let mtl = ETH.ethernet_mtl(); - // Disable the TX DMA and wait for any previous transmissions to be completed - dma.dmactx_cr().modify(|w| w.set_st(false)); - while { - let txqueue = mtl.mtltx_qdr().read(); - txqueue.trcsts() == 0b01 || txqueue.txqsts() - } {} + // Disable the TX DMA and wait for any previous transmissions to be completed + dma.dmactx_cr().modify(|w| w.set_st(false)); + while { + let txqueue = mtl.mtltx_qdr().read(); + txqueue.trcsts() == 0b01 || txqueue.txqsts() + } {} - // Disable MAC transmitter and receiver - mac.maccr().modify(|w| { - w.set_re(false); - w.set_te(false); - }); + // Disable MAC transmitter and receiver + mac.maccr().modify(|w| { + w.set_re(false); + w.set_te(false); + }); - // Wait for previous receiver transfers to be completed and then disable the RX DMA - while { - let rxqueue = mtl.mtlrx_qdr().read(); - rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0 - } {} - dma.dmacrx_cr().modify(|w| w.set_sr(false)); - } + // Wait for previous receiver transfers to be completed and then disable the RX DMA + while { + let rxqueue = mtl.mtlrx_qdr().read(); + rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0 + } {} + dma.dmacrx_cr().modify(|w| w.set_sr(false)); - // NOTE(unsafe) Exclusive access to the regs - critical_section::with(|_| unsafe { + critical_section::with(|_| { for pin in self.pins.iter_mut() { pin.set_as_disconnected(); } diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 0631ae473..3ff92c9e6 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -206,7 +206,7 @@ struct ExtiInputFuture<'a> { impl<'a> ExtiInputFuture<'a> { fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let pin = pin as usize; exticr_regs().exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); EXTI.rtsr(0).modify(|w| w.set_line(pin, rising)); @@ -233,7 +233,7 @@ impl<'a> ExtiInputFuture<'a> { impl<'a> Drop for ExtiInputFuture<'a> { fn drop(&mut self) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let pin = self.pin as _; cpu_regs().imr(0).modify(|w| w.set_line(pin, false)); }); @@ -246,7 +246,7 @@ impl<'a> Future for ExtiInputFuture<'a> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { EXTI_WAKERS[self.pin as usize].register(cx.waker()); - let imr = unsafe { cpu_regs().imr(0).read() }; + let imr = cpu_regs().imr(0).read(); if !imr.line(self.pin as _) { Poll::Ready(()) } else { diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 5e1fc696f..242d99278 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -192,7 +192,7 @@ impl FlashSector { #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub(crate) fn is_default_layout() -> bool { - unsafe { !pac::FLASH.optcr().read().db1m() } + !pac::FLASH.optcr().read().db1m() } #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] @@ -336,7 +336,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E ret } -pub(crate) unsafe fn clear_all_err() { +pub(crate) fn clear_all_err() { pac::FLASH.sr().write(|w| { w.set_pgserr(true); w.set_pgperr(true); @@ -345,7 +345,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { +pub(crate) async fn wait_ready() -> Result<(), Error> { use core::task::Poll; use futures::future::poll_fn; @@ -391,10 +391,10 @@ fn save_data_cache_state() { let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; if dual_bank { // Disable data cache during write/erase if there are two banks, see errata 2.2.12 - let dcen = unsafe { pac::FLASH.acr().read().dcen() }; + let dcen = pac::FLASH.acr().read().dcen(); DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed); if dcen { - unsafe { pac::FLASH.acr().modify(|w| w.set_dcen(false)) }; + pac::FLASH.acr().modify(|w| w.set_dcen(false)); } } } @@ -405,12 +405,10 @@ fn restore_data_cache_state() { // Restore data cache if it was enabled let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed); if dcen { - unsafe { - // Reset data cache before we enable it again - pac::FLASH.acr().modify(|w| w.set_dcrst(true)); - pac::FLASH.acr().modify(|w| w.set_dcrst(false)); - pac::FLASH.acr().modify(|w| w.set_dcen(true)) - }; + // Reset data cache before we enable it again + pac::FLASH.acr().modify(|w| w.set_dcrst(true)); + pac::FLASH.acr().modify(|w| w.set_dcrst(false)); + pac::FLASH.acr().modify(|w| w.set_dcen(true)) } } } @@ -445,7 +443,7 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) { feature = "stm32f439vi", feature = "stm32f439zi", ))] - if second_bank_read && unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { + if second_bank_read && pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() { panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11"); } @@ -479,11 +477,9 @@ fn pa12_is_output_pull_low() -> bool { use pac::gpio::vals; use pac::GPIOA; const PIN: usize = 12; - unsafe { - GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT - && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN - && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW - } + GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT + && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN + && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW } #[cfg(test)] diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index b9129cb51..a4f3b9686 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -16,7 +16,7 @@ unsafe impl<'d, T> stm32_fmc::FmcPeripheral for Fmc<'d, T> where T: Instance, { - const REGISTERS: *const () = T::REGS.0 as *const _; + const REGISTERS: *const () = T::REGS.as_ptr() as *const _; fn enable(&mut self) { ::enable(); @@ -28,9 +28,7 @@ where // fsmc v1, v2 and v3 does not have the fmcen bit // This is a "not" because it is expected that all future versions have this bit #[cfg(not(any(fmc_v1x3, fmc_v2x1, fsmc_v1x0, fsmc_v1x3, fsmc_v2x3, fsmc_v3x1)))] - unsafe { - T::REGS.bcr1().modify(|r| r.set_fmcen(true)) - }; + T::REGS.bcr1().modify(|r| r.set_fmcen(true)); } fn source_clock_hz(&self) -> u32 { @@ -67,7 +65,7 @@ macro_rules! fmc_sdram_constructor { chip: CHIP ) -> stm32_fmc::Sdram, CHIP> { - critical_section::with(|_| unsafe { + critical_section::with(|_| { config_pins!( $($addr_pin_name),*, $($ba_pin_name),*, diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 7a066a4ca..af3a8eaca 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -46,7 +46,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// Put the pin into input mode. #[inline] pub fn set_as_input(&mut self, pull: Pull) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let r = self.pin.block(); let n = self.pin.pin() as usize; #[cfg(gpio_v1)] @@ -84,7 +84,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// at a specific level, call `set_high`/`set_low` on the pin first. #[inline] pub fn set_as_output(&mut self, speed: Speed) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let r = self.pin.block(); let n = self.pin.pin() as usize; #[cfg(gpio_v1)] @@ -116,7 +116,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// at a specific level, call `set_high`/`set_low` on the pin first. #[inline] pub fn set_as_input_output(&mut self, speed: Speed, pull: Pull) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let r = self.pin.block(); let n = self.pin.pin() as usize; #[cfg(gpio_v1)] @@ -147,7 +147,7 @@ impl<'d, T: Pin> Flex<'d, T> { #[inline] pub fn is_low(&self) -> bool { - let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) }; + let state = self.pin.block().idr().read().idr(self.pin.pin() as _); state == vals::Idr::LOW } @@ -164,7 +164,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// Is the output pin set as low? #[inline] pub fn is_set_low(&self) -> bool { - let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) }; + let state = self.pin.block().odr().read().odr(self.pin.pin() as _); state == vals::Odr::LOW } @@ -207,7 +207,7 @@ impl<'d, T: Pin> Flex<'d, T> { impl<'d, T: Pin> Drop for Flex<'d, T> { #[inline] fn drop(&mut self) { - critical_section::with(|_| unsafe { + critical_section::with(|_| { let r = self.pin.block(); let n = self.pin.pin() as usize; #[cfg(gpio_v1)] @@ -534,29 +534,25 @@ pub(crate) mod sealed { /// Set the output as high. #[inline] fn set_high(&self) { - unsafe { - let n = self._pin() as _; - self.block().bsrr().write(|w| w.set_bs(n, true)); - } + let n = self._pin() as _; + self.block().bsrr().write(|w| w.set_bs(n, true)); } /// Set the output as low. #[inline] fn set_low(&self) { - unsafe { - let n = self._pin() as _; - self.block().bsrr().write(|w| w.set_br(n, true)); - } + let n = self._pin() as _; + self.block().bsrr().write(|w| w.set_br(n, true)); } #[inline] - unsafe fn set_as_af(&self, af_num: u8, af_type: AFType) { + fn set_as_af(&self, af_num: u8, af_type: AFType) { self.set_as_af_pull(af_num, af_type, Pull::None); } #[cfg(gpio_v1)] #[inline] - unsafe fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { + fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { // F1 uses the AFIO register for remapping. // For now, this is not implemented, so af_num is ignored // _af_num should be zero here, since it is not set by stm32-data @@ -599,7 +595,7 @@ pub(crate) mod sealed { #[cfg(gpio_v2)] #[inline] - unsafe fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { + fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { let pin = self._pin() as usize; let block = self.block(); block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); @@ -614,7 +610,7 @@ pub(crate) mod sealed { } #[inline] - unsafe fn set_as_analog(&self) { + fn set_as_analog(&self) { let pin = self._pin() as usize; let block = self.block(); #[cfg(gpio_v1)] @@ -635,12 +631,12 @@ pub(crate) mod sealed { /// This is currently the same as set_as_analog but is semantically different really. /// Drivers should set_as_disconnected pins when dropped. #[inline] - unsafe fn set_as_disconnected(&self) { + fn set_as_disconnected(&self) { self.set_as_analog(); } #[inline] - unsafe fn set_speed(&self, speed: Speed) { + fn set_speed(&self, speed: Speed) { let pin = self._pin() as usize; #[cfg(gpio_v1)] diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index e04038886..aa485cd86 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -68,53 +68,45 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { T::enable(); T::reset(); - unsafe { - scl.set_as_af_pull( - scl.af_num(), - AFType::OutputOpenDrain, - match config.scl_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - sda.set_as_af_pull( - sda.af_num(), - AFType::OutputOpenDrain, - match config.sda_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - } + scl.set_as_af_pull( + scl.af_num(), + AFType::OutputOpenDrain, + match config.scl_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); + sda.set_as_af_pull( + sda.af_num(), + AFType::OutputOpenDrain, + match config.sda_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_pe(false); - //reg.set_anfoff(false); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_pe(false); + //reg.set_anfoff(false); + }); let timings = Timings::new(T::frequency(), freq.into()); - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_freq(timings.freq); - }); - T::regs().ccr().modify(|reg| { - reg.set_f_s(timings.mode.f_s()); - reg.set_duty(timings.duty.duty()); - reg.set_ccr(timings.ccr); - }); - T::regs().trise().modify(|reg| { - reg.set_trise(timings.trise); - }); - } + T::regs().cr2().modify(|reg| { + reg.set_freq(timings.freq); + }); + T::regs().ccr().modify(|reg| { + reg.set_f_s(timings.mode.f_s()); + reg.set_duty(timings.duty.duty()); + reg.set_ccr(timings.ccr); + }); + T::regs().trise().modify(|reg| { + reg.set_trise(timings.trise); + }); - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_pe(true); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_pe(true); + }); Self { phantom: PhantomData, @@ -123,7 +115,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } } - unsafe fn check_and_clear_error_flags(&self) -> Result { + fn check_and_clear_error_flags(&self) -> Result { // Note that flags should only be cleared once they have been registered. If flags are // cleared otherwise, there may be an inherent race condition and flags may be missed. let sr1 = T::regs().sr1().read(); @@ -162,7 +154,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(sr1) } - unsafe fn write_bytes( + fn write_bytes( &mut self, addr: u8, bytes: &[u8], @@ -211,7 +203,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } - unsafe fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { + fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { // Wait until we're ready for sending while { // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. @@ -234,7 +226,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } - unsafe fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result { + fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result { while { // Check for any potential error conditions. self.check_and_clear_error_flags()?; @@ -256,56 +248,52 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { ) -> Result<(), Error> { if let Some((last, buffer)) = buffer.split_last_mut() { // Send a START condition and set ACK bit - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_start(true); - reg.set_ack(true); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_start(true); + reg.set_ack(true); + }); // Wait until START condition was generated - while unsafe { !self.check_and_clear_error_flags()?.start() } { + while !self.check_and_clear_error_flags()?.start() { check_timeout()?; } // Also wait until signalled we're master and everything is waiting for us while { - let sr2 = unsafe { T::regs().sr2().read() }; + let sr2 = T::regs().sr2().read(); !sr2.msl() && !sr2.busy() } { check_timeout()?; } // Set up current address, we're trying to talk to - unsafe { T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)) } + T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)); // Wait until address was sent // Wait for the address to be acknowledged - while unsafe { !self.check_and_clear_error_flags()?.addr() } { + while !self.check_and_clear_error_flags()?.addr() { check_timeout()?; } // Clear condition by reading SR2 - let _ = unsafe { T::regs().sr2().read() }; + let _ = T::regs().sr2().read(); // Receive bytes into buffer for c in buffer { - *c = unsafe { self.recv_byte(&check_timeout)? }; + *c = self.recv_byte(&check_timeout)?; } // Prepare to send NACK then STOP after next byte - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_ack(false); - reg.set_stop(true); - }) - } + T::regs().cr1().modify(|reg| { + reg.set_ack(false); + reg.set_stop(true); + }); // Receive last byte - *last = unsafe { self.recv_byte(&check_timeout)? }; + *last = self.recv_byte(&check_timeout)?; // Wait for the STOP to be sent. - while unsafe { T::regs().cr1().read().stop() } { + while T::regs().cr1().read().stop() { check_timeout()?; } @@ -326,15 +314,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { write: &[u8], check_timeout: impl Fn() -> Result<(), Error>, ) -> Result<(), Error> { - unsafe { - self.write_bytes(addr, write, &check_timeout)?; - // Send a STOP condition - T::regs().cr1().modify(|reg| reg.set_stop(true)); - // Wait for STOP condition to transmit. - while T::regs().cr1().read().stop() { - check_timeout()?; - } - }; + self.write_bytes(addr, write, &check_timeout)?; + // Send a STOP condition + T::regs().cr1().modify(|reg| reg.set_stop(true)); + // Wait for STOP condition to transmit. + while T::regs().cr1().read().stop() { + check_timeout()?; + } // Fallthrough is success Ok(()) @@ -351,7 +337,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { read: &mut [u8], check_timeout: impl Fn() -> Result<(), Error>, ) -> Result<(), Error> { - unsafe { self.write_bytes(addr, write, &check_timeout)? }; + self.write_bytes(addr, write, &check_timeout)?; self.blocking_read_timeout(addr, read, &check_timeout)?; Ok(()) @@ -478,8 +464,6 @@ impl Timings { assert!(freq >= 2 && freq <= 50); // Configure bus frequency into I2C peripheral - //self.i2c.cr2.write(|w| unsafe { w.freq().bits(freq as u8) }); - let trise = if speed <= 100_000 { freq + 1 } else { @@ -539,18 +523,16 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> { type Config = Hertz; fn set_config(&mut self, config: &Self::Config) { let timings = Timings::new(T::frequency(), *config); - unsafe { - T::regs().cr2().modify(|reg| { - reg.set_freq(timings.freq); - }); - T::regs().ccr().modify(|reg| { - reg.set_f_s(timings.mode.f_s()); - reg.set_duty(timings.duty.duty()); - reg.set_ccr(timings.ccr); - }); - T::regs().trise().modify(|reg| { - reg.set_trise(timings.trise); - }); - } + T::regs().cr2().modify(|reg| { + reg.set_freq(timings.freq); + }); + T::regs().ccr().modify(|reg| { + reg.set_f_s(timings.mode.f_s()); + reg.set_duty(timings.duty.duty()); + reg.set_ccr(timings.ccr); + }); + T::regs().trise().modify(|reg| { + reg.set_trise(timings.trise); + }); } } diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 1aaf2b46b..1f036d55c 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -89,49 +89,41 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { T::enable(); T::reset(); - unsafe { - scl.set_as_af_pull( - scl.af_num(), - AFType::OutputOpenDrain, - match config.scl_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - sda.set_as_af_pull( - sda.af_num(), - AFType::OutputOpenDrain, - match config.sda_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - } + scl.set_as_af_pull( + scl.af_num(), + AFType::OutputOpenDrain, + match config.scl_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); + sda.set_as_af_pull( + sda.af_num(), + AFType::OutputOpenDrain, + match config.sda_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_pe(false); - reg.set_anfoff(false); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_pe(false); + reg.set_anfoff(false); + }); let timings = Timings::new(T::frequency(), freq.into()); - unsafe { - T::regs().timingr().write(|reg| { - reg.set_presc(timings.prescale); - reg.set_scll(timings.scll); - reg.set_sclh(timings.sclh); - reg.set_sdadel(timings.sdadel); - reg.set_scldel(timings.scldel); - }); - } + T::regs().timingr().write(|reg| { + reg.set_presc(timings.prescale); + reg.set_scll(timings.scll); + reg.set_sclh(timings.sclh); + reg.set_sdadel(timings.sdadel); + reg.set_scldel(timings.scldel); + }); - unsafe { - T::regs().cr1().modify(|reg| { - reg.set_pe(true); - }); - } + T::regs().cr1().modify(|reg| { + reg.set_pe(true); + }); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; @@ -144,12 +136,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } fn master_stop(&mut self) { - unsafe { - T::regs().cr2().write(|w| w.set_stop(true)); - } + T::regs().cr2().write(|w| w.set_stop(true)); } - unsafe fn master_read( + fn master_read( address: u8, length: usize, stop: Stop, @@ -191,7 +181,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } - unsafe fn master_write( + fn master_write( address: u8, length: usize, stop: Stop, @@ -229,7 +219,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(()) } - unsafe fn master_continue( + fn master_continue( length: usize, reload: bool, check_timeout: impl Fn() -> Result<(), Error>, @@ -259,13 +249,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { //$i2c.txdr.write(|w| w.txdata().bits(0)); //} - unsafe { - if T::regs().isr().read().txis() { - T::regs().txdr().write(|w| w.set_txdata(0)); - } - if !T::regs().isr().read().txe() { - T::regs().isr().modify(|w| w.set_txe(true)) - } + if T::regs().isr().read().txis() { + T::regs().txdr().write(|w| w.set_txdata(0)); + } + if !T::regs().isr().read().txe() { + T::regs().isr().modify(|w| w.set_txe(true)) } // If TXDR is not flagged as empty, write 1 to flush it @@ -276,21 +264,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { loop { - unsafe { - let isr = T::regs().isr().read(); - if isr.txe() { - return Ok(()); - } else if isr.berr() { - T::regs().icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - T::regs().icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - T::regs().icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); - } + let isr = T::regs().isr().read(); + if isr.txe() { + return Ok(()); + } else if isr.berr() { + T::regs().icr().write(|reg| reg.set_berrcf(true)); + return Err(Error::Bus); + } else if isr.arlo() { + T::regs().icr().write(|reg| reg.set_arlocf(true)); + return Err(Error::Arbitration); + } else if isr.nackf() { + T::regs().icr().write(|reg| reg.set_nackcf(true)); + self.flush_txdr(); + return Err(Error::Nack); } check_timeout()?; @@ -299,21 +285,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { loop { - unsafe { - let isr = T::regs().isr().read(); - if isr.rxne() { - return Ok(()); - } else if isr.berr() { - T::regs().icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - T::regs().icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - T::regs().icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); - } + let isr = T::regs().isr().read(); + if isr.rxne() { + return Ok(()); + } else if isr.berr() { + T::regs().icr().write(|reg| reg.set_berrcf(true)); + return Err(Error::Bus); + } else if isr.arlo() { + T::regs().icr().write(|reg| reg.set_arlocf(true)); + return Err(Error::Arbitration); + } else if isr.nackf() { + T::regs().icr().write(|reg| reg.set_nackcf(true)); + self.flush_txdr(); + return Err(Error::Nack); } check_timeout()?; @@ -322,21 +306,19 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { loop { - unsafe { - let isr = T::regs().isr().read(); - if isr.tc() { - return Ok(()); - } else if isr.berr() { - T::regs().icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - T::regs().icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - T::regs().icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); - } + let isr = T::regs().isr().read(); + if isr.tc() { + return Ok(()); + } else if isr.berr() { + T::regs().icr().write(|reg| reg.set_berrcf(true)); + return Err(Error::Bus); + } else if isr.arlo() { + T::regs().icr().write(|reg| reg.set_arlocf(true)); + return Err(Error::Arbitration); + } else if isr.nackf() { + T::regs().icr().write(|reg| reg.set_nackcf(true)); + self.flush_txdr(); + return Err(Error::Nack); } check_timeout()?; @@ -358,32 +340,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { }; let last_chunk_idx = total_chunks.saturating_sub(1); - unsafe { - Self::master_read( - address, - read.len().min(255), - Stop::Automatic, - last_chunk_idx != 0, - restart, - &check_timeout, - )?; - } + Self::master_read( + address, + read.len().min(255), + Stop::Automatic, + last_chunk_idx != 0, + restart, + &check_timeout, + )?; for (number, chunk) in read.chunks_mut(255).enumerate() { if number != 0 { - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; - } + Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; } for byte in chunk { // Wait until we have received something self.wait_rxne(&check_timeout)?; - unsafe { - *byte = T::regs().rxdr().read().rxdata(); - } + *byte = T::regs().rxdr().read().rxdata(); } } Ok(()) @@ -407,23 +382,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // I2C start // // ST SAD+W - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_write( - address, - write.len().min(255), - Stop::Software, - last_chunk_idx != 0, - &check_timeout, - )?; - } + Self::master_write( + address, + write.len().min(255), + Stop::Software, + last_chunk_idx != 0, + &check_timeout, + )?; for (number, chunk) in write.chunks(255).enumerate() { if number != 0 { - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; - } + Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; } for byte in chunk { @@ -432,9 +401,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // through) self.wait_txe(&check_timeout)?; - unsafe { - T::regs().txdr().write(|w| w.set_txdata(*byte)); - } + T::regs().txdr().write(|w| w.set_txdata(*byte)); } } // Wait until the write finishes @@ -467,7 +434,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { w.set_tcie(true); } }); - let dst = regs.txdr().ptr() as *mut u8; + let dst = regs.txdr().as_ptr() as *mut u8; let ch = &mut self.tx_dma; let request = ch.request(); @@ -479,37 +446,30 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let on_drop = OnDrop::new(|| { let regs = T::regs(); - unsafe { - regs.cr1().modify(|w| { - if last_slice { - w.set_txdmaen(false); - } - w.set_tcie(false); - }) - } + regs.cr1().modify(|w| { + if last_slice { + w.set_txdmaen(false); + } + w.set_tcie(false); + }) }); poll_fn(|cx| { state.waker.register(cx.waker()); - let isr = unsafe { T::regs().isr().read() }; + let isr = T::regs().isr().read(); if remaining_len == total_len { - // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers if first_slice { - unsafe { - Self::master_write( - address, - total_len.min(255), - Stop::Software, - (total_len > 255) || !last_slice, - &check_timeout, - )?; - } + Self::master_write( + address, + total_len.min(255), + Stop::Software, + (total_len > 255) || !last_slice, + &check_timeout, + )?; } else { - unsafe { - Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; - T::regs().cr1().modify(|w| w.set_tcie(true)); - } + Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; + T::regs().cr1().modify(|w| w.set_tcie(true)); } } else if !(isr.tcr() || isr.tc()) { // poll_fn was woken without an interrupt present @@ -519,13 +479,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } else { let last_piece = (remaining_len <= 255) && last_slice; - // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers - unsafe { - if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { - return Poll::Ready(Err(e)); - } - T::regs().cr1().modify(|w| w.set_tcie(true)); + if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { + return Poll::Ready(Err(e)); } + T::regs().cr1().modify(|w| w.set_tcie(true)); } remaining_len = remaining_len.saturating_sub(255); @@ -564,7 +521,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { w.set_rxdmaen(true); w.set_tcie(true); }); - let src = regs.rxdr().ptr() as *mut u8; + let src = regs.rxdr().as_ptr() as *mut u8; let ch = &mut self.rx_dma; let request = ch.request(); @@ -576,30 +533,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let on_drop = OnDrop::new(|| { let regs = T::regs(); - unsafe { - regs.cr1().modify(|w| { - w.set_rxdmaen(false); - w.set_tcie(false); - }) - } + regs.cr1().modify(|w| { + w.set_rxdmaen(false); + w.set_tcie(false); + }) }); poll_fn(|cx| { state.waker.register(cx.waker()); - let isr = unsafe { T::regs().isr().read() }; + let isr = T::regs().isr().read(); if remaining_len == total_len { - // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers - unsafe { - Self::master_read( - address, - total_len.min(255), - Stop::Software, - total_len > 255, - restart, - &check_timeout, - )?; - } + Self::master_read( + address, + total_len.min(255), + Stop::Software, + total_len > 255, + restart, + &check_timeout, + )?; } else if !(isr.tcr() || isr.tc()) { // poll_fn was woken without an interrupt present return Poll::Pending; @@ -608,13 +560,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } else { let last_piece = remaining_len <= 255; - // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers - unsafe { - if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { - return Poll::Ready(Err(e)); - } - T::regs().cr1().modify(|w| w.set_tcie(true)); + if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { + return Poll::Ready(Err(e)); } + T::regs().cr1().modify(|w| w.set_tcie(true)); } remaining_len = remaining_len.saturating_sub(255); @@ -758,16 +707,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let first_length = write[0].len(); let last_slice_index = write.len() - 1; - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_write( - address, - first_length.min(255), - Stop::Software, - (first_length > 255) || (last_slice_index != 0), - &check_timeout, - )?; - } + Self::master_write( + address, + first_length.min(255), + Stop::Software, + (first_length > 255) || (last_slice_index != 0), + &check_timeout, + )?; for (idx, slice) in write.iter().enumerate() { let slice_len = slice.len(); @@ -780,26 +726,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let last_chunk_idx = total_chunks.saturating_sub(1); if idx != 0 { - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_continue( - slice_len.min(255), - (idx != last_slice_index) || (slice_len > 255), - &check_timeout, - )?; - } + Self::master_continue( + slice_len.min(255), + (idx != last_slice_index) || (slice_len > 255), + &check_timeout, + )?; } for (number, chunk) in slice.chunks(255).enumerate() { if number != 0 { - // NOTE(unsafe) We have &mut self - unsafe { - Self::master_continue( - chunk.len(), - (number != last_chunk_idx) || (idx != last_slice_index), - &check_timeout, - )?; - } + Self::master_continue( + chunk.len(), + (number != last_chunk_idx) || (idx != last_slice_index), + &check_timeout, + )?; } for byte in chunk { @@ -810,9 +750,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // Put byte on the wire //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); - unsafe { - T::regs().txdr().write(|w| w.set_txdata(*byte)); - } + T::regs().txdr().write(|w| w.set_txdata(*byte)); } } } @@ -1061,14 +999,12 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> { type Config = Hertz; fn set_config(&mut self, config: &Self::Config) { let timings = Timings::new(T::frequency(), *config); - unsafe { - T::regs().timingr().write(|reg| { - reg.set_presc(timings.prescale); - reg.set_scll(timings.scll); - reg.set_sclh(timings.sclh); - reg.set_sdadel(timings.sdadel); - reg.set_scldel(timings.scldel); - }); - } + T::regs().timingr().write(|reg| { + reg.set_presc(timings.prescale); + reg.set_scll(timings.scll); + reg.set_sclh(timings.sclh); + reg.set_sdadel(timings.sdadel); + reg.set_scldel(timings.scldel); + }); } } diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 2bb199f68..62dda69b4 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -153,19 +153,17 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { ) -> Self { into_ref!(sd, ws, ck, mck); - unsafe { - sd.set_as_af(sd.af_num(), AFType::OutputPushPull); - sd.set_speed(crate::gpio::Speed::VeryHigh); + sd.set_as_af(sd.af_num(), AFType::OutputPushPull); + sd.set_speed(crate::gpio::Speed::VeryHigh); - ws.set_as_af(ws.af_num(), AFType::OutputPushPull); - ws.set_speed(crate::gpio::Speed::VeryHigh); + ws.set_as_af(ws.af_num(), AFType::OutputPushPull); + ws.set_speed(crate::gpio::Speed::VeryHigh); - ck.set_as_af(ck.af_num(), AFType::OutputPushPull); - ck.set_speed(crate::gpio::Speed::VeryHigh); + ck.set_as_af(ck.af_num(), AFType::OutputPushPull); + ck.set_speed(crate::gpio::Speed::VeryHigh); - mck.set_as_af(mck.af_num(), AFType::OutputPushPull); - mck.set_speed(crate::gpio::Speed::VeryHigh); - } + mck.set_as_af(mck.af_num(), AFType::OutputPushPull); + mck.set_speed(crate::gpio::Speed::VeryHigh); let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default()); @@ -178,7 +176,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format); #[cfg(any(spi_v1, spi_f1))] - unsafe { + { use stm32_metapac::spi::vals::{I2scfg, Odd}; // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR register to define the serial clock baud @@ -232,10 +230,6 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { w.set_i2se(true) }); } - #[cfg(spi_v2)] - unsafe {} - #[cfg(any(spi_v3, spi_v4))] - unsafe {} Self { _peri: spi, @@ -264,12 +258,10 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { impl<'d, T: Instance, Tx, Rx> Drop for I2S<'d, T, Tx, Rx> { fn drop(&mut self) { - unsafe { - self.sd.as_ref().map(|x| x.set_as_disconnected()); - self.ws.as_ref().map(|x| x.set_as_disconnected()); - self.ck.as_ref().map(|x| x.set_as_disconnected()); - self.mck.as_ref().map(|x| x.set_as_disconnected()); - } + self.sd.as_ref().map(|x| x.set_as_disconnected()); + self.ws.as_ref().map(|x| x.set_as_disconnected()); + self.ck.as_ref().map(|x| x.set_as_disconnected()); + self.mck.as_ref().map(|x| x.set_as_disconnected()); } } diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 609c4d2c3..3062226c7 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -26,7 +26,7 @@ impl interrupt::typelevel::Handler for Receive ]; // Status register gives channel occupied status. For rx, use cpu1. - let sr = unsafe { regs.cpu(1).sr().read() }; + let sr = regs.cpu(1).sr().read(); regs.cpu(0).mr().modify(|w| { for channel in channels { if sr.chf(channel as usize) { @@ -57,7 +57,7 @@ impl interrupt::typelevel::Handler for Transmi ]; // Status register gives channel occupied status. For tx, use cpu0. - let sr = unsafe { regs.cpu(0).sr().read() }; + let sr = regs.cpu(0).sr().read(); regs.cpu(0).mr().modify(|w| { for channel in channels { if !sr.chf(channel as usize) { @@ -98,16 +98,14 @@ impl Ipcc { IPCC::reset(); IPCC::set_cpu2(true); - unsafe { _configure_pwr() }; + _configure_pwr(); let regs = IPCC::regs(); - unsafe { - regs.cpu(0).cr().modify(|w| { - w.set_rxoie(true); - w.set_txfie(true); - }) - } + regs.cpu(0).cr().modify(|w| { + w.set_rxoie(true); + w.set_txfie(true); + }); // enable interrupts crate::interrupt::typelevel::IPCC_C1_RX::unpend(); @@ -129,7 +127,7 @@ impl Ipcc { compiler_fence(Ordering::SeqCst); trace!("ipcc: ch {}: send data", channel as u8); - unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) } + regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)); } /// Wait for the tx channel to become clear @@ -137,20 +135,20 @@ impl Ipcc { let regs = IPCC::regs(); // This is a race, but is nice for debugging - if unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { + if regs.cpu(0).sr().read().chf(channel as usize) { trace!("ipcc: ch {}: wait for tx free", channel as u8); } poll_fn(|cx| { IPCC::state().tx_waker_for(channel).register(cx.waker()); // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt - unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)) } + regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)); compiler_fence(Ordering::SeqCst); - if !unsafe { regs.cpu(0).sr().read() }.chf(channel as usize) { + if !regs.cpu(0).sr().read().chf(channel as usize) { // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt - unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } + regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)); Poll::Ready(()) } else { @@ -166,20 +164,20 @@ impl Ipcc { loop { // This is a race, but is nice for debugging - if !unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { + if !regs.cpu(1).sr().read().chf(channel as usize) { trace!("ipcc: ch {}: wait for rx occupied", channel as u8); } poll_fn(|cx| { IPCC::state().rx_waker_for(channel).register(cx.waker()); // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt - unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)) } + regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)); compiler_fence(Ordering::SeqCst); - if unsafe { regs.cpu(1).sr().read() }.chf(channel as usize) { + if regs.cpu(1).sr().read().chf(channel as usize) { // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt - unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)) } + regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)); Poll::Ready(()) } else { @@ -199,7 +197,7 @@ impl Ipcc { trace!("ipcc: ch {}: clear rx", channel as u8); compiler_fence(Ordering::SeqCst); // If the channel is clear and the read function returns none, fetch more data - unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } + regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)); } } } @@ -210,7 +208,7 @@ impl sealed::Instance for crate::peripherals::IPCC { } fn set_cpu2(enabled: bool) { - unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) } + crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)); } fn state() -> &'static self::sealed::State { @@ -269,7 +267,7 @@ pub(crate) mod sealed { } } -unsafe fn _configure_pwr() { +fn _configure_pwr() { // TODO: move this to RCC let pwr = crate::pac::PWR; diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 6fde61c06..45a7b5476 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -146,35 +146,35 @@ impl Default for Config { pub fn init(config: Config) -> Peripherals { let p = Peripherals::take(); - unsafe { - #[cfg(dbgmcu)] - if config.enable_debug_during_sleep { - crate::pac::DBGMCU.cr().modify(|cr| { - #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))] - { - cr.set_dbg_stop(true); - cr.set_dbg_standby(true); - } - #[cfg(any( - dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, - dbgmcu_l4, dbgmcu_wb, dbgmcu_wl - ))] - { - cr.set_dbg_sleep(true); - cr.set_dbg_stop(true); - cr.set_dbg_standby(true); - } - #[cfg(dbgmcu_h7)] - { - cr.set_d1dbgcken(true); - cr.set_d3dbgcken(true); - cr.set_dbgsleep_d1(true); - cr.set_dbgstby_d1(true); - cr.set_dbgstop_d1(true); - } - }); - } + #[cfg(dbgmcu)] + if config.enable_debug_during_sleep { + crate::pac::DBGMCU.cr().modify(|cr| { + #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))] + { + cr.set_dbg_stop(true); + cr.set_dbg_standby(true); + } + #[cfg(any( + dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, + dbgmcu_l4, dbgmcu_wb, dbgmcu_wl + ))] + { + cr.set_dbg_sleep(true); + cr.set_dbg_stop(true); + cr.set_dbg_standby(true); + } + #[cfg(dbgmcu_h7)] + { + cr.set_d1dbgcken(true); + cr.set_d3dbgcken(true); + cr.set_dbgsleep_d1(true); + cr.set_dbgstby_d1(true); + cr.set_dbgstop_d1(true); + } + }); + } + unsafe { gpio::init(); dma::init( #[cfg(bdma)] diff --git a/embassy-stm32/src/pwm/complementary_pwm.rs b/embassy-stm32/src/pwm/complementary_pwm.rs index cfb79947c..0e153202e 100644 --- a/embassy-stm32/src/pwm/complementary_pwm.rs +++ b/embassy-stm32/src/pwm/complementary_pwm.rs @@ -21,7 +21,7 @@ macro_rules! complementary_channel_impl { impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { into_ref!(pin); - critical_section::with(|_| unsafe { + critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AFType::OutputPushPull); #[cfg(gpio_v2)] @@ -72,33 +72,27 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { this.inner.set_frequency(freq); this.inner.start(); - unsafe { - this.inner.enable_outputs(true); + this.inner.enable_outputs(true); - this.inner - .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); - } + this.inner + .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); this } pub fn enable(&mut self, channel: Channel) { - unsafe { - self.inner.enable_channel(channel, true); - self.inner.enable_complementary_channel(channel, true); - } + self.inner.enable_channel(channel, true); + self.inner.enable_complementary_channel(channel, true); } pub fn disable(&mut self, channel: Channel) { - unsafe { - self.inner.enable_complementary_channel(channel, false); - self.inner.enable_channel(channel, false); - } + self.inner.enable_complementary_channel(channel, false); + self.inner.enable_channel(channel, false); } pub fn set_freq(&mut self, freq: Hertz) { @@ -106,22 +100,20 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { } pub fn get_max_duty(&self) -> u16 { - unsafe { self.inner.get_max_compare_value() } + self.inner.get_max_compare_value() } pub fn set_duty(&mut self, channel: Channel, duty: u16) { assert!(duty < self.get_max_duty()); - unsafe { self.inner.set_compare_value(channel, duty) } + self.inner.set_compare_value(channel, duty) } /// Set the dead time as a proportion of max_duty pub fn set_dead_time(&mut self, value: u16) { let (ckd, value) = compute_dead_time_value(value); - unsafe { - self.inner.set_dead_time_clock_division(ckd); - self.inner.set_dead_time_value(value); - } + self.inner.set_dead_time_clock_division(ckd); + self.inner.set_dead_time_value(value); } } diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs index 0bef07089..5aba2663e 100644 --- a/embassy-stm32/src/pwm/mod.rs +++ b/embassy-stm32/src/pwm/mod.rs @@ -59,33 +59,33 @@ pub(crate) mod sealed { pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { /// Global output enable. Does not do anything on non-advanced timers. - unsafe fn enable_outputs(&mut self, enable: bool); + fn enable_outputs(&mut self, enable: bool); - unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); + fn enable_channel(&mut self, channel: Channel, enable: bool); - unsafe fn set_compare_value(&mut self, channel: Channel, value: u16); + fn set_compare_value(&mut self, channel: Channel, value: u16); - unsafe fn get_max_compare_value(&self) -> u16; + fn get_max_compare_value(&self) -> u16; } pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { - unsafe fn set_dead_time_clock_division(&mut self, value: Ckd); + fn set_dead_time_clock_division(&mut self, value: Ckd); - unsafe fn set_dead_time_value(&mut self, value: u8); + fn set_dead_time_value(&mut self, value: u8); - unsafe fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); + fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); } pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance { - unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); + fn enable_channel(&mut self, channel: Channel, enable: bool); - unsafe fn set_compare_value(&mut self, channel: Channel, value: u32); + fn set_compare_value(&mut self, channel: Channel, value: u32); - unsafe fn get_max_compare_value(&self) -> u32; + fn get_max_compare_value(&self) -> u32; } } @@ -108,9 +108,9 @@ pub trait CaptureCompare32bitInstance: macro_rules! impl_compare_capable_16bit { ($inst:ident) => { impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - unsafe fn enable_outputs(&mut self, _enable: bool) {} + fn enable_outputs(&mut self, _enable: bool) {} - unsafe fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { + fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { use crate::timer::sealed::GeneralPurpose16bitInstance; let r = Self::regs_gp16(); let raw_channel: usize = channel.raw(); @@ -118,19 +118,19 @@ macro_rules! impl_compare_capable_16bit { .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); } - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { + fn enable_channel(&mut self, channel: Channel, enable: bool) { use crate::timer::sealed::GeneralPurpose16bitInstance; Self::regs_gp16() .ccer() .modify(|w| w.set_cce(channel.raw(), enable)); } - unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { + fn set_compare_value(&mut self, channel: Channel, value: u16) { use crate::timer::sealed::GeneralPurpose16bitInstance; Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); } - unsafe fn get_max_compare_value(&self) -> u16 { + fn get_max_compare_value(&self) -> u16 { use crate::timer::sealed::GeneralPurpose16bitInstance; Self::regs_gp16().arr().read().arr() } @@ -150,7 +150,7 @@ foreach_interrupt! { ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { impl_compare_capable_16bit!($inst); impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { - unsafe fn set_output_compare_mode( + fn set_output_compare_mode( &mut self, channel: crate::pwm::Channel, mode: OutputCompareMode, @@ -160,17 +160,17 @@ foreach_interrupt! { Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into())); } - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { + fn enable_channel(&mut self, channel: Channel, enable: bool) { use crate::timer::sealed::GeneralPurpose32bitInstance; Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable)); } - unsafe fn set_compare_value(&mut self, channel: Channel, value: u32) { + fn set_compare_value(&mut self, channel: Channel, value: u32) { use crate::timer::sealed::GeneralPurpose32bitInstance; Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); } - unsafe fn get_max_compare_value(&self) -> u32 { + fn get_max_compare_value(&self) -> u32 { use crate::timer::sealed::GeneralPurpose32bitInstance; Self::regs_gp32().arr().read().arr() as u32 } @@ -185,13 +185,13 @@ foreach_interrupt! { ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - unsafe fn enable_outputs(&mut self, enable: bool) { + fn enable_outputs(&mut self, enable: bool) { use crate::timer::sealed::AdvancedControlInstance; let r = Self::regs_advanced(); r.bdtr().modify(|w| w.set_moe(enable)); } - unsafe fn set_output_compare_mode( + fn set_output_compare_mode( &mut self, channel: crate::pwm::Channel, mode: OutputCompareMode, @@ -203,21 +203,21 @@ foreach_interrupt! { .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); } - unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) { + fn enable_channel(&mut self, channel: Channel, enable: bool) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced() .ccer() .modify(|w| w.set_cce(channel.raw(), enable)); } - unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) { + fn set_compare_value(&mut self, channel: Channel, value: u16) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced() .ccr(channel.raw()) .modify(|w| w.set_ccr(value)); } - unsafe fn get_max_compare_value(&self) -> u16 { + fn get_max_compare_value(&self) -> u16 { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced().arr().read().arr() } @@ -228,17 +228,17 @@ foreach_interrupt! { } impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { - unsafe fn set_dead_time_clock_division(&mut self, value: Ckd) { + fn set_dead_time_clock_division(&mut self, value: Ckd) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); } - unsafe fn set_dead_time_value(&mut self, value: u8) { + fn set_dead_time_value(&mut self, value: u8) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); } - unsafe fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { + fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced() .ccer() diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs index b045a2d78..995f59c23 100644 --- a/embassy-stm32/src/pwm/simple_pwm.rs +++ b/embassy-stm32/src/pwm/simple_pwm.rs @@ -24,7 +24,7 @@ macro_rules! channel_impl { impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { into_ref!(pin); - critical_section::with(|_| unsafe { + critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AFType::OutputPushPull); #[cfg(gpio_v2)] @@ -71,31 +71,25 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { this.inner.set_frequency(freq); this.inner.start(); - unsafe { - this.inner.enable_outputs(true); + this.inner.enable_outputs(true); - this.inner - .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); - } + this.inner + .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); + this.inner + .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); this } pub fn enable(&mut self, channel: Channel) { - unsafe { - self.inner.enable_channel(channel, true); - } + self.inner.enable_channel(channel, true); } pub fn disable(&mut self, channel: Channel) { - unsafe { - self.inner.enable_channel(channel, false); - } + self.inner.enable_channel(channel, false); } pub fn set_freq(&mut self, freq: Hertz) { @@ -103,11 +97,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { } pub fn get_max_duty(&self) -> u16 { - unsafe { self.inner.get_max_compare_value() } + self.inner.get_max_compare_value() } pub fn set_duty(&mut self, channel: Channel, duty: u16) { assert!(duty < self.get_max_duty()); - unsafe { self.inner.set_compare_value(channel, duty) } + self.inner.set_compare_value(channel, duty) } } diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index c3126b37f..e9db934bf 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -96,20 +96,18 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { ) -> Self { into_ref!(peri, d0, d1, d2, d3, sck, nss); - unsafe { - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af(nss.af_num(), AFType::OutputPushPull); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af(d0.af_num(), AFType::OutputPushPull); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af(d1.af_num(), AFType::OutputPushPull); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af(d2.af_num(), AFType::OutputPushPull); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af(d3.af_num(), AFType::OutputPushPull); - d3.set_speed(crate::gpio::Speed::VeryHigh); - } + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + nss.set_as_af(nss.af_num(), AFType::OutputPushPull); + nss.set_speed(crate::gpio::Speed::VeryHigh); + d0.set_as_af(d0.af_num(), AFType::OutputPushPull); + d0.set_speed(crate::gpio::Speed::VeryHigh); + d1.set_as_af(d1.af_num(), AFType::OutputPushPull); + d1.set_speed(crate::gpio::Speed::VeryHigh); + d2.set_as_af(d2.af_num(), AFType::OutputPushPull); + d2.set_speed(crate::gpio::Speed::VeryHigh); + d3.set_as_af(d3.af_num(), AFType::OutputPushPull); + d3.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( peri, @@ -138,21 +136,19 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { into_ref!(peri, dma); T::enable(); - unsafe { - T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); + T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); - while T::REGS.sr().read().busy() {} + while T::REGS.sr().read().busy() {} - T::REGS.cr().write(|w| { - w.set_prescaler(config.prescaler); - w.set_en(true); - }); - T::REGS.dcr().write(|w| { - w.set_fsize(config.memory_size.into()); - w.set_csht(config.cs_high_time.into()); - w.set_ckmode(false); - }); - } + T::REGS.cr().write(|w| { + w.set_prescaler(config.prescaler); + w.set_en(true); + }); + T::REGS.dcr().write(|w| { + w.set_fsize(config.memory_size.into()); + w.set_csht(config.cs_high_time.into()); + w.set_ckmode(false); + }); Self { _peri: peri, @@ -168,148 +164,140 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } pub fn command(&mut self, transaction: TransferConfig) { - unsafe { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); - } + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); } pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { - unsafe { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - if let Some(len) = transaction.data_len { - let current_ar = T::REGS.ar().read().address(); - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectRead.into()); - }); - T::REGS.ar().write(|v| { - v.set_address(current_ar); - }); + if let Some(len) = transaction.data_len { + let current_ar = T::REGS.ar().read().address(); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectRead.into()); + }); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); - for idx in 0..len { - while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} - buf[idx] = *(T::REGS.dr().ptr() as *mut u8); - } + for idx in 0..len { + while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} + buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; } - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); } pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { - unsafe { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - if let Some(len) = transaction.data_len { - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectWrite.into()); - }); + if let Some(len) = transaction.data_len { + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectWrite.into()); + }); - for idx in 0..len { - while !T::REGS.sr().read().ftf() {} - *(T::REGS.dr().ptr() as *mut u8) = buf[idx]; - } + for idx in 0..len { + while !T::REGS.sr().read().ftf() {} + unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) }; } - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); } pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) where Dma: QuadDma, { - unsafe { - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectRead.into()); - }); - let current_ar = T::REGS.ar().read().address(); - T::REGS.ar().write(|v| { - v.set_address(current_ar); - }); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectRead.into()); + }); + let current_ar = T::REGS.ar().read().address(); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); - let request = self.dma.request(); - let transfer = Transfer::new_read( + let request = self.dma.request(); + let transfer = unsafe { + Transfer::new_read( &mut self.dma, request, - T::REGS.dr().ptr() as *mut u8, + T::REGS.dr().as_ptr() as *mut u8, buf, Default::default(), - ); + ) + }; - T::REGS.cr().modify(|v| v.set_dmaen(true)); + T::REGS.cr().modify(|v| v.set_dmaen(true)); - transfer.blocking_wait(); - } + transfer.blocking_wait(); } pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) where Dma: QuadDma, { - unsafe { - self.setup_transaction(QspiMode::IndirectWrite, &transaction); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectWrite.into()); - }); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectWrite.into()); + }); - let request = self.dma.request(); - let transfer = Transfer::new_write( + let request = self.dma.request(); + let transfer = unsafe { + Transfer::new_write( &mut self.dma, request, buf, - T::REGS.dr().ptr() as *mut u8, + T::REGS.dr().as_ptr() as *mut u8, Default::default(), - ); + ) + }; - T::REGS.cr().modify(|v| v.set_dmaen(true)); + T::REGS.cr().modify(|v| v.set_dmaen(true)); - transfer.blocking_wait(); - } + transfer.blocking_wait(); } fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { - unsafe { - T::REGS.fcr().modify(|v| { - v.set_csmf(true); - v.set_ctcf(true); - v.set_ctef(true); - v.set_ctof(true); + T::REGS.fcr().modify(|v| { + v.set_csmf(true); + v.set_ctcf(true); + v.set_ctef(true); + v.set_ctof(true); + }); + + while T::REGS.sr().read().busy() {} + + if let Some(len) = transaction.data_len { + T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); + } + + T::REGS.ccr().write(|v| { + v.set_fmode(fmode.into()); + v.set_imode(transaction.iwidth.into()); + v.set_instruction(transaction.instruction); + v.set_admode(transaction.awidth.into()); + v.set_adsize(self.config.address_size.into()); + v.set_dmode(transaction.dwidth.into()); + v.set_abmode(QspiWidth::NONE.into()); + v.set_dcyc(transaction.dummy.into()); + }); + + if let Some(addr) = transaction.address { + T::REGS.ar().write(|v| { + v.set_address(addr); }); - - while T::REGS.sr().read().busy() {} - - if let Some(len) = transaction.data_len { - T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); - } - - T::REGS.ccr().write(|v| { - v.set_fmode(fmode.into()); - v.set_imode(transaction.iwidth.into()); - v.set_instruction(transaction.instruction); - v.set_admode(transaction.awidth.into()); - v.set_adsize(self.config.address_size.into()); - v.set_dmode(transaction.dwidth.into()); - v.set_abmode(QspiWidth::NONE.into()); - v.set_dcyc(transaction.dummy.into()); - }); - - if let Some(addr) = transaction.address { - T::REGS.ar().write(|v| { - v.set_address(addr); - }); - } } } } diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index e0929ca49..bc430afb2 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -36,18 +36,18 @@ pub struct Config { } #[cfg(stm32f410)] -unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { +fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } // Not currently implemented, but will be in the future #[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] -unsafe fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { +fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] -unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { +fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { let min_div = 2; let max_div = 7; let target = match plli2s { @@ -82,13 +82,7 @@ unsafe fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { Some(output) } -unsafe fn setup_pll( - pllsrcclk: u32, - use_hse: bool, - pllsysclk: Option, - plli2s: Option, - pll48clk: bool, -) -> PllResults { +fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Option, pll48clk: bool) -> PllResults { use crate::pac::rcc::vals::{Pllp, Pllsrc}; let sysclk = pllsysclk.unwrap_or(pllsrcclk); @@ -320,7 +314,7 @@ impl<'d, T: McoInstance> Mco<'d, T> { } } -unsafe fn flash_setup(sysclk: u32) { +fn flash_setup(sysclk: u32) { use crate::pac::flash::vals::Latency; // Be conservative with voltage ranges diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs index 2d21326a3..71215cac5 100644 --- a/embassy-stm32/src/rcc/f7.rs +++ b/embassy-stm32/src/rcc/f7.rs @@ -25,7 +25,7 @@ pub struct Config { pub pll48: bool, } -unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bool) -> PllResults { +fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bool) -> PllResults { use crate::pac::rcc::vals::{Pllp, Pllsrc}; let sysclk = pllsysclk.unwrap_or(pllsrcclk); @@ -97,7 +97,7 @@ unsafe fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48 } } -unsafe fn flash_setup(sysclk: u32) { +fn flash_setup(sysclk: u32) { use crate::pac::flash::vals::Latency; // Be conservative with voltage ranges diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 3e138c7ab..17c73c36b 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -245,7 +245,7 @@ impl Default for Config { } impl PllConfig { - pub(crate) unsafe fn init(self) -> u32 { + pub(crate) fn init(self) -> u32 { assert!(self.n >= 8 && self.n <= 86); let (src, input_freq) = match self.source { PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0), diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs index 17fbc6056..4025a4e05 100644 --- a/embassy-stm32/src/rcc/h5.rs +++ b/embassy-stm32/src/rcc/h5.rs @@ -462,7 +462,7 @@ struct PllOutput { r: Option, } -unsafe fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { +fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { let Some(config) = config else { // Stop PLL RCC.cr().modify(|w| w.set_pllon(num, false)); @@ -595,12 +595,9 @@ fn flash_setup(clk: Hertz, vos: VoltageScale) { defmt::debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq); - // NOTE(unsafe) Atomic write - unsafe { - FLASH.acr().write(|w| { - w.set_wrhighfreq(wrhighfreq); - w.set_latency(latency); - }); - while FLASH.acr().read().latency() != latency {} - } + FLASH.acr().write(|w| { + w.set_wrhighfreq(wrhighfreq); + w.set_latency(latency); + }); + while FLASH.acr().read().latency() != latency {} } diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index 0185f7ae8..daa1cd61f 100644 --- a/embassy-stm32/src/rcc/h7.rs +++ b/embassy-stm32/src/rcc/h7.rs @@ -253,14 +253,11 @@ fn flash_setup(rcc_aclk: u32, vos: VoltageScale) { }, }; - // NOTE(unsafe) Atomic write - unsafe { - FLASH.acr().write(|w| { - w.set_wrhighfreq(progr_delay); - w.set_latency(wait_states) - }); - while FLASH.acr().read().latency() != wait_states {} - } + FLASH.acr().write(|w| { + w.set_wrhighfreq(progr_delay); + w.set_latency(wait_states) + }); + while FLASH.acr().read().latency() != wait_states {} } pub enum McoClock { @@ -474,7 +471,6 @@ pub(crate) unsafe fn init(mut config: Config) { // Configure traceclk from PLL if needed traceclk_setup(&mut config, sys_use_pll1_p); - // NOTE(unsafe) We have exclusive access to the RCC let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = pll::pll_setup(srcclk.0, &config.pll1, 0); let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = pll::pll_setup(srcclk.0, &config.pll2, 1); let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = pll::pll_setup(srcclk.0, &config.pll3, 2); @@ -756,7 +752,7 @@ mod pll { /// # Safety /// /// Must have exclusive access to the RCC register block - unsafe fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults { + fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults { use crate::pac::rcc::vals::{Pllrge, Pllvcosel}; let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln); @@ -785,11 +781,7 @@ mod pll { /// # Safety /// /// Must have exclusive access to the RCC register block - pub(super) unsafe fn pll_setup( - pll_src: u32, - config: &PllConfig, - plln: usize, - ) -> (Option, Option, Option) { + pub(super) fn pll_setup(pll_src: u32, config: &PllConfig, plln: usize) -> (Option, Option, Option) { use crate::pac::rcc::vals::Divp; match config.p_ck { diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index c657bf70e..b2faec53d 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -34,40 +34,34 @@ impl<'d, T: Instance> Rng<'d, T> { pub fn reset(&mut self) { // rng_v2 locks up on seed error, needs reset #[cfg(rng_v2)] - if unsafe { T::regs().sr().read().seis() } { + if T::regs().sr().read().seis() { T::reset(); } - unsafe { - T::regs().cr().modify(|reg| { - reg.set_rngen(true); - reg.set_ie(true); - }); - T::regs().sr().modify(|reg| { - reg.set_seis(false); - reg.set_ceis(false); - }); - } + T::regs().cr().modify(|reg| { + reg.set_rngen(true); + reg.set_ie(true); + }); + T::regs().sr().modify(|reg| { + reg.set_seis(false); + reg.set_ceis(false); + }); // Reference manual says to discard the first. let _ = self.next_u32(); } pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - unsafe { - T::regs().cr().modify(|reg| { - reg.set_rngen(true); - }) - } + T::regs().cr().modify(|reg| { + reg.set_rngen(true); + }); for chunk in dest.chunks_mut(4) { poll_fn(|cx| { RNG_WAKER.register(cx.waker()); - unsafe { - T::regs().cr().modify(|reg| { - reg.set_ie(true); - }); - } + T::regs().cr().modify(|reg| { + reg.set_ie(true); + }); - let bits = unsafe { T::regs().sr().read() }; + let bits = T::regs().sr().read(); if bits.drdy() { Poll::Ready(Ok(())) @@ -82,7 +76,7 @@ impl<'d, T: Instance> Rng<'d, T> { } }) .await?; - let random_bytes = unsafe { T::regs().dr().read() }.to_be_bytes(); + let random_bytes = T::regs().dr().read().to_be_bytes(); for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) { *dest = *src } @@ -95,11 +89,11 @@ impl<'d, T: Instance> Rng<'d, T> { impl<'d, T: Instance> RngCore for Rng<'d, T> { fn next_u32(&mut self) -> u32 { loop { - let sr = unsafe { T::regs().sr().read() }; + let sr = T::regs().sr().read(); if sr.seis() | sr.ceis() { self.reset(); } else if sr.drdy() { - return unsafe { T::regs().dr().read() }; + return T::regs().dr().read(); } } } diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index 0a590c1bb..a9c48d88d 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs @@ -154,29 +154,27 @@ pub(super) fn write_date_time(rtc: &Rtc, t: DateTime) { let yr_offset = (yr - 1970_u16) as u8; let (yt, yu) = byte_to_bcd2(yr_offset); - unsafe { - use crate::pac::rtc::vals::Ampm; + use crate::pac::rtc::vals::Ampm; - rtc.tr().write(|w| { - w.set_ht(ht); - w.set_hu(hu); - w.set_mnt(mnt); - w.set_mnu(mnu); - w.set_st(st); - w.set_su(su); - w.set_pm(Ampm::AM); - }); + rtc.tr().write(|w| { + w.set_ht(ht); + w.set_hu(hu); + w.set_mnt(mnt); + w.set_mnu(mnu); + w.set_st(st); + w.set_su(su); + w.set_pm(Ampm::AM); + }); - rtc.dr().write(|w| { - w.set_dt(dt); - w.set_du(du); - w.set_mt(mt > 0); - w.set_mu(mu); - w.set_yt(yt); - w.set_yu(yu); - w.set_wdu(day_of_week_to_u8(t.day_of_week)); - }); - } + rtc.dr().write(|w| { + w.set_dt(dt); + w.set_du(du); + w.set_mt(mt > 0); + w.set_mu(mu); + w.set_yt(yt); + w.set_yu(yu); + w.set_wdu(day_of_week_to_u8(t.day_of_week)); + }); } pub(super) fn datetime( diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 962927fb1..12a2ac795 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -113,7 +113,7 @@ impl Default for RtcCalibrationCyclePeriod { impl<'d, T: Instance> Rtc<'d, T> { pub fn new(_rtc: impl Peripheral

+ 'd, rtc_config: RtcConfig) -> Self { - unsafe { T::enable_peripheral_clk() }; + T::enable_peripheral_clk(); let mut rtc_struct = Self { phantom: PhantomData, @@ -144,34 +144,32 @@ impl<'d, T: Instance> Rtc<'d, T> { /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. pub fn now(&self) -> Result { let r = T::regs(); - unsafe { - let tr = r.tr().read(); - let second = bcd2_to_byte((tr.st(), tr.su())); - let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); - let hour = bcd2_to_byte((tr.ht(), tr.hu())); - // Reading either RTC_SSR or RTC_TR locks the values in the higher-order - // calendar shadow registers until RTC_DR is read. - let dr = r.dr().read(); + let tr = r.tr().read(); + let second = bcd2_to_byte((tr.st(), tr.su())); + let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); + let hour = bcd2_to_byte((tr.ht(), tr.hu())); + // Reading either RTC_SSR or RTC_TR locks the values in the higher-order + // calendar shadow registers until RTC_DR is read. + let dr = r.dr().read(); - let weekday = dr.wdu(); - let day = bcd2_to_byte((dr.dt(), dr.du())); - let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); - let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; + let weekday = dr.wdu(); + let day = bcd2_to_byte((dr.dt(), dr.du())); + let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); + let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; - self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) - } + self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) } /// Check if daylight savings time is active. pub fn get_daylight_savings(&self) -> bool { - let cr = unsafe { T::regs().cr().read() }; + let cr = T::regs().cr().read(); cr.bkp() } /// Enable/disable daylight savings time. pub fn set_daylight_savings(&mut self, daylight_savings: bool) { self.write(true, |rtc| { - unsafe { rtc.cr().modify(|w| w.set_bkp(daylight_savings)) }; + rtc.cr().modify(|w| w.set_bkp(daylight_savings)); }) } @@ -228,7 +226,7 @@ pub(crate) mod sealed { crate::pac::RTC } - unsafe fn enable_peripheral_clk() {} + fn enable_peripheral_clk() {} /// Read content of the backup register. /// diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index adaafe67a..e1615b34c 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -8,74 +8,72 @@ impl<'d, T: Instance> super::Rtc<'d, T> { /// It this changes the RTC clock source the time will be reset pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { // Unlock the backup domain - unsafe { - let clock_config = rtc_config.clock_config as u8; + let clock_config = rtc_config.clock_config as u8; - #[cfg(not(rtc_v2wb))] - use stm32_metapac::rcc::vals::Rtcsel; + #[cfg(not(rtc_v2wb))] + use stm32_metapac::rcc::vals::Rtcsel; - #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] - let cr = crate::pac::PWR.cr(); - #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - let cr = crate::pac::PWR.cr1(); + #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] + let cr = crate::pac::PWR.cr(); + #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] + let cr = crate::pac::PWR.cr1(); - // TODO: Missing from PAC for l0 and f0? - #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] - { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} - } - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let reg = crate::pac::RCC.bdcr().read(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let reg = crate::pac::RCC.csr().read(); - - #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - #[cfg(rtc_v2wb)] - let rtcsel = reg.rtcsel(); - #[cfg(not(rtc_v2wb))] - let rtcsel = reg.rtcsel().0; - - if !reg.rtcen() || rtcsel != clock_config { - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - cr.modify(|w| { - // Reset - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - w.set_bdrst(false); - - // Select RTC source - #[cfg(not(rtc_v2wb))] - w.set_rtcsel(Rtcsel(clock_config)); - #[cfg(rtc_v2wb)] - w.set_rtcsel(clock_config); - w.set_rtcen(true); - - // Restore bcdr - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscosel(reg.lscosel()); - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); - - #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } + // TODO: Missing from PAC for l0 and f0? + #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] + { + cr.modify(|w| w.set_dbp(true)); + while !cr.read().dbp() {} } - self.write(true, |rtc| unsafe { + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let reg = crate::pac::RCC.bdcr().read(); + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let reg = crate::pac::RCC.csr().read(); + + #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] + assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + + #[cfg(rtc_v2wb)] + let rtcsel = reg.rtcsel(); + #[cfg(not(rtc_v2wb))] + let rtcsel = reg.rtcsel().0; + + if !reg.rtcen() || rtcsel != clock_config { + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); + + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + let cr = crate::pac::RCC.bdcr(); + #[cfg(any(rtc_v2l0, rtc_v2l1))] + let cr = crate::pac::RCC.csr(); + + cr.modify(|w| { + // Reset + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + w.set_bdrst(false); + + // Select RTC source + #[cfg(not(rtc_v2wb))] + w.set_rtcsel(Rtcsel(clock_config)); + #[cfg(rtc_v2wb)] + w.set_rtcsel(clock_config); + w.set_rtcen(true); + + // Restore bcdr + #[cfg(any(rtc_v2l4, rtc_v2wb))] + w.set_lscosel(reg.lscosel()); + #[cfg(any(rtc_v2l4, rtc_v2wb))] + w.set_lscoen(reg.lscoen()); + + w.set_lseon(reg.lseon()); + + #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] + w.set_lsedrv(reg.lsedrv()); + w.set_lsebyp(reg.lsebyp()); + }); + } + + self.write(true, |rtc| { rtc.cr().modify(|w| { #[cfg(rtc_v2f2)] w.set_fmt(false); @@ -117,47 +115,45 @@ impl<'d, T: Instance> super::Rtc<'d, T> { clock_drift = clock_drift / RTC_CALR_RESOLUTION_PPM; self.write(false, |rtc| { - unsafe { - rtc.calr().write(|w| { - match period { - super::RtcCalibrationCyclePeriod::Seconds8 => { - w.set_calw8(stm32_metapac::rtc::vals::Calw8::EIGHT_SECOND); - } - super::RtcCalibrationCyclePeriod::Seconds16 => { - w.set_calw16(stm32_metapac::rtc::vals::Calw16::SIXTEEN_SECOND); - } - super::RtcCalibrationCyclePeriod::Seconds32 => { - // Set neither `calw8` nor `calw16` to use 32 seconds - } + rtc.calr().write(|w| { + match period { + super::RtcCalibrationCyclePeriod::Seconds8 => { + w.set_calw8(stm32_metapac::rtc::vals::Calw8::EIGHT_SECOND); } - - // Extra pulses during calibration cycle period: CALP * 512 - CALM - // - // CALP sets whether pulses are added or omitted. - // - // CALM contains how many pulses (out of 512) are masked in a - // given calibration cycle period. - if clock_drift > 0.0 { - // Maximum (about 512.2) rounds to 512. - clock_drift += 0.5; - - // When the offset is positive (0 to 512), the opposite of - // the offset (512 - offset) is masked, i.e. for the - // maximum offset (512), 0 pulses are masked. - w.set_calp(stm32_metapac::rtc::vals::Calp::INCREASEFREQ); - w.set_calm(512 - clock_drift as u16); - } else { - // Minimum (about -510.7) rounds to -511. - clock_drift -= 0.5; - - // When the offset is negative or zero (-511 to 0), - // the absolute offset is masked, i.e. for the minimum - // offset (-511), 511 pulses are masked. - w.set_calp(stm32_metapac::rtc::vals::Calp::NOCHANGE); - w.set_calm((clock_drift * -1.0) as u16); + super::RtcCalibrationCyclePeriod::Seconds16 => { + w.set_calw16(stm32_metapac::rtc::vals::Calw16::SIXTEEN_SECOND); } - }); - } + super::RtcCalibrationCyclePeriod::Seconds32 => { + // Set neither `calw8` nor `calw16` to use 32 seconds + } + } + + // Extra pulses during calibration cycle period: CALP * 512 - CALM + // + // CALP sets whether pulses are added or omitted. + // + // CALM contains how many pulses (out of 512) are masked in a + // given calibration cycle period. + if clock_drift > 0.0 { + // Maximum (about 512.2) rounds to 512. + clock_drift += 0.5; + + // When the offset is positive (0 to 512), the opposite of + // the offset (512 - offset) is masked, i.e. for the + // maximum offset (512), 0 pulses are masked. + w.set_calp(stm32_metapac::rtc::vals::Calp::INCREASEFREQ); + w.set_calm(512 - clock_drift as u16); + } else { + // Minimum (about -510.7) rounds to -511. + clock_drift -= 0.5; + + // When the offset is negative or zero (-511 to 0), + // the absolute offset is masked, i.e. for the minimum + // offset (-511), 511 pulses are masked. + w.set_calp(stm32_metapac::rtc::vals::Calp::NOCHANGE); + w.set_calm((clock_drift * -1.0) as u16); + } + }); }) } @@ -168,31 +164,27 @@ impl<'d, T: Instance> super::Rtc<'d, T> { let r = T::regs(); // Disable write protection. // This is safe, as we're only writin the correct and expected values. - unsafe { - r.wpr().write(|w| w.set_key(0xca)); - r.wpr().write(|w| w.set_key(0x53)); + r.wpr().write(|w| w.set_key(0xca)); + r.wpr().write(|w| w.set_key(0x53)); - // true if initf bit indicates RTC peripheral is in init mode - if init_mode && !r.isr().read().initf() { - // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode - r.isr().modify(|w| w.set_init(Init::INITMODE)); - // wait till init state entered - // ~2 RTCCLK cycles - while !r.isr().read().initf() {} - } + // true if initf bit indicates RTC peripheral is in init mode + if init_mode && !r.isr().read().initf() { + // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode + r.isr().modify(|w| w.set_init(Init::INITMODE)); + // wait till init state entered + // ~2 RTCCLK cycles + while !r.isr().read().initf() {} } let result = f(&r); - unsafe { - if init_mode { - r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode - } - - // Re-enable write protection. - // This is safe, as the field accepts the full range of 8-bit values. - r.wpr().write(|w| w.set_key(0xff)); + if init_mode { + r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode } + + // Re-enable write protection. + // This is safe, as the field accepts the full range of 8-bit values. + r.wpr().write(|w| w.set_key(0xff)); result } } @@ -200,7 +192,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { impl sealed::Instance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 20; - unsafe fn enable_peripheral_clk() { + fn enable_peripheral_clk() { #[cfg(any(rtc_v2l4, rtc_v2wb))] { // enable peripheral clock for communication @@ -213,7 +205,7 @@ impl sealed::Instance for crate::peripherals::RTC { fn read_backup_register(rtc: &Rtc, register: usize) -> Option { if register < Self::BACKUP_REGISTER_COUNT { - Some(unsafe { rtc.bkpr(register).read().bkp() }) + Some(rtc.bkpr(register).read().bkp()) } else { None } @@ -221,7 +213,7 @@ impl sealed::Instance for crate::peripherals::RTC { fn write_backup_register(rtc: &Rtc, register: usize, value: u32) { if register < Self::BACKUP_REGISTER_COUNT { - unsafe { rtc.bkpr(register).write(|w| w.set_bkp(value)) } + rtc.bkpr(register).write(|w| w.set_bkp(value)); } } } diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 24f6496a6..7c91046a2 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -8,70 +8,66 @@ impl<'d, T: Instance> super::Rtc<'d, T> { /// It this changes the RTC clock source the time will be reset pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { // Unlock the backup domain - unsafe { - #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] - { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); - while !crate::pac::PWR.cr1().read().dbp() {} - } - #[cfg(any(rcc_wl5, rcc_wle))] - { - use crate::pac::pwr::vals::Dbp; + #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] + { + crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); + while !crate::pac::PWR.cr1().read().dbp() {} + } + #[cfg(any(rcc_wl5, rcc_wle))] + { + use crate::pac::pwr::vals::Dbp; - crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); - while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} - } + crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); + while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} + } - let reg = crate::pac::RCC.bdcr().read(); - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + let reg = crate::pac::RCC.bdcr().read(); + assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - let config_rtcsel = rtc_config.clock_config as u8; - #[cfg(not(any(rcc_wl5, rcc_wle)))] - let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel); + let config_rtcsel = rtc_config.clock_config as u8; + #[cfg(not(any(rcc_wl5, rcc_wle)))] + let config_rtcsel = crate::pac::rcc::vals::Rtcsel(config_rtcsel); - if !reg.rtcen() || reg.rtcsel() != config_rtcsel { - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); + if !reg.rtcen() || reg.rtcsel() != config_rtcsel { + crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - crate::pac::RCC.bdcr().modify(|w| { - // Reset - w.set_bdrst(false); + crate::pac::RCC.bdcr().modify(|w| { + // Reset + w.set_bdrst(false); - // Select RTC source - w.set_rtcsel(config_rtcsel); + // Select RTC source + w.set_rtcsel(config_rtcsel); - w.set_rtcen(true); + w.set_rtcen(true); - // Restore bcdr - w.set_lscosel(reg.lscosel()); - w.set_lscoen(reg.lscoen()); + // Restore bcdr + w.set_lscosel(reg.lscosel()); + w.set_lscoen(reg.lscoen()); - w.set_lseon(reg.lseon()); - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } + w.set_lseon(reg.lseon()); + w.set_lsedrv(reg.lsedrv()); + w.set_lsebyp(reg.lsebyp()); + }); } self.write(true, |rtc| { - unsafe { - rtc.cr().modify(|w| { - w.set_fmt(Fmt::TWENTYFOURHOUR); - w.set_osel(Osel::DISABLED); - w.set_pol(Pol::HIGH); - }); + rtc.cr().modify(|w| { + w.set_fmt(Fmt::TWENTYFOURHOUR); + w.set_osel(Osel::DISABLED); + w.set_pol(Pol::HIGH); + }); - rtc.prer().modify(|w| { - w.set_prediv_s(rtc_config.sync_prescaler); - w.set_prediv_a(rtc_config.async_prescaler); - }); + rtc.prer().modify(|w| { + w.set_prediv_s(rtc_config.sync_prescaler); + w.set_prediv_a(rtc_config.async_prescaler); + }); - // TODO: configuration for output pins - rtc.cr().modify(|w| { - w.set_out2en(false); - w.set_tampalrm_type(TampalrmType::PUSHPULL); - w.set_tampalrm_pu(TampalrmPu::NOPULLUP); - }); - } + // TODO: configuration for output pins + rtc.cr().modify(|w| { + w.set_out2en(false); + w.set_tampalrm_type(TampalrmType::PUSHPULL); + w.set_tampalrm_pu(TampalrmPu::NOPULLUP); + }); }); self.rtc_config = rtc_config; @@ -99,47 +95,45 @@ impl<'d, T: Instance> super::Rtc<'d, T> { clock_drift = clock_drift / Self::RTC_CALR_RESOLUTION_PPM; self.write(false, |rtc| { - unsafe { - rtc.calr().write(|w| { - match period { - RtcCalibrationCyclePeriod::Seconds8 => { - w.set_calw8(Calw8::EIGHTSECONDS); - } - RtcCalibrationCyclePeriod::Seconds16 => { - w.set_calw16(Calw16::SIXTEENSECONDS); - } - RtcCalibrationCyclePeriod::Seconds32 => { - // Set neither `calw8` nor `calw16` to use 32 seconds - } + rtc.calr().write(|w| { + match period { + RtcCalibrationCyclePeriod::Seconds8 => { + w.set_calw8(Calw8::EIGHTSECONDS); } - - // Extra pulses during calibration cycle period: CALP * 512 - CALM - // - // CALP sets whether pulses are added or omitted. - // - // CALM contains how many pulses (out of 512) are masked in a - // given calibration cycle period. - if clock_drift > 0.0 { - // Maximum (about 512.2) rounds to 512. - clock_drift += 0.5; - - // When the offset is positive (0 to 512), the opposite of - // the offset (512 - offset) is masked, i.e. for the - // maximum offset (512), 0 pulses are masked. - w.set_calp(Calp::INCREASEFREQ); - w.set_calm(512 - clock_drift as u16); - } else { - // Minimum (about -510.7) rounds to -511. - clock_drift -= 0.5; - - // When the offset is negative or zero (-511 to 0), - // the absolute offset is masked, i.e. for the minimum - // offset (-511), 511 pulses are masked. - w.set_calp(Calp::NOCHANGE); - w.set_calm((clock_drift * -1.0) as u16); + RtcCalibrationCyclePeriod::Seconds16 => { + w.set_calw16(Calw16::SIXTEENSECONDS); } - }); - } + RtcCalibrationCyclePeriod::Seconds32 => { + // Set neither `calw8` nor `calw16` to use 32 seconds + } + } + + // Extra pulses during calibration cycle period: CALP * 512 - CALM + // + // CALP sets whether pulses are added or omitted. + // + // CALM contains how many pulses (out of 512) are masked in a + // given calibration cycle period. + if clock_drift > 0.0 { + // Maximum (about 512.2) rounds to 512. + clock_drift += 0.5; + + // When the offset is positive (0 to 512), the opposite of + // the offset (512 - offset) is masked, i.e. for the + // maximum offset (512), 0 pulses are masked. + w.set_calp(Calp::INCREASEFREQ); + w.set_calm(512 - clock_drift as u16); + } else { + // Minimum (about -510.7) rounds to -511. + clock_drift -= 0.5; + + // When the offset is negative or zero (-511 to 0), + // the absolute offset is masked, i.e. for the minimum + // offset (-511), 511 pulses are masked. + w.set_calp(Calp::NOCHANGE); + w.set_calm((clock_drift * -1.0) as u16); + } + }); }) } @@ -150,29 +144,26 @@ impl<'d, T: Instance> super::Rtc<'d, T> { let r = T::regs(); // Disable write protection. // This is safe, as we're only writin the correct and expected values. - unsafe { - r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); - r.wpr().write(|w| w.set_key(Key::DEACTIVATE2)); + r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); + r.wpr().write(|w| w.set_key(Key::DEACTIVATE2)); - if init_mode && !r.icsr().read().initf() { - r.icsr().modify(|w| w.set_init(Init::INITMODE)); - // wait till init state entered - // ~2 RTCCLK cycles - while !r.icsr().read().initf() {} - } + if init_mode && !r.icsr().read().initf() { + r.icsr().modify(|w| w.set_init(Init::INITMODE)); + // wait till init state entered + // ~2 RTCCLK cycles + while !r.icsr().read().initf() {} } let result = f(&r); - unsafe { - if init_mode { - r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode - } - - // Re-enable write protection. - // This is safe, as the field accepts the full range of 8-bit values. - r.wpr().write(|w| w.set_key(Key::ACTIVATE)); + if init_mode { + r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode } + + // Re-enable write protection. + // This is safe, as the field accepts the full range of 8-bit values. + r.wpr().write(|w| w.set_key(Key::ACTIVATE)); + result } } @@ -192,7 +183,7 @@ impl sealed::Instance for crate::peripherals::RTC { fn write_backup_register(_rtc: &Rtc, register: usize, _value: u32) { if register < Self::BACKUP_REGISTER_COUNT { // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC - //unsafe { self.rtc.bkpr()[register].write(|w| w.bits(value)) } + //self.rtc.bkpr()[register].write(|w| w.bits(value)) } } } diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 28eb49ab6..80a336a48 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -28,17 +28,14 @@ pub struct InterruptHandler { impl InterruptHandler { fn data_interrupts(enable: bool) { let regs = T::regs(); - // NOTE(unsafe) Atomic write - unsafe { - regs.maskr().write(|w| { - w.set_dcrcfailie(enable); - w.set_dtimeoutie(enable); - w.set_dataendie(enable); + regs.maskr().write(|w| { + w.set_dcrcfailie(enable); + w.set_dtimeoutie(enable); + w.set_dataendie(enable); - #[cfg(sdmmc_v2)] - w.set_dabortie(enable); - }); - } + #[cfg(sdmmc_v2)] + w.set_dabortie(enable); + }); } } @@ -285,7 +282,7 @@ impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> { ) -> Self { into_ref!(clk, cmd, d0); - critical_section::with(|_| unsafe { + critical_section::with(|_| { clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); @@ -322,7 +319,7 @@ impl<'d, T: Instance, Dma: SdmmcDma> Sdmmc<'d, T, Dma> { ) -> Self { into_ref!(clk, cmd, d0, d1, d2, d3); - critical_section::with(|_| unsafe { + critical_section::with(|_| { clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); @@ -364,7 +361,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { ) -> Self { into_ref!(clk, cmd, d0); - critical_section::with(|_| unsafe { + critical_section::with(|_| { clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); @@ -400,7 +397,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { ) -> Self { into_ref!(clk, cmd, d0, d1, d2, d3); - critical_section::with(|_| unsafe { + critical_section::with(|_| { clk.set_as_af_pull(clk.af_num(), AFType::OutputPushPull, Pull::None); cmd.set_as_af_pull(cmd.af_num(), AFType::OutputPushPull, Pull::Up); d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::Up); @@ -451,26 +448,24 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { unsafe { T::Interrupt::enable() }; let regs = T::regs(); - unsafe { - regs.clkcr().write(|w| { - w.set_pwrsav(false); - w.set_negedge(false); + regs.clkcr().write(|w| { + w.set_pwrsav(false); + w.set_negedge(false); - // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors. - // See chip erratas for more details. - #[cfg(sdmmc_v1)] - w.set_hwfc_en(false); - #[cfg(sdmmc_v2)] - w.set_hwfc_en(true); + // Hardware flow control is broken on SDIOv1 and causes clock glitches, which result in CRC errors. + // See chip erratas for more details. + #[cfg(sdmmc_v1)] + w.set_hwfc_en(false); + #[cfg(sdmmc_v2)] + w.set_hwfc_en(true); - #[cfg(sdmmc_v1)] - w.set_clken(true); - }); + #[cfg(sdmmc_v1)] + w.set_clken(true); + }); - // Power off, writen 00: Clock to the card is stopped; - // D[7:0], CMD, and CK are driven high. - regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); - } + // Power off, writen 00: Clock to the card is stopped; + // D[7:0], CMD, and CK are driven high. + regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); Self { _peri: sdmmc, @@ -495,14 +490,11 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { fn data_active() -> bool { let regs = T::regs(); - // NOTE(unsafe) Atomic read with no side-effects - unsafe { - let status = regs.star().read(); - #[cfg(sdmmc_v1)] - return status.rxact() || status.txact(); - #[cfg(sdmmc_v2)] - return status.dpsmact(); - } + let status = regs.star().read(); + #[cfg(sdmmc_v1)] + return status.rxact() || status.txact(); + #[cfg(sdmmc_v2)] + return status.dpsmact(); } /// Coammand transfer is in progress @@ -510,14 +502,11 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { fn cmd_active() -> bool { let regs = T::regs(); - // NOTE(unsafe) Atomic read with no side-effects - unsafe { - let status = regs.star().read(); - #[cfg(sdmmc_v1)] - return status.cmdact(); - #[cfg(sdmmc_v2)] - return status.cpsmact(); - } + let status = regs.star().read(); + #[cfg(sdmmc_v1)] + return status.cmdact(); + #[cfg(sdmmc_v2)] + return status.cpsmact(); } /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) @@ -542,44 +531,41 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::wait_idle(); Self::clear_interrupt_flags(); - // NOTE(unsafe) We have exclusive access to the regisers - unsafe { - regs.dtimer() - .write(|w| w.set_datatime(self.config.data_transfer_timeout)); - regs.dlenr().write(|w| w.set_datalength(length_bytes)); + regs.dtimer() + .write(|w| w.set_datatime(self.config.data_transfer_timeout)); + regs.dlenr().write(|w| w.set_datalength(length_bytes)); + #[cfg(sdmmc_v1)] + let transfer = unsafe { + let request = self.dma.request(); + Transfer::new_read( + &mut self.dma, + request, + regs.fifor().as_ptr() as *mut u32, + buffer, + DMA_TRANSFER_OPTIONS, + ) + }; + #[cfg(sdmmc_v2)] + let transfer = { + regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); + regs.idmactrlr().modify(|w| w.set_idmaen(true)); + Transfer { + _dummy: core::marker::PhantomData, + } + }; + + regs.dctrl().modify(|w| { + w.set_dblocksize(block_size); + w.set_dtdir(true); #[cfg(sdmmc_v1)] - let transfer = { - let request = self.dma.request(); - Transfer::new_read( - &mut self.dma, - request, - regs.fifor().ptr() as *mut u32, - buffer, - DMA_TRANSFER_OPTIONS, - ) - }; - #[cfg(sdmmc_v2)] - let transfer = { - regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); - regs.idmactrlr().modify(|w| w.set_idmaen(true)); - Transfer { - _dummy: core::marker::PhantomData, - } - }; + { + w.set_dmaen(true); + w.set_dten(true); + } + }); - regs.dctrl().modify(|w| { - w.set_dblocksize(block_size); - w.set_dtdir(true); - #[cfg(sdmmc_v1)] - { - w.set_dmaen(true); - w.set_dten(true); - } - }); - - transfer - } + transfer } /// # Safety @@ -598,59 +584,54 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::wait_idle(); Self::clear_interrupt_flags(); - // NOTE(unsafe) We have exclusive access to the regisers - unsafe { - regs.dtimer() - .write(|w| w.set_datatime(self.config.data_transfer_timeout)); - regs.dlenr().write(|w| w.set_datalength(length_bytes)); + regs.dtimer() + .write(|w| w.set_datatime(self.config.data_transfer_timeout)); + regs.dlenr().write(|w| w.set_datalength(length_bytes)); + #[cfg(sdmmc_v1)] + let transfer = unsafe { + let request = self.dma.request(); + Transfer::new_write( + &mut self.dma, + request, + buffer, + regs.fifor().as_ptr() as *mut u32, + DMA_TRANSFER_OPTIONS, + ) + }; + #[cfg(sdmmc_v2)] + let transfer = { + regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32)); + regs.idmactrlr().modify(|w| w.set_idmaen(true)); + Transfer { + _dummy: core::marker::PhantomData, + } + }; + + regs.dctrl().modify(|w| { + w.set_dblocksize(block_size); + w.set_dtdir(false); #[cfg(sdmmc_v1)] - let transfer = { - let request = self.dma.request(); - Transfer::new_write( - &mut self.dma, - request, - buffer, - regs.fifor().ptr() as *mut u32, - DMA_TRANSFER_OPTIONS, - ) - }; - #[cfg(sdmmc_v2)] - let transfer = { - regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_ptr() as u32)); - regs.idmactrlr().modify(|w| w.set_idmaen(true)); - Transfer { - _dummy: core::marker::PhantomData, - } - }; + { + w.set_dmaen(true); + w.set_dten(true); + } + }); - regs.dctrl().modify(|w| { - w.set_dblocksize(block_size); - w.set_dtdir(false); - #[cfg(sdmmc_v1)] - { - w.set_dmaen(true); - w.set_dten(true); - } - }); - - transfer - } + transfer } /// Stops the DMA datapath fn stop_datapath() { let regs = T::regs(); - unsafe { - #[cfg(sdmmc_v1)] - regs.dctrl().modify(|w| { - w.set_dmaen(false); - w.set_dten(false); - }); - #[cfg(sdmmc_v2)] - regs.idmactrlr().modify(|w| w.set_idmaen(false)); - } + #[cfg(sdmmc_v1)] + regs.dctrl().modify(|w| { + w.set_dmaen(false); + w.set_dten(false); + }); + #[cfg(sdmmc_v2)] + regs.idmactrlr().modify(|w| w.set_idmaen(false)); } /// Sets the CLKDIV field in CLKCR. Updates clock field in self @@ -673,16 +654,13 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); self.clock = new_clock; - // NOTE(unsafe) We have exclusive access to the regblock - unsafe { - // CPSMACT and DPSMACT must be 0 to set CLKDIV - Self::wait_idle(); - regs.clkcr().modify(|w| { - w.set_clkdiv(clkdiv); - #[cfg(sdmmc_v1)] - w.set_bypass(_bypass); - }); - } + // CPSMACT and DPSMACT must be 0 to set CLKDIV + Self::wait_idle(); + regs.clkcr().modify(|w| { + w.set_clkdiv(clkdiv); + #[cfg(sdmmc_v1)] + w.set_bypass(_bypass); + }); Ok(()) } @@ -710,7 +688,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = self.prepare_datapath_read(&mut status, 64, 6); InterruptHandler::::data_interrupts(true); @@ -718,7 +696,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -769,8 +747,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::cmd(Cmd::card_status(rca << 16), false)?; // CMD13 - // NOTE(unsafe) Atomic read with no side-effects - let r1 = unsafe { regs.respr(0).read().cardstatus() }; + let r1 = regs.respr(0).read().cardstatus(); Ok(r1.into()) } @@ -786,7 +763,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = self.prepare_datapath_read(&mut status, 64, 6); InterruptHandler::::data_interrupts(true); @@ -794,7 +771,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -840,35 +817,32 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { #[inline(always)] fn clear_interrupt_flags() { let regs = T::regs(); - // NOTE(unsafe) Atomic write - unsafe { - regs.icr().write(|w| { - w.set_ccrcfailc(true); - w.set_dcrcfailc(true); - w.set_ctimeoutc(true); - w.set_dtimeoutc(true); - w.set_txunderrc(true); - w.set_rxoverrc(true); - w.set_cmdrendc(true); - w.set_cmdsentc(true); - w.set_dataendc(true); - w.set_dbckendc(true); - w.set_sdioitc(true); + regs.icr().write(|w| { + w.set_ccrcfailc(true); + w.set_dcrcfailc(true); + w.set_ctimeoutc(true); + w.set_dtimeoutc(true); + w.set_txunderrc(true); + w.set_rxoverrc(true); + w.set_cmdrendc(true); + w.set_cmdsentc(true); + w.set_dataendc(true); + w.set_dbckendc(true); + w.set_sdioitc(true); - #[cfg(sdmmc_v2)] - { - w.set_dholdc(true); - w.set_dabortc(true); - w.set_busyd0endc(true); - w.set_ackfailc(true); - w.set_acktimeoutc(true); - w.set_vswendc(true); - w.set_ckstopc(true); - w.set_idmatec(true); - w.set_idmabtcc(true); - } - }); - } + #[cfg(sdmmc_v2)] + { + w.set_dholdc(true); + w.set_dabortc(true); + w.set_busyd0endc(true); + w.set_ackfailc(true); + w.set_acktimeoutc(true); + w.set_vswendc(true); + w.set_ckstopc(true); + w.set_idmatec(true); + w.set_idmabtcc(true); + } + }); } async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { @@ -880,7 +854,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3); InterruptHandler::::data_interrupts(true); @@ -888,7 +862,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -921,59 +895,53 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let regs = T::regs(); Self::clear_interrupt_flags(); - // NOTE(safety) Atomic operations - unsafe { - // CP state machine must be idle - while Self::cmd_active() {} + // CP state machine must be idle + while Self::cmd_active() {} - // Command arg - regs.argr().write(|w| w.set_cmdarg(cmd.arg)); + // Command arg + regs.argr().write(|w| w.set_cmdarg(cmd.arg)); - // Command index and start CP State Machine - regs.cmdr().write(|w| { - w.set_waitint(false); - w.set_waitresp(cmd.resp as u8); - w.set_cmdindex(cmd.cmd); - w.set_cpsmen(true); + // Command index and start CP State Machine + regs.cmdr().write(|w| { + w.set_waitint(false); + w.set_waitresp(cmd.resp as u8); + w.set_cmdindex(cmd.cmd); + w.set_cpsmen(true); - #[cfg(sdmmc_v2)] - { - // Special mode in CP State Machine - // CMD12: Stop Transmission - let cpsm_stop_transmission = cmd.cmd == 12; - w.set_cmdstop(cpsm_stop_transmission); - w.set_cmdtrans(data); - } - }); - - let mut status; - if cmd.resp == Response::None { - // Wait for CMDSENT or a timeout - while { - status = regs.star().read(); - !(status.ctimeout() || status.cmdsent()) - } {} - } else { - // Wait for CMDREND or CCRCFAIL or a timeout - while { - status = regs.star().read(); - !(status.ctimeout() || status.cmdrend() || status.ccrcfail()) - } {} + #[cfg(sdmmc_v2)] + { + // Special mode in CP State Machine + // CMD12: Stop Transmission + let cpsm_stop_transmission = cmd.cmd == 12; + w.set_cmdstop(cpsm_stop_transmission); + w.set_cmdtrans(data); } + }); - if status.ctimeout() { - return Err(Error::Timeout); - } else if status.ccrcfail() { - return Err(Error::Crc); - } - Ok(()) + let mut status; + if cmd.resp == Response::None { + // Wait for CMDSENT or a timeout + while { + status = regs.star().read(); + !(status.ctimeout() || status.cmdsent()) + } {} + } else { + // Wait for CMDREND or CCRCFAIL or a timeout + while { + status = regs.star().read(); + !(status.ctimeout() || status.cmdrend() || status.ccrcfail()) + } {} } + + if status.ctimeout() { + return Err(Error::Timeout); + } else if status.ccrcfail() { + return Err(Error::Crc); + } + Ok(()) } - /// # Safety - /// - /// Ensure that `regs` has exclusive access to the regblocks - unsafe fn on_drop() { + fn on_drop() { let regs = T::regs(); if Self::data_active() { Self::clear_interrupt_flags(); @@ -1017,141 +985,138 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { false => BusWidth::One, }; - // NOTE(unsafe) We have exclusive access to the peripheral - unsafe { - // While the SD/SDIO card or eMMC is in identification mode, - // the SDMMC_CK frequency must be no more than 400 kHz. - let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0)); - self.clock = init_clock; + // While the SD/SDIO card or eMMC is in identification mode, + // the SDMMC_CK frequency must be no more than 400 kHz. + let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0)); + self.clock = init_clock; - // CPSMACT and DPSMACT must be 0 to set WIDBUS - Self::wait_idle(); + // CPSMACT and DPSMACT must be 0 to set WIDBUS + Self::wait_idle(); - regs.clkcr().modify(|w| { - w.set_widbus(0); - w.set_clkdiv(clkdiv); - #[cfg(sdmmc_v1)] - w.set_bypass(_bypass); - }); + regs.clkcr().modify(|w| { + w.set_widbus(0); + w.set_clkdiv(clkdiv); + #[cfg(sdmmc_v1)] + w.set_bypass(_bypass); + }); - regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); - Self::cmd(Cmd::idle(), false)?; + regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); + Self::cmd(Cmd::idle(), false)?; - // Check if cards supports CMD8 (with pattern) - Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?; - let r1 = regs.respr(0).read().cardstatus(); + // Check if cards supports CMD8 (with pattern) + Self::cmd(Cmd::hs_send_ext_csd(0x1AA), false)?; + let r1 = regs.respr(0).read().cardstatus(); - let mut card = if r1 == 0x1AA { - // Card echoed back the pattern. Must be at least v2 - Card::default() - } else { - return Err(Error::UnsupportedCardVersion); - }; + let mut card = if r1 == 0x1AA { + // Card echoed back the pattern. Must be at least v2 + Card::default() + } else { + return Err(Error::UnsupportedCardVersion); + }; - let ocr = loop { - // Signal that next command is a app command - Self::cmd(Cmd::app_cmd(0), false)?; // CMD55 + let ocr = loop { + // Signal that next command is a app command + Self::cmd(Cmd::app_cmd(0), false)?; // CMD55 - let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32 - | CmdAppOper::HIGH_CAPACITY as u32 - | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32; + let arg = CmdAppOper::VOLTAGE_WINDOW_SD as u32 + | CmdAppOper::HIGH_CAPACITY as u32 + | CmdAppOper::SD_SWITCH_1_8V_CAPACITY as u32; - // Initialize card - match Self::cmd(Cmd::app_op_cmd(arg), false) { - // ACMD41 - Ok(_) => (), - Err(Error::Crc) => (), - Err(err) => return Err(err), - } - let ocr: OCR = regs.respr(0).read().cardstatus().into(); - if !ocr.is_busy() { - // Power up done - break ocr; - } - }; - - if ocr.high_capacity() { - // Card is SDHC or SDXC or SDUC - card.card_type = CardCapacity::SDHC; - } else { - card.card_type = CardCapacity::SDSC; + // Initialize card + match Self::cmd(Cmd::app_op_cmd(arg), false) { + // ACMD41 + Ok(_) => (), + Err(Error::Crc) => (), + Err(err) => return Err(err), } - card.ocr = ocr; - - Self::cmd(Cmd::all_send_cid(), false)?; // CMD2 - let cid0 = regs.respr(0).read().cardstatus() as u128; - let cid1 = regs.respr(1).read().cardstatus() as u128; - let cid2 = regs.respr(2).read().cardstatus() as u128; - let cid3 = regs.respr(3).read().cardstatus() as u128; - let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); - card.cid = cid.into(); - - Self::cmd(Cmd::send_rel_addr(), false)?; - card.rca = regs.respr(0).read().cardstatus() >> 16; - - Self::cmd(Cmd::send_csd(card.rca << 16), false)?; - let csd0 = regs.respr(0).read().cardstatus() as u128; - let csd1 = regs.respr(1).read().cardstatus() as u128; - let csd2 = regs.respr(2).read().cardstatus() as u128; - let csd3 = regs.respr(3).read().cardstatus() as u128; - let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3); - card.csd = csd.into(); - - self.select_card(Some(&card))?; - - self.get_scr(&mut card).await?; - - // Set bus width - let (width, acmd_arg) = match bus_width { - BusWidth::Eight => unimplemented!(), - BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2), - _ => (BusWidth::One, 0), - }; - Self::cmd(Cmd::app_cmd(card.rca << 16), false)?; - Self::cmd(Cmd::cmd6(acmd_arg), false)?; - - // CPSMACT and DPSMACT must be 0 to set WIDBUS - Self::wait_idle(); - - regs.clkcr().modify(|w| { - w.set_widbus(match width { - BusWidth::One => 0, - BusWidth::Four => 1, - BusWidth::Eight => 2, - _ => panic!("Invalid Bus Width"), - }) - }); - - // Set Clock - if freq.0 <= 25_000_000 { - // Final clock frequency - self.clkcr_set_clkdiv(freq.0, width)?; - } else { - // Switch to max clock for SDR12 - self.clkcr_set_clkdiv(25_000_000, width)?; + let ocr: OCR = regs.respr(0).read().cardstatus().into(); + if !ocr.is_busy() { + // Power up done + break ocr; } + }; - self.card = Some(card); - - // Read status - self.read_sd_status().await?; - - if freq.0 > 25_000_000 { - // Switch to SDR25 - self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; - - if self.signalling == Signalling::SDR25 { - // Set final clock frequency - self.clkcr_set_clkdiv(freq.0, width)?; - - if self.read_status(&card)?.state() != CurrentState::Transfer { - return Err(Error::SignalingSwitchFailed); - } - } - } - // Read status after signalling change - self.read_sd_status().await?; + if ocr.high_capacity() { + // Card is SDHC or SDXC or SDUC + card.card_type = CardCapacity::SDHC; + } else { + card.card_type = CardCapacity::SDSC; } + card.ocr = ocr; + + Self::cmd(Cmd::all_send_cid(), false)?; // CMD2 + let cid0 = regs.respr(0).read().cardstatus() as u128; + let cid1 = regs.respr(1).read().cardstatus() as u128; + let cid2 = regs.respr(2).read().cardstatus() as u128; + let cid3 = regs.respr(3).read().cardstatus() as u128; + let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); + card.cid = cid.into(); + + Self::cmd(Cmd::send_rel_addr(), false)?; + card.rca = regs.respr(0).read().cardstatus() >> 16; + + Self::cmd(Cmd::send_csd(card.rca << 16), false)?; + let csd0 = regs.respr(0).read().cardstatus() as u128; + let csd1 = regs.respr(1).read().cardstatus() as u128; + let csd2 = regs.respr(2).read().cardstatus() as u128; + let csd3 = regs.respr(3).read().cardstatus() as u128; + let csd = (csd0 << 96) | (csd1 << 64) | (csd2 << 32) | (csd3); + card.csd = csd.into(); + + self.select_card(Some(&card))?; + + self.get_scr(&mut card).await?; + + // Set bus width + let (width, acmd_arg) = match bus_width { + BusWidth::Eight => unimplemented!(), + BusWidth::Four if card.scr.bus_width_four() => (BusWidth::Four, 2), + _ => (BusWidth::One, 0), + }; + Self::cmd(Cmd::app_cmd(card.rca << 16), false)?; + Self::cmd(Cmd::cmd6(acmd_arg), false)?; + + // CPSMACT and DPSMACT must be 0 to set WIDBUS + Self::wait_idle(); + + regs.clkcr().modify(|w| { + w.set_widbus(match width { + BusWidth::One => 0, + BusWidth::Four => 1, + BusWidth::Eight => 2, + _ => panic!("Invalid Bus Width"), + }) + }); + + // Set Clock + if freq.0 <= 25_000_000 { + // Final clock frequency + self.clkcr_set_clkdiv(freq.0, width)?; + } else { + // Switch to max clock for SDR12 + self.clkcr_set_clkdiv(25_000_000, width)?; + } + + self.card = Some(card); + + // Read status + self.read_sd_status().await?; + + if freq.0 > 25_000_000 { + // Switch to SDR25 + self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; + + if self.signalling == Signalling::SDR25 { + // Set final clock frequency + self.clkcr_set_clkdiv(freq.0, width)?; + + if self.read_status(&card)?.state() != CurrentState::Transfer { + return Err(Error::SignalingSwitchFailed); + } + } + } + // Read status after signalling change + self.read_sd_status().await?; Ok(()) } @@ -1172,7 +1137,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = self.prepare_datapath_read(buffer, 512, 9); InterruptHandler::::data_interrupts(true); @@ -1180,7 +1145,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -1217,7 +1182,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::cmd(Cmd::set_block_length(512), false)?; // CMD16 let regs = T::regs(); - let on_drop = OnDrop::new(|| unsafe { Self::on_drop() }); + let on_drop = OnDrop::new(|| Self::on_drop()); // sdmmc_v1 uses different cmd/dma order than v2, but only for writes #[cfg(sdmmc_v1)] @@ -1231,7 +1196,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let res = poll_fn(|cx| { T::state().register(cx.waker()); - let status = unsafe { regs.star().read() }; + let status = regs.star().read(); if status.dcrcfail() { return Poll::Ready(Err(Error::Crc)); @@ -1289,9 +1254,9 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { impl<'d, T: Instance, Dma: SdmmcDma + 'd> Drop for Sdmmc<'d, T, Dma> { fn drop(&mut self) { T::Interrupt::disable(); - unsafe { Self::on_drop() }; + Self::on_drop(); - critical_section::with(|_| unsafe { + critical_section::with(|_| { self.clk.set_as_disconnected(); self.cmd.set_as_disconnected(); self.d0.set_as_disconnected(); diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 580971e45..1cddac992 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -98,14 +98,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { Polarity::IdleHigh => Pull::Up, }; - unsafe { - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode); - sck.set_speed(crate::gpio::Speed::VeryHigh); - mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); - mosi.set_speed(crate::gpio::Speed::VeryHigh); - miso.set_as_af(miso.af_num(), AFType::Input); - miso.set_speed(crate::gpio::Speed::VeryHigh); - } + sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, sck_pull_mode); + sck.set_speed(crate::gpio::Speed::VeryHigh); + mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); + mosi.set_speed(crate::gpio::Speed::VeryHigh); + miso.set_as_af(miso.af_num(), AFType::Input); + miso.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( peri, @@ -129,12 +127,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { config: Config, ) -> Self { into_ref!(sck, miso); - unsafe { - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); - sck.set_speed(crate::gpio::Speed::VeryHigh); - miso.set_as_af(miso.af_num(), AFType::Input); - miso.set_speed(crate::gpio::Speed::VeryHigh); - } + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + miso.set_as_af(miso.af_num(), AFType::Input); + miso.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( peri, @@ -158,12 +154,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { config: Config, ) -> Self { into_ref!(sck, mosi); - unsafe { - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); - sck.set_speed(crate::gpio::Speed::VeryHigh); - mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); - mosi.set_speed(crate::gpio::Speed::VeryHigh); - } + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); + mosi.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( peri, @@ -186,10 +180,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { config: Config, ) -> Self { into_ref!(mosi); - unsafe { - mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); - mosi.set_speed(crate::gpio::Speed::Medium); - } + mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); + mosi.set_speed(crate::gpio::Speed::Medium); Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config) } @@ -247,7 +239,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { T::reset(); #[cfg(any(spi_v1, spi_f1))] - unsafe { + { T::REGS.cr2().modify(|w| { w.set_ssoe(false); }); @@ -270,7 +262,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } #[cfg(spi_v2)] - unsafe { + { T::REGS.cr2().modify(|w| { let (ds, frxth) = ::CONFIG; w.set_frxth(frxth); @@ -292,7 +284,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } #[cfg(any(spi_v3, spi_v4, spi_v5))] - unsafe { + { T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff); T::REGS.cfg2().modify(|w| { //w.set_ssoe(true); @@ -343,29 +335,25 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { let lsbfirst = config.raw_byte_order(); #[cfg(any(spi_v1, spi_f1, spi_v2))] - unsafe { - T::REGS.cr1().modify(|w| { - w.set_cpha(cpha); - w.set_cpol(cpol); - w.set_lsbfirst(lsbfirst); - }); - } + T::REGS.cr1().modify(|w| { + w.set_cpha(cpha); + w.set_cpol(cpol); + w.set_lsbfirst(lsbfirst); + }); #[cfg(any(spi_v3, spi_v4, spi_v5))] - unsafe { - T::REGS.cfg2().modify(|w| { - w.set_cpha(cpha); - w.set_cpol(cpol); - w.set_lsbfirst(lsbfirst); - }); - } + T::REGS.cfg2().modify(|w| { + w.set_cpha(cpha); + w.set_cpol(cpol); + w.set_lsbfirst(lsbfirst); + }); } pub fn get_current_config(&self) -> Config { #[cfg(any(spi_v1, spi_f1, spi_v2))] - let cfg = unsafe { T::REGS.cr1().read() }; + let cfg = T::REGS.cr1().read(); #[cfg(any(spi_v3, spi_v4, spi_v5))] - let cfg = unsafe { T::REGS.cfg2().read() }; + let cfg = T::REGS.cfg2().read(); let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { Polarity::IdleLow } else { @@ -395,7 +383,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } #[cfg(any(spi_v1, spi_f1))] - unsafe { + { T::REGS.cr1().modify(|reg| { reg.set_spe(false); reg.set_dff(word_size) @@ -405,7 +393,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } #[cfg(spi_v2)] - unsafe { + { T::REGS.cr1().modify(|w| { w.set_spe(false); }); @@ -418,7 +406,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } #[cfg(any(spi_v3, spi_v4, spi_v5))] - unsafe { + { T::REGS.cr1().modify(|w| { w.set_csusp(true); }); @@ -447,26 +435,22 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } self.set_word_size(W::CONFIG); - unsafe { - T::REGS.cr1().modify(|w| { - w.set_spe(false); - }); - } + T::REGS.cr1().modify(|w| { + w.set_spe(false); + }); let tx_request = self.txdma.request(); let tx_dst = T::REGS.tx_ptr(); let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) }; - unsafe { - set_txdmaen(T::REGS, true); - T::REGS.cr1().modify(|w| { - w.set_spe(true); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - T::REGS.cr1().modify(|w| { - w.set_cstart(true); - }); - } + set_txdmaen(T::REGS, true); + T::REGS.cr1().modify(|w| { + w.set_spe(true); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + T::REGS.cr1().modify(|w| { + w.set_cstart(true); + }); tx_f.await; @@ -485,11 +469,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } self.set_word_size(W::CONFIG); - unsafe { - T::REGS.cr1().modify(|w| { - w.set_spe(false); - }); - } + T::REGS.cr1().modify(|w| { + w.set_spe(false); + }); // SPIv3 clears rxfifo on SPE=0 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] @@ -517,16 +499,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { ) }; - unsafe { - set_txdmaen(T::REGS, true); - T::REGS.cr1().modify(|w| { - w.set_spe(true); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - T::REGS.cr1().modify(|w| { - w.set_cstart(true); - }); - } + set_txdmaen(T::REGS, true); + T::REGS.cr1().modify(|w| { + w.set_spe(true); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + T::REGS.cr1().modify(|w| { + w.set_cstart(true); + }); join(tx_f, rx_f).await; @@ -548,11 +528,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } self.set_word_size(W::CONFIG); - unsafe { - T::REGS.cr1().modify(|w| { - w.set_spe(false); - }); - } + T::REGS.cr1().modify(|w| { + w.set_spe(false); + }); // SPIv3 clears rxfifo on SPE=0 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] @@ -568,16 +546,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { let tx_dst = T::REGS.tx_ptr(); let tx_f = unsafe { Transfer::new_write_raw(&mut self.txdma, tx_request, write, tx_dst, Default::default()) }; - unsafe { - set_txdmaen(T::REGS, true); - T::REGS.cr1().modify(|w| { - w.set_spe(true); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - T::REGS.cr1().modify(|w| { - w.set_cstart(true); - }); - } + set_txdmaen(T::REGS, true); + T::REGS.cr1().modify(|w| { + w.set_spe(true); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + T::REGS.cr1().modify(|w| { + w.set_cstart(true); + }); join(tx_f, rx_f).await; @@ -603,7 +579,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } pub fn blocking_write(&mut self, words: &[W]) -> Result<(), Error> { - unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } + T::REGS.cr1().modify(|w| w.set_spe(true)); flush_rx_fifo(T::REGS); self.set_word_size(W::CONFIG); for word in words.iter() { @@ -613,7 +589,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } pub fn blocking_read(&mut self, words: &mut [W]) -> Result<(), Error> { - unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } + T::REGS.cr1().modify(|w| w.set_spe(true)); flush_rx_fifo(T::REGS); self.set_word_size(W::CONFIG); for word in words.iter_mut() { @@ -623,7 +599,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } pub fn blocking_transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> { - unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } + T::REGS.cr1().modify(|w| w.set_spe(true)); flush_rx_fifo(T::REGS); self.set_word_size(W::CONFIG); for word in words.iter_mut() { @@ -633,7 +609,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } pub fn blocking_transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { - unsafe { T::REGS.cr1().modify(|w| w.set_spe(true)) } + T::REGS.cr1().modify(|w| w.set_spe(true)); flush_rx_fifo(T::REGS); self.set_word_size(W::CONFIG); let len = read.len().max(write.len()); @@ -650,11 +626,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { fn drop(&mut self) { - unsafe { - self.sck.as_ref().map(|x| x.set_as_disconnected()); - self.mosi.as_ref().map(|x| x.set_as_disconnected()); - self.miso.as_ref().map(|x| x.set_as_disconnected()); - } + self.sck.as_ref().map(|x| x.set_as_disconnected()); + self.mosi.as_ref().map(|x| x.set_as_disconnected()); + self.miso.as_ref().map(|x| x.set_as_disconnected()); } } @@ -690,7 +664,7 @@ impl RegsExt for Regs { let dr = self.dr(); #[cfg(any(spi_v3, spi_v4, spi_v5))] let dr = self.txdr(); - dr.ptr() as *mut W + dr.as_ptr() as *mut W } fn rx_ptr(&self) -> *mut W { @@ -698,7 +672,7 @@ impl RegsExt for Regs { let dr = self.dr(); #[cfg(any(spi_v3, spi_v4, spi_v5))] let dr = self.rxdr(); - dr.ptr() as *mut W + dr.as_ptr() as *mut W } } @@ -731,7 +705,7 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> { fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> { loop { - let sr = unsafe { regs.sr().read() }; + let sr = regs.sr().read(); check_error_flags(sr)?; @@ -748,7 +722,7 @@ fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> { fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { loop { - let sr = unsafe { regs.sr().read() }; + let sr = regs.sr().read(); check_error_flags(sr)?; @@ -764,72 +738,64 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { } fn flush_rx_fifo(regs: Regs) { - unsafe { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - while regs.sr().read().rxne() { - let _ = regs.dr().read(); - } - #[cfg(any(spi_v3, spi_v4, spi_v5))] - while regs.sr().read().rxp() { - let _ = regs.rxdr().read(); - } + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + while regs.sr().read().rxne() { + let _ = regs.dr().read(); + } + #[cfg(any(spi_v3, spi_v4, spi_v5))] + while regs.sr().read().rxp() { + let _ = regs.rxdr().read(); } } fn set_txdmaen(regs: Regs, val: bool) { - unsafe { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - regs.cr2().modify(|reg| { - reg.set_txdmaen(val); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - regs.cfg1().modify(|reg| { - reg.set_txdmaen(val); - }); - } + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + regs.cr2().modify(|reg| { + reg.set_txdmaen(val); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + regs.cfg1().modify(|reg| { + reg.set_txdmaen(val); + }); } fn set_rxdmaen(regs: Regs, val: bool) { - unsafe { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - regs.cr2().modify(|reg| { - reg.set_rxdmaen(val); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - regs.cfg1().modify(|reg| { - reg.set_rxdmaen(val); - }); - } + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + regs.cr2().modify(|reg| { + reg.set_rxdmaen(val); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + regs.cfg1().modify(|reg| { + reg.set_rxdmaen(val); + }); } fn finish_dma(regs: Regs) { - unsafe { - #[cfg(spi_v2)] - while regs.sr().read().ftlvl() > 0 {} + #[cfg(spi_v2)] + while regs.sr().read().ftlvl() > 0 {} - #[cfg(any(spi_v3, spi_v4, spi_v5))] - while !regs.sr().read().txc() {} - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - while regs.sr().read().bsy() {} + #[cfg(any(spi_v3, spi_v4, spi_v5))] + while !regs.sr().read().txc() {} + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + while regs.sr().read().bsy() {} - // Disable the spi peripheral - regs.cr1().modify(|w| { - w.set_spe(false); - }); + // Disable the spi peripheral + regs.cr1().modify(|w| { + w.set_spe(false); + }); - // The peripheral automatically disables the DMA stream on completion without error, - // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] - regs.cr2().modify(|reg| { - reg.set_txdmaen(false); - reg.set_rxdmaen(false); - }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] - regs.cfg1().modify(|reg| { - reg.set_txdmaen(false); - reg.set_rxdmaen(false); - }); - } + // The peripheral automatically disables the DMA stream on completion without error, + // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. + #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + regs.cr2().modify(|reg| { + reg.set_txdmaen(false); + reg.set_rxdmaen(false); + }); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + regs.cfg1().modify(|reg| { + reg.set_txdmaen(false); + reg.set_rxdmaen(false); + }); } fn transfer_word(regs: Regs, tx_word: W) -> Result { diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index e82501a45..2622442f4 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -155,8 +155,7 @@ impl RtcDriver { let timer_freq = T::frequency(); - // NOTE(unsafe) Critical section to use the unsafe methods - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.cr1().modify(|w| w.set_cen(false)); r.cnt().write(|w| w.set_cnt(0)); @@ -184,7 +183,7 @@ impl RtcDriver { }); ::Interrupt::unpend(); - ::Interrupt::enable(); + unsafe { ::Interrupt::enable() }; r.cr1().modify(|w| w.set_cen(true)); }) @@ -193,9 +192,8 @@ impl RtcDriver { fn on_interrupt(&self) { let r = T::regs_gp16(); - // NOTE(unsafe) Use critical section to access the methods // XXX: reduce the size of this critical section ? - critical_section::with(|cs| unsafe { + critical_section::with(|cs| { let sr = r.sr().read(); let dier = r.dier().read(); @@ -228,7 +226,7 @@ impl RtcDriver { let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; let t = (period as u64) << 15; - critical_section::with(move |cs| unsafe { + critical_section::with(move |cs| { r.dier().modify(move |w| { for n in 0..ALARM_COUNT { let alarm = &self.alarms.borrow(cs)[n]; @@ -269,8 +267,7 @@ impl Driver for RtcDriver { let period = self.period.load(Ordering::Relaxed); compiler_fence(Ordering::Acquire); - // NOTE(unsafe) Atomic read with no side-effects - let counter = unsafe { r.cnt().read().cnt() }; + let counter = r.cnt().read().cnt(); calc_now(period, counter) } @@ -310,7 +307,7 @@ impl Driver for RtcDriver { if timestamp <= t { // If alarm timestamp has passed the alarm will not fire. // Disarm the alarm and return `false` to indicate that. - unsafe { r.dier().modify(|w| w.set_ccie(n + 1, false)) }; + r.dier().modify(|w| w.set_ccie(n + 1, false)); alarm.timestamp.set(u64::MAX); @@ -321,12 +318,11 @@ impl Driver for RtcDriver { // Write the CCR value regardless of whether we're going to enable it now or not. // This way, when we enable it later, the right value is already set. - unsafe { r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)) }; + r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)); // Enable it if it'll happen soon. Otherwise, `next_period` will enable it. let diff = timestamp - t; - // NOTE(unsafe) We're in a critical section - unsafe { r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)) }; + r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)); true }) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 14db97024..09b7a3776 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -60,25 +60,19 @@ macro_rules! impl_basic_16bit_timer { type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> crate::pac::timer::TimBasic { - crate::pac::timer::TimBasic(crate::pac::$inst.0) + unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } } fn start(&mut self) { - unsafe { - Self::regs().cr1().modify(|r| r.set_cen(true)); - } + Self::regs().cr1().modify(|r| r.set_cen(true)); } fn stop(&mut self) { - unsafe { - Self::regs().cr1().modify(|r| r.set_cen(false)); - } + Self::regs().cr1().modify(|r| r.set_cen(false)); } fn reset(&mut self) { - unsafe { - Self::regs().cnt().write(|r| r.set_cnt(0)); - } + Self::regs().cnt().write(|r| r.set_cnt(0)); } fn set_frequency(&mut self, frequency: Hertz) { @@ -90,35 +84,29 @@ macro_rules! impl_basic_16bit_timer { let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); let regs = Self::regs(); - unsafe { - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write(|r| r.set_arr(arr)); + regs.psc().write(|r| r.set_psc(psc)); + regs.arr().write(|r| r.set_arr(arr)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); } fn clear_update_interrupt(&mut self) -> bool { let regs = Self::regs(); - unsafe { - let sr = regs.sr().read(); - if sr.uif() { - regs.sr().modify(|r| { - r.set_uif(false); - }); - true - } else { - false - } + let sr = regs.sr().read(); + if sr.uif() { + regs.sr().modify(|r| { + r.set_uif(false); + }); + true + } else { + false } } fn enable_update_interrupt(&mut self, enable: bool) { - unsafe { - Self::regs().dier().write(|r| r.set_uie(enable)); - } + Self::regs().dier().write(|r| r.set_uie(enable)); } } }; @@ -141,14 +129,12 @@ macro_rules! impl_32bit_timer { let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into())); let regs = Self::regs_gp32(); - unsafe { - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write(|r| r.set_arr(arr)); + regs.psc().write(|r| r.set_psc(psc)); + regs.arr().write(|r| r.set_arr(arr)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); } } }; @@ -185,7 +171,7 @@ foreach_interrupt! { impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { fn regs_gp16() -> crate::pac::timer::TimGp16 { - crate::pac::timer::TimGp16(crate::pac::$inst.0) + unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } } @@ -206,7 +192,7 @@ foreach_interrupt! { impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { fn regs_gp16() -> crate::pac::timer::TimGp16 { - crate::pac::timer::TimGp16(crate::pac::$inst.0) + unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } } diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 086196a2c..433ad299c 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -19,68 +19,64 @@ impl interrupt::typelevel::Handler for Interrupt let state = T::buffered_state(); // RX - unsafe { - let sr = sr(r).read(); - // On v1 & v2, reading DR clears the rxne, error and idle interrupt - // flags. Keep this close to the SR read to reduce the chance of a - // flag being set in-between. - let dr = if sr.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr.ore() || sr.idle()) { - Some(rdr(r).read_volatile()) + let sr_val = sr(r).read(); + // On v1 & v2, reading DR clears the rxne, error and idle interrupt + // flags. Keep this close to the SR read to reduce the chance of a + // flag being set in-between. + let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) { + Some(rdr(r).read_volatile()) + } else { + None + }; + clear_interrupt_flags(r, sr_val); + + if sr_val.pe() { + warn!("Parity error"); + } + if sr_val.fe() { + warn!("Framing error"); + } + if sr_val.ne() { + warn!("Noise error"); + } + if sr_val.ore() { + warn!("Overrun error"); + } + if sr_val.rxne() { + let mut rx_writer = state.rx_buf.writer(); + let buf = rx_writer.push_slice(); + if !buf.is_empty() { + buf[0] = dr.unwrap(); + rx_writer.push_done(1); } else { - None - }; - clear_interrupt_flags(r, sr); - - if sr.pe() { - warn!("Parity error"); - } - if sr.fe() { - warn!("Framing error"); - } - if sr.ne() { - warn!("Noise error"); - } - if sr.ore() { - warn!("Overrun error"); - } - if sr.rxne() { - let mut rx_writer = state.rx_buf.writer(); - let buf = rx_writer.push_slice(); - if !buf.is_empty() { - buf[0] = dr.unwrap(); - rx_writer.push_done(1); - } else { - // FIXME: Should we disable any further RX interrupts when the buffer becomes full. - } - - if state.rx_buf.is_full() { - state.rx_waker.wake(); - } + // FIXME: Should we disable any further RX interrupts when the buffer becomes full. } - if sr.idle() { + if state.rx_buf.is_full() { state.rx_waker.wake(); } } + if sr_val.idle() { + state.rx_waker.wake(); + } + // TX - unsafe { - if sr(r).read().txe() { - let mut tx_reader = state.tx_buf.reader(); - let buf = tx_reader.pop_slice(); - if !buf.is_empty() { - r.cr1().modify(|w| { - w.set_txeie(true); - }); - tdr(r).write_volatile(buf[0].into()); - tx_reader.pop_done(1); - state.tx_waker.wake(); - } else { - // Disable interrupt until we have something to transmit again - r.cr1().modify(|w| { - w.set_txeie(false); - }); - } + if sr(r).read().txe() { + let mut tx_reader = state.tx_buf.reader(); + let buf = tx_reader.pop_slice(); + if !buf.is_empty() { + r.cr1().modify(|w| { + w.set_txeie(true); + }); + tdr(r).write_volatile(buf[0].into()); + tx_reader.pop_done(1); + state.tx_waker.wake(); + } else { + // Disable interrupt until we have something to transmit again + r.cr1().modify(|w| { + w.set_txeie(false); + }); } } } @@ -150,14 +146,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { T::enable(); T::reset(); - unsafe { - rts.set_as_af(rts.af_num(), AFType::OutputPushPull); - cts.set_as_af(cts.af_num(), AFType::Input); - T::regs().cr3().write(|w| { - w.set_rtse(true); - w.set_ctse(true); - }); - } + rts.set_as_af(rts.af_num(), AFType::OutputPushPull); + cts.set_as_af(cts.af_num(), AFType::Input); + T::regs().cr3().write(|w| { + w.set_rtse(true); + w.set_ctse(true); + }); Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) } @@ -178,12 +172,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { T::enable(); T::reset(); - unsafe { - de.set_as_af(de.af_num(), AFType::OutputPushPull); - T::regs().cr3().write(|w| { - w.set_dem(true); - }); - } + de.set_as_af(de.af_num(), AFType::OutputPushPull); + T::regs().cr3().write(|w| { + w.set_dem(true); + }); Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) } @@ -205,22 +197,18 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; let r = T::regs(); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); configure(r, &config, T::frequency(), T::KIND, true, true); - unsafe { - r.cr1().modify(|w| { - #[cfg(lpuart_v2)] - w.set_fifoen(true); + r.cr1().modify(|w| { + #[cfg(lpuart_v2)] + w.set_fifoen(true); - w.set_rxneie(true); - w.set_idleie(true); - }); - } + w.set_rxneie(true); + w.set_idleie(true); + }); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index da3644a81..47a79c187 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -36,35 +36,31 @@ impl interrupt::typelevel::Handler for Interrupt let r = T::regs(); let s = T::state(); - let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) }; + let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read()); let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie()); if has_errors { // clear all interrupts and DMA Rx Request - unsafe { - r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // disable parity interrupt - w.set_peie(false); - // disable idle line interrupt - w.set_idleie(false); - }); - r.cr3().modify(|w| { - // disable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(false); - // disable DMA Rx Request - w.set_dmar(false); - }); - } + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // disable parity interrupt + w.set_peie(false); + // disable idle line interrupt + w.set_idleie(false); + }); + r.cr3().modify(|w| { + // disable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(false); + // disable DMA Rx Request + w.set_dmar(false); + }); } else if cr1.idleie() && sr.idle() { // IDLE detected: no more data will come - unsafe { - r.cr1().modify(|w| { - // disable idle line detection - w.set_idleie(false); - }); - } + r.cr1().modify(|w| { + // disable idle line detection + w.set_idleie(false); + }); } else if cr1.rxneie() { // We cannot check the RXNE flag as it is auto-cleared by the DMA controller @@ -205,12 +201,10 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { T::enable(); T::reset(); - unsafe { - cts.set_as_af(cts.af_num(), AFType::Input); - T::regs().cr3().write(|w| { - w.set_ctse(true); - }); - } + cts.set_as_af(cts.af_num(), AFType::Input); + T::regs().cr3().write(|w| { + w.set_ctse(true); + }); Self::new_inner(peri, tx, tx_dma, config) } @@ -224,9 +218,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { let r = T::regs(); - unsafe { - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); configure(r, &config, T::frequency(), T::KIND, false, true); @@ -245,11 +237,9 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { { let ch = &mut self.tx_dma; let request = ch.request(); - unsafe { - T::regs().cr3().modify(|reg| { - reg.set_dmat(true); - }); - } + T::regs().cr3().modify(|reg| { + reg.set_dmat(true); + }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. let transfer = unsafe { Transfer::new_write(ch, request, buffer, tdr(T::regs()), Default::default()) }; @@ -258,21 +248,17 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { } pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { - unsafe { - let r = T::regs(); - for &b in buffer { - while !sr(r).read().txe() {} - tdr(r).write_volatile(b); - } + let r = T::regs(); + for &b in buffer { + while !sr(r).read().txe() {} + unsafe { tdr(r).write_volatile(b) }; } Ok(()) } pub fn blocking_flush(&mut self) -> Result<(), Error> { - unsafe { - let r = T::regs(); - while !sr(r).read().tc() {} - } + let r = T::regs(); + while !sr(r).read().tc() {} Ok(()) } } @@ -305,12 +291,10 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { T::enable(); T::reset(); - unsafe { - rts.set_as_af(rts.af_num(), AFType::OutputPushPull); - T::regs().cr3().write(|w| { - w.set_rtse(true); - }); - } + rts.set_as_af(rts.af_num(), AFType::OutputPushPull); + T::regs().cr3().write(|w| { + w.set_rtse(true); + }); Self::new_inner(peri, rx, rx_dma, config) } @@ -325,9 +309,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { let r = T::regs(); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - } + rx.set_as_af(rx.af_num(), AFType::Input); configure(r, &config, T::frequency(), T::KIND, true, false); @@ -347,7 +329,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { } #[cfg(any(usart_v1, usart_v2))] - unsafe fn check_rx_flags(&mut self) -> Result { + fn check_rx_flags(&mut self) -> Result { let r = T::regs(); loop { // Handle all buffered error flags. @@ -380,7 +362,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { } #[cfg(any(usart_v3, usart_v4))] - unsafe fn check_rx_flags(&mut self) -> Result { + fn check_rx_flags(&mut self) -> Result { let r = T::regs(); let sr = r.isr().read(); if sr.pe() { @@ -410,22 +392,18 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { pub fn nb_read(&mut self) -> Result> { let r = T::regs(); - unsafe { - if self.check_rx_flags()? { - Ok(rdr(r).read_volatile()) - } else { - Err(nb::Error::WouldBlock) - } + if self.check_rx_flags()? { + Ok(unsafe { rdr(r).read_volatile() }) + } else { + Err(nb::Error::WouldBlock) } } pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - unsafe { - let r = T::regs(); - for b in buffer { - while !self.check_rx_flags()? {} - *b = rdr(r).read_volatile(); - } + let r = T::regs(); + for b in buffer { + while !self.check_rx_flags()? {} + unsafe { *b = rdr(r).read_volatile() } } Ok(()) } @@ -451,23 +429,20 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { let on_drop = OnDrop::new(move || { // defmt::trace!("Clear all USART interrupts and DMA Read Request"); // clear all interrupts and DMA Rx Request - // SAFETY: only clears Rx related flags - unsafe { - r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // disable parity interrupt - w.set_peie(false); - // disable idle line interrupt - w.set_idleie(false); - }); - r.cr3().modify(|w| { - // disable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(false); - // disable DMA Rx Request - w.set_dmar(false); - }); - } + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // disable parity interrupt + w.set_peie(false); + // disable idle line interrupt + w.set_idleie(false); + }); + r.cr3().modify(|w| { + // disable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(false); + // disable DMA Rx Request + w.set_dmar(false); + }); }); let ch = &mut self.rx_dma; @@ -480,78 +455,74 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { // future which will complete when DMA Read request completes let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) }; - // SAFETY: The only way we might have a problem is using split rx and tx - // here we only modify or read Rx related flags, interrupts and DMA channel - unsafe { - // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer - if !self.detect_previous_overrun { - let sr = sr(r).read(); - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); + // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer + if !self.detect_previous_overrun { + let sr = sr(r).read(); + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); + } + + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // enable parity interrupt if not ParityNone + w.set_peie(w.pce()); + }); + + r.cr3().modify(|w| { + // enable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(true); + // enable DMA Rx Request + w.set_dmar(true); + }); + + compiler_fence(Ordering::SeqCst); + + // In case of errors already pending when reception started, interrupts may have already been raised + // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts + // have been disabled in interrupt handler and DMA Rx Request has been disabled. + + let cr3 = r.cr3().read(); + + if !cr3.dmar() { + // something went wrong + // because the only way to get this flag cleared is to have an interrupt + + // DMA will be stopped when transfer is dropped + + let sr = sr(r).read(); + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); + + if sr.pe() { + return Err(Error::Parity); + } + if sr.fe() { + return Err(Error::Framing); + } + if sr.ne() { + return Err(Error::Noise); + } + if sr.ore() { + return Err(Error::Overrun); } + unreachable!(); + } + + if enable_idle_line_detection { + // clear idle flag + let sr = sr(r).read(); + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); + + // enable idle interrupt r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // enable parity interrupt if not ParityNone - w.set_peie(w.pce()); + w.set_idleie(true); }); - - r.cr3().modify(|w| { - // enable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(true); - // enable DMA Rx Request - w.set_dmar(true); - }); - - compiler_fence(Ordering::SeqCst); - - // In case of errors already pending when reception started, interrupts may have already been raised - // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts - // have been disabled in interrupt handler and DMA Rx Request has been disabled. - - let cr3 = r.cr3().read(); - - if !cr3.dmar() { - // something went wrong - // because the only way to get this flag cleared is to have an interrupt - - // DMA will be stopped when transfer is dropped - - let sr = sr(r).read(); - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); - - if sr.pe() { - return Err(Error::Parity); - } - if sr.fe() { - return Err(Error::Framing); - } - if sr.ne() { - return Err(Error::Noise); - } - if sr.ore() { - return Err(Error::Overrun); - } - - unreachable!(); - } - - if enable_idle_line_detection { - // clear idle flag - let sr = sr(r).read(); - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); - - // enable idle interrupt - r.cr1().modify(|w| { - w.set_idleie(true); - }); - } } compiler_fence(Ordering::SeqCst); @@ -562,15 +533,11 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { s.rx_waker.register(cx.waker()); - // SAFETY: read only and we only use Rx related flags - let sr = unsafe { sr(r).read() }; + let sr = sr(r).read(); - // SAFETY: only clears Rx related flags - unsafe { - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); - } + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); compiler_fence(Ordering::SeqCst); @@ -677,14 +644,12 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { T::enable(); T::reset(); - unsafe { - rts.set_as_af(rts.af_num(), AFType::OutputPushPull); - cts.set_as_af(cts.af_num(), AFType::Input); - T::regs().cr3().write(|w| { - w.set_rtse(true); - w.set_ctse(true); - }); - } + rts.set_as_af(rts.af_num(), AFType::OutputPushPull); + cts.set_as_af(cts.af_num(), AFType::Input); + T::regs().cr3().write(|w| { + w.set_rtse(true); + w.set_ctse(true); + }); Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) } @@ -704,12 +669,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { T::enable(); T::reset(); - unsafe { - de.set_as_af(de.af_num(), AFType::OutputPushPull); - T::regs().cr3().write(|w| { - w.set_dem(true); - }); - } + de.set_as_af(de.af_num(), AFType::OutputPushPull); + T::regs().cr3().write(|w| { + w.set_dem(true); + }); Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) } @@ -725,10 +688,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { let r = T::regs(); - unsafe { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); configure(r, &config, T::frequency(), T::KIND, true, true); @@ -847,11 +808,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { over8 = true; let div = div as u32; - unsafe { - r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07))); - #[cfg(usart_v4)] - r.presc().write(|w| w.set_prescaler(_presc_val)); - } + r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07))); + #[cfg(usart_v4)] + r.presc().write(|w| w.set_prescaler(_presc_val)); found = Some(div); break; } @@ -860,11 +819,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: if div < brr_max { let div = div as u32; - unsafe { - r.brr().write_value(regs::Brr(div)); - #[cfg(usart_v4)] - r.presc().write(|w| w.set_prescaler(_presc_val)); - } + r.brr().write_value(regs::Brr(div)); + #[cfg(usart_v4)] + r.presc().write(|w| w.set_prescaler(_presc_val)); found = Some(div); break; } @@ -883,44 +840,42 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: pclk_freq.0 / div ); - unsafe { - r.cr2().write(|w| { - w.set_stop(match config.stop_bits { - StopBits::STOP0P5 => vals::Stop::STOP0P5, - StopBits::STOP1 => vals::Stop::STOP1, - StopBits::STOP1P5 => vals::Stop::STOP1P5, - StopBits::STOP2 => vals::Stop::STOP2, - }); + r.cr2().write(|w| { + w.set_stop(match config.stop_bits { + StopBits::STOP0P5 => vals::Stop::STOP0P5, + StopBits::STOP1 => vals::Stop::STOP1, + StopBits::STOP1P5 => vals::Stop::STOP1P5, + StopBits::STOP2 => vals::Stop::STOP2, }); - r.cr1().write(|w| { - // enable uart - w.set_ue(true); - // enable transceiver - w.set_te(enable_tx); - // enable receiver - w.set_re(enable_rx); - // configure word size - w.set_m0(if config.parity != Parity::ParityNone { - vals::M0::BIT9 - } else { - vals::M0::BIT8 - }); - // configure parity - w.set_pce(config.parity != Parity::ParityNone); - w.set_ps(match config.parity { - Parity::ParityOdd => vals::Ps::ODD, - Parity::ParityEven => vals::Ps::EVEN, - _ => vals::Ps::EVEN, - }); - #[cfg(not(usart_v1))] - w.set_over8(vals::Over8(over8 as _)); + }); + r.cr1().write(|w| { + // enable uart + w.set_ue(true); + // enable transceiver + w.set_te(enable_tx); + // enable receiver + w.set_re(enable_rx); + // configure word size + w.set_m0(if config.parity != Parity::ParityNone { + vals::M0::BIT9 + } else { + vals::M0::BIT8 + }); + // configure parity + w.set_pce(config.parity != Parity::ParityNone); + w.set_ps(match config.parity { + Parity::ParityOdd => vals::Ps::ODD, + Parity::ParityEven => vals::Ps::EVEN, + _ => vals::Ps::EVEN, }); - #[cfg(not(usart_v1))] - r.cr3().modify(|w| { - w.set_onebit(config.assume_noise_free); - }); - } + w.set_over8(vals::Over8(over8 as _)); + }); + + #[cfg(not(usart_v1))] + r.cr3().modify(|w| { + w.set_onebit(config.assume_noise_free); + }); } mod eh02 { @@ -1111,12 +1066,12 @@ use self::sealed::Kind; #[cfg(any(usart_v1, usart_v2))] fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { - r.dr().ptr() as _ + r.dr().as_ptr() as _ } #[cfg(any(usart_v1, usart_v2))] fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { - r.dr().ptr() as _ + r.dr().as_ptr() as _ } #[cfg(any(usart_v1, usart_v2))] @@ -1126,18 +1081,18 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg *mut u8 { - r.tdr().ptr() as _ + r.tdr().as_ptr() as _ } #[cfg(any(usart_v3, usart_v4))] fn rdr(r: Regs) -> *mut u8 { - r.rdr().ptr() as _ + r.rdr().as_ptr() as _ } #[cfg(any(usart_v3, usart_v4))] @@ -1147,7 +1102,7 @@ fn sr(r: Regs) -> crate::pac::common::Reg { #[cfg(any(usart_v3, usart_v4))] #[allow(unused)] -unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { +fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { r.icr().write(|w| *w = regs::Icr(sr.0)); } @@ -1214,7 +1169,7 @@ macro_rules! impl_usart { type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> Regs { - Regs(crate::pac::$inst.0) + unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } } fn state() -> &'static crate::usart::sealed::State { diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 511b71c7f..c74d7e092 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -59,23 +59,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma> RingBufferedUartRx<'d, T, RxD let r = T::regs(); // clear all interrupts and DMA Rx Request - // SAFETY: only clears Rx related flags - unsafe { - r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // enable parity interrupt if not ParityNone - w.set_peie(w.pce()); - // enable idle line interrupt - w.set_idleie(true); - }); - r.cr3().modify(|w| { - // enable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(true); - // enable DMA Rx Request - w.set_dmar(true); - }); - } + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // enable parity interrupt if not ParityNone + w.set_peie(w.pce()); + // enable idle line interrupt + w.set_idleie(true); + }); + r.cr3().modify(|w| { + // enable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(true); + // enable DMA Rx Request + w.set_dmar(true); + }); } /// Stop uart background receive @@ -84,23 +81,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma> RingBufferedUartRx<'d, T, RxD let r = T::regs(); // clear all interrupts and DMA Rx Request - // SAFETY: only clears Rx related flags - unsafe { - r.cr1().modify(|w| { - // disable RXNE interrupt - w.set_rxneie(false); - // disable parity interrupt - w.set_peie(false); - // disable idle line interrupt - w.set_idleie(false); - }); - r.cr3().modify(|w| { - // disable Error Interrupt: (Frame error, Noise error, Overrun error) - w.set_eie(false); - // disable DMA Rx Request - w.set_dmar(false); - }); - } + r.cr1().modify(|w| { + // disable RXNE interrupt + w.set_rxneie(false); + // disable parity interrupt + w.set_peie(false); + // disable idle line interrupt + w.set_idleie(false); + }); + r.cr3().modify(|w| { + // disable Error Interrupt: (Frame error, Noise error, Overrun error) + w.set_eie(false); + // disable DMA Rx Request + w.set_dmar(false); + }); compiler_fence(Ordering::SeqCst); } @@ -117,8 +111,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma> RingBufferedUartRx<'d, T, RxD let r = T::regs(); // Start background receive if it was not already started - // SAFETY: read only - match unsafe { r.cr3().read().dmar() } { + match r.cr3().read().dmar() { false => self.start()?, _ => {} }; @@ -213,19 +206,17 @@ fn check_for_errors(s: Sr) -> Result<(), Error> { /// Clear IDLE and return the Sr register fn clear_idle_flag(r: Regs) -> Sr { - unsafe { - // SAFETY: read only and we only use Rx related flags + // SAFETY: read only and we only use Rx related flags - let sr = sr(r).read(); + let sr = sr(r).read(); - // This read also clears the error and idle interrupt flags on v1. - rdr(r).read_volatile(); - clear_interrupt_flags(r, sr); + // This read also clears the error and idle interrupt flags on v1. + unsafe { rdr(r).read_volatile() }; + clear_interrupt_flags(r, sr); - r.cr1().modify(|w| w.set_idleie(true)); + r.cr1().modify(|w| w.set_idleie(true)); - sr - } + sr } #[cfg(all(feature = "unstable-traits", feature = "nightly"))] diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 7486bd376..2367127e8 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -28,82 +28,80 @@ pub struct InterruptHandler { impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { - unsafe { - let regs = T::regs(); - //let x = regs.istr().read().0; - //trace!("USB IRQ: {:08x}", x); + let regs = T::regs(); + //let x = regs.istr().read().0; + //trace!("USB IRQ: {:08x}", x); - let istr = regs.istr().read(); + let istr = regs.istr().read(); - if istr.susp() { - //trace!("USB IRQ: susp"); - IRQ_SUSPEND.store(true, Ordering::Relaxed); - regs.cntr().modify(|w| { - w.set_fsusp(true); - w.set_lpmode(true); - }); + if istr.susp() { + //trace!("USB IRQ: susp"); + IRQ_SUSPEND.store(true, Ordering::Relaxed); + regs.cntr().modify(|w| { + w.set_fsusp(true); + w.set_lpmode(true); + }); - // Write 0 to clear. - let mut clear = regs::Istr(!0); - clear.set_susp(false); - regs.istr().write_value(clear); + // Write 0 to clear. + let mut clear = regs::Istr(!0); + clear.set_susp(false); + regs.istr().write_value(clear); - // Wake main thread. - BUS_WAKER.wake(); - } + // Wake main thread. + BUS_WAKER.wake(); + } - if istr.wkup() { - //trace!("USB IRQ: wkup"); - IRQ_RESUME.store(true, Ordering::Relaxed); - regs.cntr().modify(|w| { - w.set_fsusp(false); - w.set_lpmode(false); - }); + if istr.wkup() { + //trace!("USB IRQ: wkup"); + IRQ_RESUME.store(true, Ordering::Relaxed); + regs.cntr().modify(|w| { + w.set_fsusp(false); + w.set_lpmode(false); + }); - // Write 0 to clear. - let mut clear = regs::Istr(!0); - clear.set_wkup(false); - regs.istr().write_value(clear); + // Write 0 to clear. + let mut clear = regs::Istr(!0); + clear.set_wkup(false); + regs.istr().write_value(clear); - // Wake main thread. - BUS_WAKER.wake(); - } + // Wake main thread. + BUS_WAKER.wake(); + } - if istr.reset() { - //trace!("USB IRQ: reset"); - IRQ_RESET.store(true, Ordering::Relaxed); + if istr.reset() { + //trace!("USB IRQ: reset"); + IRQ_RESET.store(true, Ordering::Relaxed); - // Write 0 to clear. - let mut clear = regs::Istr(!0); - clear.set_reset(false); - regs.istr().write_value(clear); + // Write 0 to clear. + let mut clear = regs::Istr(!0); + clear.set_reset(false); + regs.istr().write_value(clear); - // Wake main thread. - BUS_WAKER.wake(); - } + // Wake main thread. + BUS_WAKER.wake(); + } - if istr.ctr() { - let index = istr.ep_id() as usize; - let mut epr = regs.epr(index).read(); - if epr.ctr_rx() { - if index == 0 && epr.setup() { - EP0_SETUP.store(true, Ordering::Relaxed); - } - //trace!("EP {} RX, setup={}", index, epr.setup()); - EP_OUT_WAKERS[index].wake(); + if istr.ctr() { + let index = istr.ep_id() as usize; + let mut epr = regs.epr(index).read(); + if epr.ctr_rx() { + if index == 0 && epr.setup() { + EP0_SETUP.store(true, Ordering::Relaxed); } - if epr.ctr_tx() { - //trace!("EP {} TX", index); - EP_IN_WAKERS[index].wake(); - } - epr.set_dtog_rx(false); - epr.set_dtog_tx(false); - epr.set_stat_rx(Stat(0)); - epr.set_stat_tx(Stat(0)); - epr.set_ctr_rx(!epr.ctr_rx()); - epr.set_ctr_tx(!epr.ctr_tx()); - regs.epr(index).write_value(epr); + //trace!("EP {} RX, setup={}", index, epr.setup()); + EP_OUT_WAKERS[index].wake(); } + if epr.ctr_tx() { + //trace!("EP {} TX", index); + EP_IN_WAKERS[index].wake(); + } + epr.set_dtog_rx(false); + epr.set_dtog_tx(false); + epr.set_stat_rx(Stat(0)); + epr.set_stat_tx(Stat(0)); + epr.set_ctr_rx(!epr.ctr_rx()); + epr.set_ctr_tx(!epr.ctr_tx()); + regs.epr(index).write_value(epr); } } } @@ -168,20 +166,20 @@ fn calc_out_len(len: u16) -> (u16, u16) { mod btable { use super::*; - pub(super) unsafe fn write_in(index: usize, addr: u16) { + pub(super) fn write_in(index: usize, addr: u16) { USBRAM.mem(index * 4 + 0).write_value(addr); } - pub(super) unsafe fn write_in_len(index: usize, _addr: u16, len: u16) { + pub(super) fn write_in_len(index: usize, _addr: u16, len: u16) { USBRAM.mem(index * 4 + 1).write_value(len); } - pub(super) unsafe fn write_out(index: usize, addr: u16, max_len_bits: u16) { + pub(super) fn write_out(index: usize, addr: u16, max_len_bits: u16) { USBRAM.mem(index * 4 + 2).write_value(addr); USBRAM.mem(index * 4 + 3).write_value(max_len_bits); } - pub(super) unsafe fn read_out_len(index: usize) -> u16 { + pub(super) fn read_out_len(index: usize) -> u16 { USBRAM.mem(index * 4 + 3).read() } } @@ -189,19 +187,19 @@ mod btable { mod btable { use super::*; - pub(super) unsafe fn write_in(_index: usize, _addr: u16) {} + pub(super) fn write_in(_index: usize, _addr: u16) {} - pub(super) unsafe fn write_in_len(index: usize, addr: u16, len: u16) { + pub(super) fn write_in_len(index: usize, addr: u16, len: u16) { USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16)); } - pub(super) unsafe fn write_out(index: usize, addr: u16, max_len_bits: u16) { + pub(super) fn write_out(index: usize, addr: u16, max_len_bits: u16) { USBRAM .mem(index * 2 + 1) .write_value((addr as u32) | ((max_len_bits as u32) << 16)); } - pub(super) unsafe fn read_out_len(index: usize) -> u16 { + pub(super) fn read_out_len(index: usize) -> u16 { (USBRAM.mem(index * 2 + 1).read() >> 16) as u16 } } @@ -216,7 +214,7 @@ impl EndpointBuffer { fn read(&mut self, buf: &mut [u8]) { assert!(buf.len() <= self.len as usize); for i in 0..(buf.len() + USBRAM_ALIGN - 1) / USBRAM_ALIGN { - let val = unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read() }; + let val = USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read(); let n = USBRAM_ALIGN.min(buf.len() - i * USBRAM_ALIGN); buf[i * USBRAM_ALIGN..][..n].copy_from_slice(&val.to_le_bytes()[..n]); } @@ -233,7 +231,7 @@ impl EndpointBuffer { let val = u16::from_le_bytes(val); #[cfg(usbram_32_2048)] let val = u32::from_le_bytes(val); - unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val) }; + USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val); } } } @@ -266,36 +264,32 @@ impl<'d, T: Instance> Driver<'d, T> { let regs = T::regs(); #[cfg(stm32l5)] - unsafe { + { crate::peripherals::PWR::enable(); crate::pac::PWR.cr2().modify(|w| w.set_usv(true)); } #[cfg(pwr_h5)] - unsafe { - crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)) - } + crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)); - unsafe { - ::enable(); - ::reset(); + ::enable(); + ::reset(); - regs.cntr().write(|w| { - w.set_pdwn(false); - w.set_fres(true); - }); + regs.cntr().write(|w| { + w.set_pdwn(false); + w.set_fres(true); + }); - #[cfg(time)] - embassy_time::block_for(embassy_time::Duration::from_millis(100)); - #[cfg(not(time))] - cortex_m::asm::delay(crate::rcc::get_freqs().sys.0 / 10); + #[cfg(time)] + embassy_time::block_for(embassy_time::Duration::from_millis(100)); + #[cfg(not(time))] + cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.0 / 10); - #[cfg(not(usb_v4))] - regs.btable().write(|w| w.set_btable(0)); + #[cfg(not(usb_v4))] + regs.btable().write(|w| w.set_btable(0)); - dp.set_as_af(dp.af_num(), AFType::OutputPushPull); - dm.set_as_af(dm.af_num(), AFType::OutputPushPull); - } + dp.set_as_af(dp.af_num(), AFType::OutputPushPull); + dm.set_as_af(dm.af_num(), AFType::OutputPushPull); // Initialize the bus so that it signals that power is available BUS_WAKER.wake(); @@ -363,7 +357,7 @@ impl<'d, T: Instance> Driver<'d, T> { let addr = self.alloc_ep_mem(len); trace!(" len_bits = {:04x}", len_bits); - unsafe { btable::write_out::(index, addr, len_bits) } + btable::write_out::(index, addr, len_bits); EndpointBuffer { addr, @@ -379,7 +373,7 @@ impl<'d, T: Instance> Driver<'d, T> { let addr = self.alloc_ep_mem(len); // ep_in_len is written when actually TXing packets. - unsafe { btable::write_in::(index, addr) } + btable::write_in::(index, addr); EndpointBuffer { addr, @@ -440,19 +434,17 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { let regs = T::regs(); - unsafe { - regs.cntr().write(|w| { - w.set_pdwn(false); - w.set_fres(false); - w.set_resetm(true); - w.set_suspm(true); - w.set_wkupm(true); - w.set_ctrm(true); - }); + regs.cntr().write(|w| { + w.set_pdwn(false); + w.set_fres(false); + w.set_resetm(true); + w.set_suspm(true); + w.set_wkupm(true); + w.set_ctrm(true); + }); - #[cfg(any(usb_v3, usb_v4))] - regs.bcdr().write(|w| w.set_dppu(true)) - } + #[cfg(any(usb_v3, usb_v4))] + regs.bcdr().write(|w| w.set_dppu(true)); trace!("enabled"); @@ -485,7 +477,7 @@ pub struct Bus<'d, T: Instance> { impl<'d, T: Instance> driver::Bus for Bus<'d, T> { async fn poll(&mut self) -> Event { - poll_fn(move |cx| unsafe { + poll_fn(move |cx| { BUS_WAKER.register(cx.waker()); if self.inited { @@ -548,7 +540,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { match ep_addr.direction() { Direction::In => { loop { - let r = unsafe { reg.read() }; + let r = reg.read(); match r.stat_tx() { Stat::DISABLED => break, // if disabled, stall does nothing. Stat::STALL => break, // done! @@ -559,7 +551,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { }; let mut w = invariant(r); w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); - unsafe { reg.write_value(w) }; + reg.write_value(w); } } } @@ -567,7 +559,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { } Direction::Out => { loop { - let r = unsafe { reg.read() }; + let r = reg.read(); match r.stat_rx() { Stat::DISABLED => break, // if disabled, stall does nothing. Stat::STALL => break, // done! @@ -578,7 +570,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { }; let mut w = invariant(r); w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); - unsafe { reg.write_value(w) }; + reg.write_value(w); } } } @@ -589,7 +581,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool { let regs = T::regs(); - let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; + let epr = regs.epr(ep_addr.index() as _).read(); match ep_addr.direction() { Direction::In => epr.stat_tx() == Stat::STALL, Direction::Out => epr.stat_rx() == Stat::STALL, @@ -600,7 +592,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { trace!("set_enabled {:x} {}", ep_addr, enabled); // This can race, so do a retry loop. let reg = T::regs().epr(ep_addr.index() as _); - trace!("EPR before: {:04x}", unsafe { reg.read() }.0); + trace!("EPR before: {:04x}", reg.read().0); match ep_addr.direction() { Direction::In => { loop { @@ -608,13 +600,13 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { false => Stat::DISABLED, true => Stat::NAK, }; - let r = unsafe { reg.read() }; + let r = reg.read(); if r.stat_tx() == want_stat { break; } let mut w = invariant(r); w.set_stat_tx(Stat(r.stat_tx().0 ^ want_stat.0)); - unsafe { reg.write_value(w) }; + reg.write_value(w); } EP_IN_WAKERS[ep_addr.index()].wake(); } @@ -624,18 +616,18 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { false => Stat::DISABLED, true => Stat::VALID, }; - let r = unsafe { reg.read() }; + let r = reg.read(); if r.stat_rx() == want_stat { break; } let mut w = invariant(r); w.set_stat_rx(Stat(r.stat_rx().0 ^ want_stat.0)); - unsafe { reg.write_value(w) }; + reg.write_value(w); } EP_OUT_WAKERS[ep_addr.index()].wake(); } } - trace!("EPR after: {:04x}", unsafe { reg.read() }.0); + trace!("EPR after: {:04x}", reg.read().0); } async fn enable(&mut self) {} @@ -685,12 +677,12 @@ impl<'d, T: Instance, D> Endpoint<'d, T, D> { fn write_data(&mut self, buf: &[u8]) { let index = self.info.addr.index(); self.buf.write(buf); - unsafe { btable::write_in_len::(index, self.buf.addr, buf.len() as _) } + btable::write_in_len::(index, self.buf.addr, buf.len() as _); } fn read_data(&mut self, buf: &mut [u8]) -> Result { let index = self.info.addr.index(); - let rx_len = unsafe { btable::read_out_len::(index) as usize } & 0x3FF; + let rx_len = btable::read_out_len::(index) as usize & 0x3FF; trace!("READ DONE, rx_len = {}", rx_len); if rx_len > buf.len() { return Err(EndpointError::BufferOverflow); @@ -711,7 +703,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> { poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(index).read() }.stat_tx() == Stat::DISABLED { + if regs.epr(index).read().stat_tx() == Stat::DISABLED { Poll::Pending } else { Poll::Ready(()) @@ -733,7 +725,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, Out> { poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(index).read() }.stat_rx() == Stat::DISABLED { + if regs.epr(index).read().stat_rx() == Stat::DISABLED { Poll::Pending } else { Poll::Ready(()) @@ -751,7 +743,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { let stat = poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); let regs = T::regs(); - let stat = unsafe { regs.epr(index).read() }.stat_rx(); + let stat = regs.epr(index).read().stat_rx(); if matches!(stat, Stat::NAK | Stat::DISABLED) { Poll::Ready(stat) } else { @@ -767,16 +759,14 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { let rx_len = self.read_data(buf)?; let regs = T::regs(); - unsafe { - regs.epr(index).write(|w| { - w.set_ep_type(convert_type(self.info.ep_type)); - w.set_ea(self.info.addr.index() as _); - w.set_stat_rx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); - w.set_stat_tx(Stat(0)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - }; + regs.epr(index).write(|w| { + w.set_ep_type(convert_type(self.info.ep_type)); + w.set_ea(self.info.addr.index() as _); + w.set_stat_rx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); + w.set_stat_tx(Stat(0)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); trace!("READ OK, rx_len = {}", rx_len); Ok(rx_len) @@ -795,7 +785,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { let stat = poll_fn(|cx| { EP_IN_WAKERS[index].register(cx.waker()); let regs = T::regs(); - let stat = unsafe { regs.epr(index).read() }.stat_tx(); + let stat = regs.epr(index).read().stat_tx(); if matches!(stat, Stat::NAK | Stat::DISABLED) { Poll::Ready(stat) } else { @@ -811,16 +801,14 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { self.write_data(buf); let regs = T::regs(); - unsafe { - regs.epr(index).write(|w| { - w.set_ep_type(convert_type(self.info.ep_type)); - w.set_ea(self.info.addr.index() as _); - w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); - w.set_stat_rx(Stat(0)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - }; + regs.epr(index).write(|w| { + w.set_ep_type(convert_type(self.info.ep_type)); + w.set_ea(self.info.addr.index() as _); + w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); + w.set_stat_rx(Stat(0)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); trace!("WRITE OK"); @@ -889,22 +877,20 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } // Note: if this is the first AND last transfer, the above effectively // changes stat_tx like NAK -> NAK, so noop. - unsafe { - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(stat_rx)); - w.set_stat_tx(Stat(stat_tx)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - } + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(stat_rx)); + w.set_stat_tx(Stat(stat_tx)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); } trace!("data_out WAITING, buf.len() = {}", buf.len()); poll_fn(|cx| { EP_OUT_WAKERS[0].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(0).read() }.stat_rx() == Stat::NAK { + if regs.epr(0).read().stat_rx() == Stat::NAK { Poll::Ready(()) } else { Poll::Pending @@ -919,19 +905,17 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { let rx_len = self.ep_out.read_data(buf)?; - unsafe { - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(match last { - // If last, set STAT_RX=STALL. - true => Stat::NAK.0 ^ Stat::STALL.0, - // Otherwise, set STAT_RX=VALID, to allow the host to send the next packet. - false => Stat::NAK.0 ^ Stat::VALID.0, - })); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - }; + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(match last { + // If last, set STAT_RX=STALL. + true => Stat::NAK.0 ^ Stat::STALL.0, + // Otherwise, set STAT_RX=VALID, to allow the host to send the next packet. + false => Stat::NAK.0 ^ Stat::VALID.0, + })); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); Ok(rx_len) } @@ -960,15 +944,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } // Note: if this is the first AND last transfer, the above effectively // does a change of NAK -> VALID. - unsafe { - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(stat_rx)); - w.set_ep_kind(last); // set OUT_STATUS if last. - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - } + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(stat_rx)); + w.set_ep_kind(last); // set OUT_STATUS if last. + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); } trace!("WRITE WAITING"); @@ -976,7 +958,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { EP_IN_WAKERS[0].register(cx.waker()); EP_OUT_WAKERS[0].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(0).read() }.stat_tx() == Stat::NAK { + if regs.epr(0).read().stat_tx() == Stat::NAK { Poll::Ready(()) } else { Poll::Pending @@ -992,15 +974,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { self.ep_in.write_data(data); let regs = T::regs(); - unsafe { - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); - w.set_ep_kind(last); // set OUT_STATUS if last. - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }) - }; + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_tx(Stat(Stat::NAK.0 ^ Stat::VALID.0)); + w.set_ep_kind(last); // set OUT_STATUS if last. + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); trace!("WRITE OK"); @@ -1014,16 +994,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { self.ep_in.write_data(&[]); // Set OUT=stall, IN=accept - unsafe { - let epr = regs.epr(0).read(); - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); - w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::VALID.0)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }); - } + let epr = regs.epr(0).read(); + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); + w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::VALID.0)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); trace!("control: accept WAITING"); // Wait is needed, so that we don't set the address too soon, breaking the status stage. @@ -1031,7 +1009,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { poll_fn(|cx| { EP_IN_WAKERS[0].register(cx.waker()); let regs = T::regs(); - if unsafe { regs.epr(0).read() }.stat_tx() == Stat::NAK { + if regs.epr(0).read().stat_tx() == Stat::NAK { Poll::Ready(()) } else { Poll::Pending @@ -1047,16 +1025,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { trace!("control: reject"); // Set IN+OUT to stall - unsafe { - let epr = regs.epr(0).read(); - regs.epr(0).write(|w| { - w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); - w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::STALL.0)); - w.set_ctr_rx(true); // don't clear - w.set_ctr_tx(true); // don't clear - }); - } + let epr = regs.epr(0).read(); + regs.epr(0).write(|w| { + w.set_ep_type(EpType::CONTROL); + w.set_stat_rx(Stat(epr.stat_rx().0 ^ Stat::STALL.0)); + w.set_stat_tx(Stat(epr.stat_tx().0 ^ Stat::STALL.0)); + w.set_ctr_rx(true); // don't clear + w.set_ctr_tx(true); // don't clear + }); } async fn accept_set_address(&mut self, addr: u8) { @@ -1064,11 +1040,9 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { let regs = T::regs(); trace!("setting addr: {}", addr); - unsafe { - regs.daddr().write(|w| { - w.set_ef(true); - w.set_add(addr); - }) - } + regs.daddr().write(|w| { + w.set_ef(true); + w.set_add(addr); + }); } } diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs index 317264cbb..12e5f0e60 100644 --- a/embassy-stm32/src/usb_otg/mod.rs +++ b/embassy-stm32/src/usb_otg/mod.rs @@ -148,7 +148,7 @@ foreach_interrupt!( fn regs() -> crate::pac::otg::Otg { // OTG HS registers are a superset of FS registers - crate::pac::otg::Otg(crate::pac::USB_OTG_HS.0) + unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) } } #[cfg(feature = "nightly")] diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index 16cbf1a95..8af5c7bd5 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs @@ -30,19 +30,16 @@ impl interrupt::typelevel::Handler for InterruptHandl let r = T::regs(); let state = T::state(); - // SAFETY: atomic read/write - let ints = unsafe { r.gintsts().read() }; + let ints = r.gintsts().read(); if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() { // Mask interrupts and notify `Bus` to process them - unsafe { r.gintmsk().write(|_| {}) }; + r.gintmsk().write(|_| {}); T::state().bus_waker.wake(); } // Handle RX - // SAFETY: atomic read with no side effects - while unsafe { r.gintsts().read().rxflvl() } { - // SAFETY: atomic "pop" register - let status = unsafe { r.grxstsp().read() }; + while r.gintsts().read().rxflvl() { + let status = r.grxstsp().read(); let ep_num = status.epnum() as usize; let len = status.bcnt() as usize; @@ -57,21 +54,15 @@ impl interrupt::typelevel::Handler for InterruptHandl if state.ep0_setup_ready.load(Ordering::Relaxed) == false { // SAFETY: exclusive access ensured by atomic bool let data = unsafe { &mut *state.ep0_setup_data.get() }; - // SAFETY: FIFO reads are exclusive to this IRQ - unsafe { - data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); - data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); - } + data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); + data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); state.ep0_setup_ready.store(true, Ordering::Release); state.ep_out_wakers[0].wake(); } else { error!("received SETUP before previous finished processing"); // discard FIFO - // SAFETY: FIFO reads are exclusive to IRQ - unsafe { - r.fifo(0).read(); - r.fifo(0).read(); - } + r.fifo(0).read(); + r.fifo(0).read(); } } vals::Pktstsd::OUT_DATA_RX => { @@ -84,8 +75,7 @@ impl interrupt::typelevel::Handler for InterruptHandl for chunk in buf.chunks_mut(4) { // RX FIFO is shared so always read from fifo(0) - // SAFETY: FIFO reads are exclusive to IRQ - let data = unsafe { r.fifo(0).read().0 }; + let data = r.fifo(0).read().0; chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]); } @@ -97,8 +87,7 @@ impl interrupt::typelevel::Handler for InterruptHandl // discard FIFO data let len_words = (len + 3) / 4; for _ in 0..len_words { - // SAFETY: FIFO reads are exclusive to IRQ - unsafe { r.fifo(0).read().data() }; + r.fifo(0).read().data(); } } } @@ -114,24 +103,20 @@ impl interrupt::typelevel::Handler for InterruptHandl // IN endpoint interrupt if ints.iepint() { - // SAFETY: atomic read with no side effects - let mut ep_mask = unsafe { r.daint().read().iepint() }; + let mut ep_mask = r.daint().read().iepint(); let mut ep_num = 0; // Iterate over endpoints while there are non-zero bits in the mask while ep_mask != 0 { if ep_mask & 1 != 0 { - // SAFETY: atomic read with no side effects - let ep_ints = unsafe { r.diepint(ep_num).read() }; + let ep_ints = r.diepint(ep_num).read(); // clear all - // SAFETY: DIEPINT is exclusive to IRQ - unsafe { r.diepint(ep_num).write_value(ep_ints) }; + r.diepint(ep_num).write_value(ep_ints); // TXFE is cleared in DIEPEMPMSK if ep_ints.txfe() { - // SAFETY: DIEPEMPMSK is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.diepempmsk().modify(|w| { w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num)); }); @@ -172,8 +157,7 @@ impl interrupt::typelevel::Handler for InterruptHandl macro_rules! config_ulpi_pins { ($($pin:ident),*) => { into_ref!($($pin),*); - // NOTE(unsafe) Exclusive access to the registers - critical_section::with(|_| unsafe { + critical_section::with(|_| { $( $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); #[cfg(gpio_v2)] @@ -298,10 +282,8 @@ impl<'d, T: Instance> Driver<'d, T> { ) -> Self { into_ref!(dp, dm); - unsafe { - dp.set_as_af(dp.af_num(), AFType::OutputPushPull); - dm.set_as_af(dm.af_num(), AFType::OutputPushPull); - } + dp.set_as_af(dp.af_num(), AFType::OutputPushPull); + dm.set_as_af(dm.af_num(), AFType::OutputPushPull); Self { phantom: PhantomData, @@ -508,18 +490,15 @@ pub struct Bus<'d, T: Instance> { impl<'d, T: Instance> Bus<'d, T> { fn restore_irqs() { - // SAFETY: atomic write - unsafe { - T::regs().gintmsk().write(|w| { - w.set_usbrst(true); - w.set_enumdnem(true); - w.set_usbsuspm(true); - w.set_wuim(true); - w.set_iepint(true); - w.set_oepint(true); - w.set_rxflvlm(true); - }); - } + T::regs().gintmsk().write(|w| { + w.set_usbrst(true); + w.set_enumdnem(true); + w.set_usbsuspm(true); + w.set_wuim(true); + w.set_iepint(true); + w.set_oepint(true); + w.set_rxflvlm(true); + }); } } @@ -533,8 +512,7 @@ impl<'d, T: Instance> Bus<'d, T> { let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out); trace!("configuring rx fifo size={}", rx_fifo_size_words); - // SAFETY: register is exclusive to `Bus` with `&mut self` - unsafe { r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)) }; + r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)); // Configure TX (USB in direction) fifo size for each endpoint let mut fifo_top = rx_fifo_size_words; @@ -549,13 +527,10 @@ impl<'d, T: Instance> Bus<'d, T> { let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) }; - // SAFETY: register is exclusive to `Bus` with `&mut self` - unsafe { - dieptxf.write(|w| { - w.set_fd(ep.fifo_size_words); - w.set_sa(fifo_top); - }); - } + dieptxf.write(|w| { + w.set_fd(ep.fifo_size_words); + w.set_sa(fifo_top); + }); fifo_top += ep.fifo_size_words; } @@ -575,8 +550,7 @@ impl<'d, T: Instance> Bus<'d, T> { // Configure IN endpoints for (index, ep) in self.ep_in.iter().enumerate() { if let Some(ep) = ep { - // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.diepctl(index).write(|w| { if index == 0 { w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); @@ -593,8 +567,7 @@ impl<'d, T: Instance> Bus<'d, T> { // Configure OUT endpoints for (index, ep) in self.ep_out.iter().enumerate() { if let Some(ep) = ep { - // SAFETY: DOEPCTL/DOEPTSIZ is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.doepctl(index).write(|w| { if index == 0 { w.set_mpsiz(ep0_mpsiz(ep.max_packet_size)); @@ -618,14 +591,11 @@ impl<'d, T: Instance> Bus<'d, T> { } // Enable IRQs for allocated endpoints - // SAFETY: register is exclusive to `Bus` with `&mut self` - unsafe { - r.daintmsk().modify(|w| { - w.set_iepm(ep_irq_mask(&self.ep_in)); - // OUT interrupts not used, handled in RXFLVL - // w.set_oepm(ep_irq_mask(&self.ep_out)); - }); - } + r.daintmsk().modify(|w| { + w.set_iepm(ep_irq_mask(&self.ep_in)); + // OUT interrupts not used, handled in RXFLVL + // w.set_oepm(ep_irq_mask(&self.ep_out)); + }); } fn disable(&mut self) { @@ -634,10 +604,8 @@ impl<'d, T: Instance> Bus<'d, T> { ::disable(); #[cfg(stm32l4)] - unsafe { - crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); - // Cannot disable PWR, because other peripherals might be using it - } + crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); + // Cannot disable PWR, because other peripherals might be using it } } @@ -653,7 +621,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { T::state().bus_waker.register(cx.waker()); - let ints = unsafe { r.gintsts().read() }; + let ints = r.gintsts().read(); if ints.usbrst() { trace!("reset"); @@ -661,34 +629,27 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { self.configure_endpoints(); // Reset address - // SAFETY: DCFG is shared with `ControlPipe` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.dcfg().modify(|w| { w.set_dad(0); }); }); - // SAFETY: atomic clear on rc_w1 register - unsafe { r.gintsts().write(|w| w.set_usbrst(true)) }; // clear + r.gintsts().write(|w| w.set_usbrst(true)); // clear Self::restore_irqs(); } if ints.enumdne() { trace!("enumdne"); - // SAFETY: atomic read with no side effects - let speed = unsafe { r.dsts().read().enumspd() }; + let speed = r.dsts().read().enumspd(); trace!(" speed={}", speed.0); - // SAFETY: register is only accessed by `Bus` under `&mut self` - unsafe { - r.gusbcfg().modify(|w| { - w.set_trdt(calculate_trdt(speed, T::frequency())); - }) - }; + r.gusbcfg().modify(|w| { + w.set_trdt(calculate_trdt(speed, T::frequency())); + }); - // SAFETY: atomic clear on rc_w1 register - unsafe { r.gintsts().write(|w| w.set_enumdne(true)) }; // clear + r.gintsts().write(|w| w.set_enumdne(true)); // clear Self::restore_irqs(); return Poll::Ready(Event::Reset); @@ -696,16 +657,14 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { if ints.usbsusp() { trace!("suspend"); - // SAFETY: atomic clear on rc_w1 register - unsafe { r.gintsts().write(|w| w.set_usbsusp(true)) }; // clear + r.gintsts().write(|w| w.set_usbsusp(true)); // clear Self::restore_irqs(); return Poll::Ready(Event::Suspend); } if ints.wkupint() { trace!("resume"); - // SAFETY: atomic clear on rc_w1 register - unsafe { r.gintsts().write(|w| w.set_wkupint(true)) }; // clear + r.gintsts().write(|w| w.set_wkupint(true)); // clear Self::restore_irqs(); return Poll::Ready(Event::Resume); } @@ -727,8 +686,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { let regs = T::regs(); match ep_addr.direction() { Direction::Out => { - // SAFETY: DOEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { regs.doepctl(ep_addr.index()).modify(|w| { w.set_stall(stalled); }); @@ -737,8 +695,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { T::state().ep_out_wakers[ep_addr.index()].wake(); } Direction::In => { - // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { regs.diepctl(ep_addr.index()).modify(|w| { w.set_stall(stalled); }); @@ -758,10 +715,9 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { let regs = T::regs(); - // SAFETY: atomic read with no side effects match ep_addr.direction() { - Direction::Out => unsafe { regs.doepctl(ep_addr.index()).read().stall() }, - Direction::In => unsafe { regs.diepctl(ep_addr.index()).read().stall() }, + Direction::Out => regs.doepctl(ep_addr.index()).read().stall(), + Direction::In => regs.diepctl(ep_addr.index()).read().stall(), } } @@ -777,8 +733,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { let r = T::regs(); match ep_addr.direction() { Direction::Out => { - // SAFETY: DOEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { // cancel transfer if active if !enabled && r.doepctl(ep_addr.index()).read().epena() { r.doepctl(ep_addr.index()).modify(|w| { @@ -796,8 +751,7 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { T::state().ep_out_wakers[ep_addr.index()].wake(); } Direction::In => { - // SAFETY: DIEPCTL is shared with `Endpoint` so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { // cancel transfer if active if !enabled && r.diepctl(ep_addr.index()).read().epena() { r.diepctl(ep_addr.index()).modify(|w| { @@ -820,196 +774,193 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { async fn enable(&mut self) { trace!("enable"); - // SAFETY: registers are only accessed by `Bus` under `&mut self` - unsafe { - #[cfg(stm32l4)] - { - crate::peripherals::PWR::enable(); - critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); - } - - #[cfg(stm32f7)] - { - // Enable ULPI clock if external PHY is used - let ulpien = !self.phy_type.internal(); - critical_section::with(|_| { - crate::pac::RCC.ahb1enr().modify(|w| { - if T::HIGH_SPEED { - w.set_usb_otg_hsulpien(ulpien); - } else { - w.set_usb_otg_hsen(ulpien); - } - }); - - // Low power mode - crate::pac::RCC.ahb1lpenr().modify(|w| { - if T::HIGH_SPEED { - w.set_usb_otg_hsulpilpen(ulpien); - } else { - w.set_usb_otg_hslpen(ulpien); - } - }); - }); - } - - #[cfg(stm32h7)] - { - // If true, VDD33USB is generated by internal regulator from VDD50USB - // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) - // TODO: unhardcode - let internal_regulator = false; - - // Enable USB power - critical_section::with(|_| { - crate::pac::PWR.cr3().modify(|w| { - w.set_usb33den(true); - w.set_usbregen(internal_regulator); - }) - }); - - // Wait for USB power to stabilize - while !crate::pac::PWR.cr3().read().usb33rdy() {} - - // Use internal 48MHz HSI clock. Should be enabled in RCC by default. - critical_section::with(|_| { - crate::pac::RCC - .d2ccip2r() - .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48)) - }); - - // Enable ULPI clock if external PHY is used - let ulpien = !self.phy_type.internal(); - critical_section::with(|_| { - crate::pac::RCC.ahb1enr().modify(|w| { - if T::HIGH_SPEED { - w.set_usb_otg_hs_ulpien(ulpien); - } else { - w.set_usb_otg_fs_ulpien(ulpien); - } - }); - crate::pac::RCC.ahb1lpenr().modify(|w| { - if T::HIGH_SPEED { - w.set_usb_otg_hs_ulpilpen(ulpien); - } else { - w.set_usb_otg_fs_ulpilpen(ulpien); - } - }); - }); - } - - #[cfg(stm32u5)] - { - // Enable USB power - critical_section::with(|_| { - crate::pac::RCC.ahb3enr().modify(|w| { - w.set_pwren(true); - }); - cortex_m::asm::delay(2); - - crate::pac::PWR.svmcr().modify(|w| { - w.set_usv(true); - w.set_uvmen(true); - }); - }); - - // Wait for USB power to stabilize - while !crate::pac::PWR.svmsr().read().vddusbrdy() {} - - // Select HSI48 as USB clock source. - critical_section::with(|_| { - crate::pac::RCC.ccipr1().modify(|w| { - w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48); - }) - }); - } - - ::enable(); - ::reset(); - - T::Interrupt::unpend(); - T::Interrupt::enable(); - - let r = T::regs(); - let core_id = r.cid().read().0; - info!("Core id {:08x}", core_id); - - // Wait for AHB ready. - while !r.grstctl().read().ahbidl() {} - - // Configure as device. - r.gusbcfg().write(|w| { - // Force device mode - w.set_fdmod(true); - // Enable internal full-speed PHY - w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed()); - }); - - // Configuring Vbus sense and SOF output - match core_id { - 0x0000_1200 | 0x0000_1100 => { - assert!(self.phy_type != PhyType::InternalHighSpeed); - - r.gccfg_v1().modify(|w| { - // Enable internal full-speed PHY, logic is inverted - w.set_pwrdwn(self.phy_type.internal()); - }); - - // F429-like chips have the GCCFG.NOVBUSSENS bit - r.gccfg_v1().modify(|w| { - w.set_novbussens(true); - w.set_vbusasen(false); - w.set_vbusbsen(false); - w.set_sofouten(false); - }); - } - 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => { - // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning - r.gccfg_v2().modify(|w| { - // Enable internal full-speed PHY, logic is inverted - w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed()); - w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed()); - }); - - r.gccfg_v2().modify(|w| { - w.set_vbden(false); - }); - - // Force B-peripheral session - r.gotgctl().modify(|w| { - w.set_bvaloen(true); - w.set_bvaloval(true); - }); - } - _ => unimplemented!("Unknown USB core id {:X}", core_id), - } - - // Soft disconnect. - r.dctl().write(|w| w.set_sdis(true)); - - // Set speed. - r.dcfg().write(|w| { - w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80); - w.set_dspd(self.phy_type.to_dspd()); - }); - - // Unmask transfer complete EP interrupt - r.diepmsk().write(|w| { - w.set_xfrcm(true); - }); - - // Unmask and clear core interrupts - Bus::::restore_irqs(); - r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF)); - - // Unmask global interrupt - r.gahbcfg().write(|w| { - w.set_gint(true); // unmask global interrupt - }); - - // Connect - r.dctl().write(|w| w.set_sdis(false)); + #[cfg(stm32l4)] + { + crate::peripherals::PWR::enable(); + critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); } + #[cfg(stm32f7)] + { + // Enable ULPI clock if external PHY is used + let ulpien = !self.phy_type.internal(); + critical_section::with(|_| { + crate::pac::RCC.ahb1enr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hsulpien(ulpien); + } else { + w.set_usb_otg_hsen(ulpien); + } + }); + + // Low power mode + crate::pac::RCC.ahb1lpenr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hsulpilpen(ulpien); + } else { + w.set_usb_otg_hslpen(ulpien); + } + }); + }); + } + + #[cfg(stm32h7)] + { + // If true, VDD33USB is generated by internal regulator from VDD50USB + // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) + // TODO: unhardcode + let internal_regulator = false; + + // Enable USB power + critical_section::with(|_| { + crate::pac::PWR.cr3().modify(|w| { + w.set_usb33den(true); + w.set_usbregen(internal_regulator); + }) + }); + + // Wait for USB power to stabilize + while !crate::pac::PWR.cr3().read().usb33rdy() {} + + // Use internal 48MHz HSI clock. Should be enabled in RCC by default. + critical_section::with(|_| { + crate::pac::RCC + .d2ccip2r() + .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48)) + }); + + // Enable ULPI clock if external PHY is used + let ulpien = !self.phy_type.internal(); + critical_section::with(|_| { + crate::pac::RCC.ahb1enr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hs_ulpien(ulpien); + } else { + w.set_usb_otg_fs_ulpien(ulpien); + } + }); + crate::pac::RCC.ahb1lpenr().modify(|w| { + if T::HIGH_SPEED { + w.set_usb_otg_hs_ulpilpen(ulpien); + } else { + w.set_usb_otg_fs_ulpilpen(ulpien); + } + }); + }); + } + + #[cfg(stm32u5)] + { + // Enable USB power + critical_section::with(|_| { + crate::pac::RCC.ahb3enr().modify(|w| { + w.set_pwren(true); + }); + cortex_m::asm::delay(2); + + crate::pac::PWR.svmcr().modify(|w| { + w.set_usv(true); + w.set_uvmen(true); + }); + }); + + // Wait for USB power to stabilize + while !crate::pac::PWR.svmsr().read().vddusbrdy() {} + + // Select HSI48 as USB clock source. + critical_section::with(|_| { + crate::pac::RCC.ccipr1().modify(|w| { + w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48); + }) + }); + } + + ::enable(); + ::reset(); + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + let r = T::regs(); + let core_id = r.cid().read().0; + info!("Core id {:08x}", core_id); + + // Wait for AHB ready. + while !r.grstctl().read().ahbidl() {} + + // Configure as device. + r.gusbcfg().write(|w| { + // Force device mode + w.set_fdmod(true); + // Enable internal full-speed PHY + w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed()); + }); + + // Configuring Vbus sense and SOF output + match core_id { + 0x0000_1200 | 0x0000_1100 => { + assert!(self.phy_type != PhyType::InternalHighSpeed); + + r.gccfg_v1().modify(|w| { + // Enable internal full-speed PHY, logic is inverted + w.set_pwrdwn(self.phy_type.internal()); + }); + + // F429-like chips have the GCCFG.NOVBUSSENS bit + r.gccfg_v1().modify(|w| { + w.set_novbussens(true); + w.set_vbusasen(false); + w.set_vbusbsen(false); + w.set_sofouten(false); + }); + } + 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => { + // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning + r.gccfg_v2().modify(|w| { + // Enable internal full-speed PHY, logic is inverted + w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed()); + w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed()); + }); + + r.gccfg_v2().modify(|w| { + w.set_vbden(false); + }); + + // Force B-peripheral session + r.gotgctl().modify(|w| { + w.set_bvaloen(true); + w.set_bvaloval(true); + }); + } + _ => unimplemented!("Unknown USB core id {:X}", core_id), + } + + // Soft disconnect. + r.dctl().write(|w| w.set_sdis(true)); + + // Set speed. + r.dcfg().write(|w| { + w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80); + w.set_dspd(self.phy_type.to_dspd()); + }); + + // Unmask transfer complete EP interrupt + r.diepmsk().write(|w| { + w.set_xfrcm(true); + }); + + // Unmask and clear core interrupts + Bus::::restore_irqs(); + r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF)); + + // Unmask global interrupt + r.gahbcfg().write(|w| { + w.set_gint(true); // unmask global interrupt + }); + + // Connect + r.dctl().write(|w| w.set_sdis(false)); + self.enabled = true; } @@ -1066,8 +1017,7 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, In> { T::state().ep_in_wakers[ep_index].register(cx.waker()); - // SAFETY: atomic read without side effects - if unsafe { T::regs().diepctl(ep_index).read().usbaep() } { + if T::regs().diepctl(ep_index).read().usbaep() { Poll::Ready(()) } else { Poll::Pending @@ -1088,8 +1038,7 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, Out> { T::state().ep_out_wakers[ep_index].register(cx.waker()); - // SAFETY: atomic read without side effects - if unsafe { T::regs().doepctl(ep_index).read().usbaep() } { + if T::regs().doepctl(ep_index).read().usbaep() { Poll::Ready(()) } else { Poll::Pending @@ -1124,8 +1073,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> { // Release buffer state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release); - // SAFETY: DOEPCTL/DOEPTSIZ is shared with `Bus` so a critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { // Receive 1 packet T::regs().doeptsiz(index).modify(|w| { w.set_xfrsiz(self.info.max_packet_size as _); @@ -1163,8 +1111,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { poll_fn(|cx| { state.ep_in_wakers[index].register(cx.waker()); - // SAFETY: atomic read with no side effects - let diepctl = unsafe { r.diepctl(index).read() }; + let diepctl = r.diepctl(index).read(); if !diepctl.usbaep() { Poll::Ready(Err(EndpointError::Disabled)) } else if !diepctl.epena() { @@ -1181,12 +1128,10 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { let size_words = (buf.len() + 3) / 4; - // SAFETY: atomic read with no side effects - let fifo_space = unsafe { r.dtxfsts(index).read().ineptfsav() as usize }; + let fifo_space = r.dtxfsts(index).read().ineptfsav() as usize; if size_words > fifo_space { // Not enough space in fifo, enable tx fifo empty interrupt - // SAFETY: DIEPEMPMSK is shared with IRQ so critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { r.diepempmsk().modify(|w| { w.set_ineptxfem(w.ineptxfem() | (1 << index)); }); @@ -1202,18 +1147,14 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { .await } - // SAFETY: DIEPTSIZ is exclusive to this endpoint under `&mut self` - unsafe { - // Setup transfer size - r.dieptsiz(index).write(|w| { - w.set_mcnt(1); - w.set_pktcnt(1); - w.set_xfrsiz(buf.len() as _); - }); - } + // Setup transfer size + r.dieptsiz(index).write(|w| { + w.set_mcnt(1); + w.set_pktcnt(1); + w.set_xfrsiz(buf.len() as _); + }); - // SAFETY: DIEPCTL is shared with `Bus` so a critical section is needed for RMW - critical_section::with(|_| unsafe { + critical_section::with(|_| { // Enable endpoint r.diepctl(index).modify(|w| { w.set_cnak(true); @@ -1225,8 +1166,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { for chunk in buf.chunks(4) { let mut tmp = [0u8; 4]; tmp[0..chunk.len()].copy_from_slice(chunk); - // SAFETY: FIFO is exclusive to this endpoint under `&mut self` - unsafe { r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))) }; + r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))); } trace!("write done ep={:?}", self.info.addr); @@ -1258,17 +1198,15 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> { state.ep0_setup_ready.store(false, Ordering::Release); // EP0 should not be controlled by `Bus` so this RMW does not need a critical section - unsafe { - // Receive 1 SETUP packet - T::regs().doeptsiz(self.ep_out.info.addr.index()).modify(|w| { - w.set_rxdpid_stupcnt(1); - }); + // Receive 1 SETUP packet + T::regs().doeptsiz(self.ep_out.info.addr.index()).modify(|w| { + w.set_rxdpid_stupcnt(1); + }); - // Clear NAK to indicate we are ready to receive more data - T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| { - w.set_cnak(true); - }); - } + // Clear NAK to indicate we are ready to receive more data + T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| { + w.set_cnak(true); + }); trace!("SETUP received: {:?}", data); Poll::Ready(data) @@ -1313,20 +1251,18 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> { trace!("control: reject"); // EP0 should not be controlled by `Bus` so this RMW does not need a critical section - unsafe { - let regs = T::regs(); - regs.diepctl(self.ep_in.info.addr.index()).modify(|w| { - w.set_stall(true); - }); - regs.doepctl(self.ep_out.info.addr.index()).modify(|w| { - w.set_stall(true); - }); - } + let regs = T::regs(); + regs.diepctl(self.ep_in.info.addr.index()).modify(|w| { + w.set_stall(true); + }); + regs.doepctl(self.ep_out.info.addr.index()).modify(|w| { + w.set_stall(true); + }); } async fn accept_set_address(&mut self, addr: u8) { trace!("setting addr: {}", addr); - critical_section::with(|_| unsafe { + critical_section::with(|_| { T::regs().dcfg().modify(|w| { w.set_dad(addr); }); diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index 18ebf97d8..5907a4e54 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs @@ -48,11 +48,9 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { let rl = reload_value(psc, timeout_us); let wdg = T::regs(); - unsafe { - wdg.kr().write(|w| w.set_key(Key::ENABLE)); - wdg.pr().write(|w| w.set_pr(Pr(pr))); - wdg.rlr().write(|w| w.set_rl(rl)); - } + wdg.kr().write(|w| w.set_key(Key::ENABLE)); + wdg.pr().write(|w| w.set_pr(Pr(pr))); + wdg.rlr().write(|w| w.set_rl(rl)); trace!( "Watchdog configured with {}us timeout, desired was {}us (PR={}, RL={})", @@ -67,11 +65,11 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { } } - pub unsafe fn unleash(&mut self) { + pub fn unleash(&mut self) { T::regs().kr().write(|w| w.set_key(Key::START)); } - pub unsafe fn pet(&mut self) { + pub fn pet(&mut self) { T::regs().kr().write(|w| w.set_key(Key::RESET)); } } diff --git a/examples/stm32f0/src/bin/wdg.rs b/examples/stm32f0/src/bin/wdg.rs index 80e76f901..a44b17528 100644 --- a/examples/stm32f0/src/bin/wdg.rs +++ b/examples/stm32f0/src/bin/wdg.rs @@ -16,10 +16,10 @@ async fn main(_spawner: Spawner) { let mut wdg = IndependentWatchdog::new(p.IWDG, 20_000_00); info!("Watchdog start"); - unsafe { wdg.unleash() }; + wdg.unleash(); loop { Timer::after(Duration::from_secs(1)).await; - unsafe { wdg.pet() }; + wdg.pet(); } } diff --git a/examples/stm32f4/src/bin/wdt.rs b/examples/stm32f4/src/bin/wdt.rs index b2c587fa1..e5d122af7 100644 --- a/examples/stm32f4/src/bin/wdt.rs +++ b/examples/stm32f4/src/bin/wdt.rs @@ -17,9 +17,7 @@ async fn main(_spawner: Spawner) { let mut led = Output::new(p.PB7, Level::High, Speed::Low); let mut wdt = IndependentWatchdog::new(p.IWDG, 1_000_000); - unsafe { - wdt.unleash(); - } + wdt.unleash(); let mut i = 0; @@ -36,9 +34,7 @@ async fn main(_spawner: Spawner) { // MCU should restart in 1 second after the last pet. if i < 5 { info!("Petting watchdog"); - unsafe { - wdt.pet(); - } + wdt.pet(); } i += 1; diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs index ecbe3a6e6..c111a9787 100644 --- a/examples/stm32g4/src/bin/usb_serial.rs +++ b/examples/stm32g4/src/bin/usb_serial.rs @@ -38,9 +38,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); info!("Hello World!"); - unsafe { - pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10)); - } + pac::RCC.ccipr().write(|w| w.set_clk48sel(0b10)); let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs index 3912327e2..336eed644 100644 --- a/examples/stm32h5/src/bin/usb_serial.rs +++ b/examples/stm32h5/src/bin/usb_serial.rs @@ -45,11 +45,9 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); - unsafe { - pac::RCC.ccipr4().write(|w| { - w.set_usbsel(pac::rcc::vals::Usbsel::HSI48); - }); - } + pac::RCC.ccipr4().write(|w| { + w.set_usbsel(pac::rcc::vals::Usbsel::HSI48); + }); // Create the driver, from the HAL. let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index 1972f8ff2..d360df085 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs @@ -62,49 +62,39 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { T::enable(); ::reset(); - unsafe { - ch1.set_speed(Speed::VeryHigh); - ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch2.set_speed(Speed::VeryHigh); - ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch3.set_speed(Speed::VeryHigh); - ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch4.set_speed(Speed::VeryHigh); - ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); - } + ch1.set_speed(Speed::VeryHigh); + ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); + ch2.set_speed(Speed::VeryHigh); + ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); + ch3.set_speed(Speed::VeryHigh); + ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); + ch4.set_speed(Speed::VeryHigh); + ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); let mut this = Self { inner: tim }; this.set_freq(freq); this.inner.start(); - unsafe { - T::regs_gp32() - .ccmr_output(0) - .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); - T::regs_gp32() - .ccmr_output(0) - .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); - T::regs_gp32() - .ccmr_output(1) - .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); - T::regs_gp32() - .ccmr_output(1) - .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); - } + let r = T::regs_gp32(); + r.ccmr_output(0) + .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); + r.ccmr_output(0) + .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); + r.ccmr_output(1) + .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); + r.ccmr_output(1) + .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into())); + this } pub fn enable(&mut self, channel: Channel) { - unsafe { - T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true)); - } + T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true)); } pub fn disable(&mut self, channel: Channel) { - unsafe { - T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false)); - } + T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false)); } pub fn set_freq(&mut self, freq: Hertz) { @@ -112,11 +102,11 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { } pub fn get_max_duty(&self) -> u32 { - unsafe { T::regs_gp32().arr().read().arr() } + T::regs_gp32().arr().read().arr() } pub fn set_duty(&mut self, channel: Channel, duty: u32) { defmt::assert!(duty < self.get_max_duty()); - unsafe { T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty)) } + T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty)) } } diff --git a/examples/stm32h7/src/bin/wdg.rs b/examples/stm32h7/src/bin/wdg.rs index 2b0301aad..9181dfd67 100644 --- a/examples/stm32h7/src/bin/wdg.rs +++ b/examples/stm32h7/src/bin/wdg.rs @@ -15,10 +15,10 @@ async fn main(_spawner: Spawner) { let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000); - unsafe { wdg.unleash() }; + wdg.unleash(); loop { Timer::after(Duration::from_secs(1)).await; - unsafe { wdg.pet() }; + wdg.pet(); } } diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs index 281346e5f..1771e5202 100644 --- a/examples/stm32l4/src/bin/adc.rs +++ b/examples/stm32l4/src/bin/adc.rs @@ -12,12 +12,10 @@ use {defmt_rtt as _, panic_probe as _}; fn main() -> ! { info!("Hello World!"); - unsafe { - pac::RCC.ccipr().modify(|w| { - w.set_adcsel(0b11); - }); - pac::RCC.ahb2enr().modify(|w| w.set_adcen(true)); - } + pac::RCC.ccipr().modify(|w| { + w.set_adcsel(0b11); + }); + pac::RCC.ahb2enr().modify(|w| w.set_adcen(true)); let p = embassy_stm32::init(Default::default()); diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs index d6e744aa6..a36ed5d90 100644 --- a/examples/stm32l4/src/bin/dac.rs +++ b/examples/stm32l4/src/bin/dac.rs @@ -11,11 +11,9 @@ use {defmt_rtt as _, panic_probe as _}; fn main() -> ! { info!("Hello World!"); - unsafe { - pac::RCC.apb1enr1().modify(|w| { - w.set_dac1en(true); - }); - } + pac::RCC.apb1enr1().modify(|w| { + w.set_dac1en(true); + }); let p = embassy_stm32::init(Default::default()); diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs index e179c5ca1..805d21418 100644 --- a/examples/stm32wl/src/bin/lora_lorawan.rs +++ b/examples/stm32wl/src/bin/lora_lorawan.rs @@ -35,7 +35,7 @@ async fn main(_spawner: Spawner) { config.rcc.enable_lsi = true; // enable RNG let p = embassy_stm32::init(config); - unsafe { pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)) } + pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)); let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index 182c607f9..d8562fca5 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs @@ -15,11 +15,9 @@ async fn main(_spawner: Spawner) { config.rcc.enable_lsi = true; //Needed for RNG to work let p = embassy_stm32::init(config); - unsafe { - pac::RCC.ccipr().modify(|w| { - w.set_rngsel(0b01); - }); - } + pac::RCC.ccipr().modify(|w| { + w.set_rngsel(0b01); + }); info!("Hello World!"); diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 32d35c42c..582df5753 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -24,10 +24,8 @@ async fn main(_spawner: Spawner) { info!("Starting LSI"); - unsafe { - pac::RCC.csr().modify(|w| w.set_lsion(true)); - while !pac::RCC.csr().read().lsirdy() {} - } + pac::RCC.csr().modify(|w| w.set_lsion(true)); + while !pac::RCC.csr().read().lsirdy() {} info!("Started LSI"); From bbc81146ecb3832e9ec1531ef6d48fec6c7c0d8c Mon Sep 17 00:00:00 2001 From: Catherine Date: Mon, 19 Jun 2023 09:06:41 +0000 Subject: [PATCH 98/98] BDMA: request stop after busy loop in blocking_wait(). Otherwise the channel cannot be used again, since CR.EN remains set and the DMA channel registers are read-only while it is set. --- embassy-stm32/src/dma/bdma.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index c0a503e25..e9b75d863 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -327,6 +327,7 @@ impl<'a, C: Channel> Transfer<'a, C> { pub fn blocking_wait(mut self) { while self.is_running() {} + self.request_stop(); // "Subsequent reads and writes cannot be moved ahead of preceding reads." fence(Ordering::SeqCst);