Compare commits
No commits in common. "main" and "embassy-rp-rustdoc-1" have entirely different histories.
main
...
embassy-rp
@ -7,7 +7,6 @@ set -euo pipefail
|
|||||||
export RUSTUP_HOME=/ci/cache/rustup
|
export RUSTUP_HOME=/ci/cache/rustup
|
||||||
export CARGO_HOME=/ci/cache/cargo
|
export CARGO_HOME=/ci/cache/cargo
|
||||||
export CARGO_TARGET_DIR=/ci/cache/target
|
export CARGO_TARGET_DIR=/ci/cache/target
|
||||||
mv rust-toolchain-nightly.toml rust-toolchain.toml
|
|
||||||
|
|
||||||
# needed for "dumb HTTP" transport support
|
# needed for "dumb HTTP" transport support
|
||||||
# used when pointing stm32-metapac to a CI-built one.
|
# used when pointing stm32-metapac to a CI-built one.
|
||||||
@ -22,7 +21,9 @@ fi
|
|||||||
hashtime restore /ci/cache/filetime.json || true
|
hashtime restore /ci/cache/filetime.json || true
|
||||||
hashtime save /ci/cache/filetime.json
|
hashtime save /ci/cache/filetime.json
|
||||||
|
|
||||||
./ci-nightly.sh
|
sed -i 's/channel.*/channel = "beta"/g' rust-toolchain.toml
|
||||||
|
|
||||||
|
./ci_stable.sh
|
||||||
|
|
||||||
# Save lockfiles
|
# Save lockfiles
|
||||||
echo Saving lockfiles...
|
echo Saving lockfiles...
|
12
.github/ci/rustfmt.sh
vendored
12
.github/ci/rustfmt.sh
vendored
@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
## on push branch~=gh-readonly-queue/main/.*
|
|
||||||
## on pull_request
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
export RUSTUP_HOME=/ci/cache/rustup
|
|
||||||
export CARGO_HOME=/ci/cache/cargo
|
|
||||||
export CARGO_TARGET_DIR=/ci/cache/target
|
|
||||||
mv rust-toolchain-nightly.toml rust-toolchain.toml
|
|
||||||
|
|
||||||
find . -name '*.rs' -not -path '*target*' | xargs rustfmt --check --skip-children --unstable-features --edition 2021
|
|
13
.github/ci/test-nightly.sh
vendored
13
.github/ci/test-nightly.sh
vendored
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
## on push branch~=gh-readonly-queue/main/.*
|
|
||||||
## on pull_request
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
export RUSTUP_HOME=/ci/cache/rustup
|
|
||||||
export CARGO_HOME=/ci/cache/cargo
|
|
||||||
export CARGO_TARGET_DIR=/ci/cache/target
|
|
||||||
mv rust-toolchain-nightly.toml rust-toolchain.toml
|
|
||||||
|
|
||||||
MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml
|
|
||||||
MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml --features nightly
|
|
3
.github/ci/test.sh
vendored
3
.github/ci/test.sh
vendored
@ -8,6 +8,9 @@ export RUSTUP_HOME=/ci/cache/rustup
|
|||||||
export CARGO_HOME=/ci/cache/cargo
|
export CARGO_HOME=/ci/cache/cargo
|
||||||
export CARGO_TARGET_DIR=/ci/cache/target
|
export CARGO_TARGET_DIR=/ci/cache/target
|
||||||
|
|
||||||
|
MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml
|
||||||
|
MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml --features nightly
|
||||||
|
|
||||||
cargo test --manifest-path ./embassy-sync/Cargo.toml
|
cargo test --manifest-path ./embassy-sync/Cargo.toml
|
||||||
cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml
|
cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml
|
||||||
cargo test --manifest-path ./embassy-hal-internal/Cargo.toml
|
cargo test --manifest-path ./embassy-hal-internal/Cargo.toml
|
||||||
|
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -15,10 +15,14 @@
|
|||||||
//"rust-analyzer.cargo.target": "thumbv7m-none-eabi",
|
//"rust-analyzer.cargo.target": "thumbv7m-none-eabi",
|
||||||
"rust-analyzer.cargo.target": "thumbv7em-none-eabi",
|
"rust-analyzer.cargo.target": "thumbv7em-none-eabi",
|
||||||
//"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
|
//"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
|
||||||
|
"rust-analyzer.cargo.features": [
|
||||||
|
// Uncomment if the example has a "nightly" feature.
|
||||||
|
"nightly",
|
||||||
|
],
|
||||||
"rust-analyzer.linkedProjects": [
|
"rust-analyzer.linkedProjects": [
|
||||||
// Uncomment ONE line for the chip you want to work on.
|
// Uncomment ONE line for the chip you want to work on.
|
||||||
// This makes rust-analyzer work on the example crate and all its dependencies.
|
// This makes rust-analyzer work on the example crate and all its dependencies.
|
||||||
"examples/stm32l4/Cargo.toml",
|
"examples/nrf52840/Cargo.toml",
|
||||||
// "examples/nrf52840-rtic/Cargo.toml",
|
// "examples/nrf52840-rtic/Cargo.toml",
|
||||||
// "examples/nrf5340/Cargo.toml",
|
// "examples/nrf5340/Cargo.toml",
|
||||||
// "examples/nrf-rtos-trace/Cargo.toml",
|
// "examples/nrf-rtos-trace/Cargo.toml",
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eo pipefail
|
|
||||||
|
|
||||||
export RUSTFLAGS=-Dwarnings
|
|
||||||
export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info
|
|
||||||
if [[ -z "${CARGO_TARGET_DIR}" ]]; then
|
|
||||||
export CARGO_TARGET_DIR=target_ci
|
|
||||||
fi
|
|
||||||
|
|
||||||
cargo batch \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,log \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,defmt \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,integrated-timers \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,integrated-timers \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt,integrated-timers \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32 \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,integrated-timers \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread \
|
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread,integrated-timers \
|
|
||||||
--- build --release --manifest-path examples/nrf52840-rtic/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840-rtic \
|
|
||||||
|
|
41
ci.sh
41
ci.sh
@ -15,24 +15,26 @@ if [ $TARGET = "x86_64-unknown-linux-gnu" ]; then
|
|||||||
BUILD_EXTRA="--- build --release --manifest-path examples/std/Cargo.toml --target $TARGET --out-dir out/examples/std"
|
BUILD_EXTRA="--- build --release --manifest-path examples/std/Cargo.toml --target $TARGET --out-dir out/examples/std"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
find . -name '*.rs' -not -path '*target*' | xargs rustfmt --check --skip-children --unstable-features --edition 2021
|
||||||
|
|
||||||
cargo batch \
|
cargo batch \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly \
|
||||||
--- 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 nightly,log \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features defmt \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,defmt \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,integrated-timers \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,integrated-timers \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,integrated-timers \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,integrated-timers \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,integrated-timers \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt,integrated-timers \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32 \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32 \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,integrated-timers \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,integrated-timers \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread \
|
||||||
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread,integrated-timers \
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread,integrated-timers \
|
||||||
--- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \
|
--- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \
|
||||||
--- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \
|
--- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features 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,proto-ipv4,medium-ethernet \
|
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \
|
||||||
@ -89,12 +91,12 @@ cargo batch \
|
|||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,embedded-sdmmc,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,embedded-sdmmc,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \
|
||||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \
|
||||||
@ -138,6 +140,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-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 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/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/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/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 \
|
--- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \
|
||||||
|
77
ci_stable.sh
Executable file
77
ci_stable.sh
Executable file
@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export RUSTFLAGS=-Dwarnings
|
||||||
|
export DEFMT_LOG=trace
|
||||||
|
|
||||||
|
cargo batch \
|
||||||
|
--- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \
|
||||||
|
--- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \
|
||||||
|
--- build --release --manifest-path embassy-boot/rp/Cargo.toml --target thumbv6m-none-eabi \
|
||||||
|
--- build --release --manifest-path embassy-boot/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4 \
|
||||||
|
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi \
|
||||||
|
--- 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,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,proto-ipv6,medium-ethernet \
|
||||||
|
--- 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 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52820,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52832,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52833,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-s,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-ns,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-s,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-ns,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-net,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,log,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,defmt,gpiote,time-driver-rtc1 \
|
||||||
|
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features defmt \
|
||||||
|
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features log \
|
||||||
|
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi \
|
||||||
|
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features qspi-as-gpio \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g473cc,defmt,exti,time-driver-any \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re,defmt,exti,time-driver-any \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g473cc,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r9zi,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303vc,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \
|
||||||
|
--- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --no-default-features --out-dir out/examples/nrf52840 --bin raw_spawn \
|
||||||
|
--- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --no-default-features --out-dir out/examples/stm32l0 --bin raw_spawn \
|
@ -1,17 +0,0 @@
|
|||||||
# cyw43-pio
|
|
||||||
|
|
||||||
RP2040 PIO driver for the nonstandard half-duplex SPI used in the Pico W. The PIO driver offloads SPI communication with the WiFi chip and improves throughput.
|
|
||||||
|
|
||||||
## Minimum supported Rust version (MSRV)
|
|
||||||
|
|
||||||
Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This work is licensed under either of
|
|
||||||
|
|
||||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
||||||
<http://www.apache.org/licenses/LICENSE-2.0>)
|
|
||||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
|
|
||||||
|
|
||||||
at your option.
|
|
@ -1,7 +1,5 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
#![doc = include_str!("../README.md")]
|
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
use core::slice;
|
use core::slice;
|
||||||
|
|
||||||
@ -13,7 +11,6 @@ use embassy_rp::{Peripheral, PeripheralRef};
|
|||||||
use fixed::FixedU32;
|
use fixed::FixedU32;
|
||||||
use pio_proc::pio_asm;
|
use pio_proc::pio_asm;
|
||||||
|
|
||||||
/// SPI comms driven by PIO.
|
|
||||||
pub struct PioSpi<'d, CS: Pin, PIO: Instance, const SM: usize, DMA> {
|
pub struct PioSpi<'d, CS: Pin, PIO: Instance, const SM: usize, DMA> {
|
||||||
cs: Output<'d, CS>,
|
cs: Output<'d, CS>,
|
||||||
sm: StateMachine<'d, PIO, SM>,
|
sm: StateMachine<'d, PIO, SM>,
|
||||||
@ -28,7 +25,6 @@ where
|
|||||||
CS: Pin,
|
CS: Pin,
|
||||||
PIO: Instance,
|
PIO: Instance,
|
||||||
{
|
{
|
||||||
/// Create a new instance of PioSpi.
|
|
||||||
pub fn new<DIO, CLK>(
|
pub fn new<DIO, CLK>(
|
||||||
common: &mut Common<'d, PIO>,
|
common: &mut Common<'d, PIO>,
|
||||||
mut sm: StateMachine<'d, PIO, SM>,
|
mut sm: StateMachine<'d, PIO, SM>,
|
||||||
@ -147,7 +143,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write data to peripheral and return status.
|
|
||||||
pub async fn write(&mut self, write: &[u32]) -> u32 {
|
pub async fn write(&mut self, write: &[u32]) -> u32 {
|
||||||
self.sm.set_enable(false);
|
self.sm.set_enable(false);
|
||||||
let write_bits = write.len() * 32 - 1;
|
let write_bits = write.len() * 32 - 1;
|
||||||
@ -175,7 +170,6 @@ where
|
|||||||
status
|
status
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send command and read response into buffer.
|
|
||||||
pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) -> u32 {
|
pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) -> u32 {
|
||||||
self.sm.set_enable(false);
|
self.sm.set_enable(false);
|
||||||
let write_bits = 31;
|
let write_bits = 31;
|
||||||
|
@ -45,10 +45,6 @@ nc 192.168.0.250 1234
|
|||||||
```
|
```
|
||||||
Send it some data, you should see it echoed back and printed in the firmware's logs.
|
Send it some data, you should see it echoed back and printed in the firmware's logs.
|
||||||
|
|
||||||
## Minimum supported Rust version (MSRV)
|
|
||||||
|
|
||||||
Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This work is licensed under either of
|
This work is licensed under either of
|
||||||
|
@ -12,23 +12,17 @@ use crate::ioctl::{IoctlState, IoctlType};
|
|||||||
use crate::structs::*;
|
use crate::structs::*;
|
||||||
use crate::{countries, events, PowerManagementMode};
|
use crate::{countries, events, PowerManagementMode};
|
||||||
|
|
||||||
/// Control errors.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
/// Status code.
|
|
||||||
pub status: u32,
|
pub status: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Multicast errors.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AddMulticastAddressError {
|
pub enum AddMulticastAddressError {
|
||||||
/// Not a multicast address.
|
|
||||||
NotMulticast,
|
NotMulticast,
|
||||||
/// No free address slots.
|
|
||||||
NoFreeSlots,
|
NoFreeSlots,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Control driver.
|
|
||||||
pub struct Control<'a> {
|
pub struct Control<'a> {
|
||||||
state_ch: ch::StateRunner<'a>,
|
state_ch: ch::StateRunner<'a>,
|
||||||
events: &'a Events,
|
events: &'a Events,
|
||||||
@ -44,7 +38,6 @@ impl<'a> Control<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize WiFi controller.
|
|
||||||
pub async fn init(&mut self, clm: &[u8]) {
|
pub async fn init(&mut self, clm: &[u8]) {
|
||||||
const CHUNK_SIZE: usize = 1024;
|
const CHUNK_SIZE: usize = 1024;
|
||||||
|
|
||||||
@ -161,7 +154,6 @@ impl<'a> Control<'a> {
|
|||||||
self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await;
|
self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set power management mode.
|
|
||||||
pub async fn set_power_management(&mut self, mode: PowerManagementMode) {
|
pub async fn set_power_management(&mut self, mode: PowerManagementMode) {
|
||||||
// power save mode
|
// power save mode
|
||||||
let mode_num = mode.mode();
|
let mode_num = mode.mode();
|
||||||
@ -174,7 +166,6 @@ impl<'a> Control<'a> {
|
|||||||
self.ioctl_set_u32(86, 0, mode_num).await;
|
self.ioctl_set_u32(86, 0, mode_num).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Join an unprotected network with the provided ssid.
|
|
||||||
pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> {
|
pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> {
|
||||||
self.set_iovar_u32("ampdu_ba_wsize", 8).await;
|
self.set_iovar_u32("ampdu_ba_wsize", 8).await;
|
||||||
|
|
||||||
@ -192,7 +183,6 @@ impl<'a> Control<'a> {
|
|||||||
self.wait_for_join(i).await
|
self.wait_for_join(i).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Join an protected network with the provided ssid and passphrase.
|
|
||||||
pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> {
|
pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> {
|
||||||
self.set_iovar_u32("ampdu_ba_wsize", 8).await;
|
self.set_iovar_u32("ampdu_ba_wsize", 8).await;
|
||||||
|
|
||||||
@ -260,19 +250,16 @@ impl<'a> Control<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set GPIO pin on WiFi chip.
|
|
||||||
pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) {
|
pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) {
|
||||||
assert!(gpio_n < 3);
|
assert!(gpio_n < 3);
|
||||||
self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 })
|
self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 })
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start open access point.
|
|
||||||
pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) {
|
pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) {
|
||||||
self.start_ap(ssid, "", Security::OPEN, channel).await;
|
self.start_ap(ssid, "", Security::OPEN, channel).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start WPA2 protected access point.
|
|
||||||
pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) {
|
pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) {
|
||||||
self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await;
|
self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await;
|
||||||
}
|
}
|
||||||
@ -507,14 +494,13 @@ impl<'a> Control<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// WiFi network scanner.
|
|
||||||
pub struct Scanner<'a> {
|
pub struct Scanner<'a> {
|
||||||
subscriber: EventSubscriber<'a>,
|
subscriber: EventSubscriber<'a>,
|
||||||
events: &'a Events,
|
events: &'a Events,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scanner<'_> {
|
impl Scanner<'_> {
|
||||||
/// Wait for the next found network.
|
/// wait for the next found network
|
||||||
pub async fn next(&mut self) -> Option<BssInfo> {
|
pub async fn next(&mut self) -> Option<BssInfo> {
|
||||||
let event = self.subscriber.next_message_pure().await;
|
let event = self.subscriber.next_message_pure().await;
|
||||||
if event.header.status != EStatus::PARTIAL {
|
if event.header.status != EStatus::PARTIAL {
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
#![deny(unused_must_use)]
|
#![deny(unused_must_use)]
|
||||||
#![doc = include_str!("../README.md")]
|
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
// This mod MUST go first, so that the others see its macros.
|
// This mod MUST go first, so that the others see its macros.
|
||||||
pub(crate) mod fmt;
|
pub(crate) mod fmt;
|
||||||
@ -104,7 +102,6 @@ const CHIP: Chip = Chip {
|
|||||||
chanspec_ctl_sb_mask: 0x0700,
|
chanspec_ctl_sb_mask: 0x0700,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Driver state.
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
ioctl_state: IoctlState,
|
ioctl_state: IoctlState,
|
||||||
ch: ch::State<MTU, 4, 4>,
|
ch: ch::State<MTU, 4, 4>,
|
||||||
@ -112,7 +109,6 @@ pub struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
/// Create new driver state holder.
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
ioctl_state: IoctlState::new(),
|
ioctl_state: IoctlState::new(),
|
||||||
@ -122,7 +118,6 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Power management modes.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum PowerManagementMode {
|
pub enum PowerManagementMode {
|
||||||
/// Custom, officially unsupported mode. Use at your own risk.
|
/// Custom, officially unsupported mode. Use at your own risk.
|
||||||
@ -208,13 +203,8 @@ impl PowerManagementMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Embassy-net driver.
|
|
||||||
pub type NetDriver<'a> = ch::Device<'a, MTU>;
|
pub type NetDriver<'a> = ch::Device<'a, MTU>;
|
||||||
|
|
||||||
/// Create a new instance of the CYW43 driver.
|
|
||||||
///
|
|
||||||
/// Returns a handle to the network device, control handle and a runner for driving the low level
|
|
||||||
/// stack.
|
|
||||||
pub async fn new<'a, PWR, SPI>(
|
pub async fn new<'a, PWR, SPI>(
|
||||||
state: &'a mut State,
|
state: &'a mut State,
|
||||||
pwr: PWR,
|
pwr: PWR,
|
||||||
|
@ -34,7 +34,6 @@ impl Default for LogState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Driver communicating with the WiFi chip.
|
|
||||||
pub struct Runner<'a, PWR, SPI> {
|
pub struct Runner<'a, PWR, SPI> {
|
||||||
ch: ch::Runner<'a, MTU>,
|
ch: ch::Runner<'a, MTU>,
|
||||||
bus: Bus<PWR, SPI>,
|
bus: Bus<PWR, SPI>,
|
||||||
@ -223,7 +222,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the
|
|
||||||
pub async fn run(mut self) -> ! {
|
pub async fn run(mut self) -> ! {
|
||||||
let mut buf = [0; 512];
|
let mut buf = [0; 512];
|
||||||
loop {
|
loop {
|
||||||
|
@ -4,16 +4,13 @@ use crate::fmt::Bytes;
|
|||||||
macro_rules! impl_bytes {
|
macro_rules! impl_bytes {
|
||||||
($t:ident) => {
|
($t:ident) => {
|
||||||
impl $t {
|
impl $t {
|
||||||
/// Bytes consumed by this type.
|
|
||||||
pub const SIZE: usize = core::mem::size_of::<Self>();
|
pub const SIZE: usize = core::mem::size_of::<Self>();
|
||||||
|
|
||||||
/// Convert to byte array.
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn to_bytes(&self) -> [u8; Self::SIZE] {
|
pub fn to_bytes(&self) -> [u8; Self::SIZE] {
|
||||||
unsafe { core::mem::transmute(*self) }
|
unsafe { core::mem::transmute(*self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create from byte array.
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self {
|
pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self {
|
||||||
let alignment = core::mem::align_of::<Self>();
|
let alignment = core::mem::align_of::<Self>();
|
||||||
@ -26,7 +23,6 @@ macro_rules! impl_bytes {
|
|||||||
unsafe { core::mem::transmute(bytes) }
|
unsafe { core::mem::transmute(bytes) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create from mutable byte array.
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self {
|
pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self {
|
||||||
let alignment = core::mem::align_of::<Self>();
|
let alignment = core::mem::align_of::<Self>();
|
||||||
@ -208,7 +204,6 @@ pub struct EthernetHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EthernetHeader {
|
impl EthernetHeader {
|
||||||
/// Swap endianness.
|
|
||||||
pub fn byteswap(&mut self) {
|
pub fn byteswap(&mut self) {
|
||||||
self.ether_type = self.ether_type.to_be();
|
self.ether_type = self.ether_type.to_be();
|
||||||
}
|
}
|
||||||
@ -477,26 +472,19 @@ impl ScanResults {
|
|||||||
#[repr(C, packed(2))]
|
#[repr(C, packed(2))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct BssInfo {
|
pub struct BssInfo {
|
||||||
/// Version.
|
|
||||||
pub version: u32,
|
pub version: u32,
|
||||||
/// Length.
|
|
||||||
pub length: u32,
|
pub length: u32,
|
||||||
/// BSSID.
|
|
||||||
pub bssid: [u8; 6],
|
pub bssid: [u8; 6],
|
||||||
/// Beacon period.
|
|
||||||
pub beacon_period: u16,
|
pub beacon_period: u16,
|
||||||
/// Capability.
|
|
||||||
pub capability: u16,
|
pub capability: u16,
|
||||||
/// SSID length.
|
|
||||||
pub ssid_len: u8,
|
pub ssid_len: u8,
|
||||||
/// SSID.
|
|
||||||
pub ssid: [u8; 32],
|
pub ssid: [u8; 32],
|
||||||
// there will be more stuff here
|
// there will be more stuff here
|
||||||
}
|
}
|
||||||
impl_bytes!(BssInfo);
|
impl_bytes!(BssInfo);
|
||||||
|
|
||||||
impl BssInfo {
|
impl BssInfo {
|
||||||
pub(crate) fn parse(packet: &mut [u8]) -> Option<&mut Self> {
|
pub fn parse(packet: &mut [u8]) -> Option<&mut Self> {
|
||||||
if packet.len() < BssInfo::SIZE {
|
if packet.len() < BssInfo::SIZE {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
|
@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
cortex-m = "0.7"
|
cortex-m = "0.7"
|
||||||
cortex-m-rt = "0.7"
|
cortex-m-rt = "0.7"
|
||||||
embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] }
|
embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] }
|
||||||
embassy-executor = { version = "0.4.0", features = ["arch-cortex-m", "executor-thread"] }
|
embassy-executor = { version = "0.4.0", features = ["nightly", "arch-cortex-m", "executor-thread"] }
|
||||||
|
|
||||||
defmt = "0.3.0"
|
defmt = "0.3.0"
|
||||||
defmt-rtt = "0.3.0"
|
defmt-rtt = "0.3.0"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::exti::ExtiInput;
|
use embassy_stm32::exti::ExtiInput;
|
||||||
|
@ -35,7 +35,7 @@ For Cortex-M targets, consider making sure that ALL of the following features ar
|
|||||||
* `executor-thread`
|
* `executor-thread`
|
||||||
* `nightly`
|
* `nightly`
|
||||||
|
|
||||||
For ESP32, consider using the executors and `#[main]` macro provided by your appropriate link:https://crates.io/crates/esp-hal-common[HAL crate].
|
For Xtensa ESP32, consider using the executors and `#[main]` macro provided by your appropriate link:https://crates.io/crates/esp-hal-common[HAL crate].
|
||||||
|
|
||||||
== Why is my binary so big?
|
== Why is my binary so big?
|
||||||
|
|
||||||
|
@ -26,22 +26,25 @@ features = ["defmt"]
|
|||||||
defmt = { version = "0.3", optional = true }
|
defmt = { version = "0.3", optional = true }
|
||||||
digest = "0.10"
|
digest = "0.10"
|
||||||
log = { version = "0.4", optional = true }
|
log = { version = "0.4", optional = true }
|
||||||
ed25519-dalek = { version = "2", default_features = false, features = ["digest"], optional = true }
|
ed25519-dalek = { version = "1.0.1", default_features = false, features = ["u32_backend"], optional = true }
|
||||||
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
|
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
|
||||||
embassy-sync = { version = "0.5.0", path = "../../embassy-sync" }
|
embassy-sync = { version = "0.5.0", path = "../../embassy-sync" }
|
||||||
embedded-storage = "0.3.1"
|
embedded-storage = "0.3.1"
|
||||||
embedded-storage-async = { version = "0.4.1" }
|
embedded-storage-async = { version = "0.4.1" }
|
||||||
salty = { version = "0.3", optional = true }
|
salty = { git = "https://github.com/ycrypto/salty.git", rev = "a9f17911a5024698406b75c0fac56ab5ccf6a8c7", optional = true }
|
||||||
signature = { version = "2.0", default-features = false }
|
signature = { version = "1.6.4", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.9"
|
env_logger = "0.9"
|
||||||
rand = "0.8"
|
rand = "0.7" # ed25519-dalek v1.0.1 depends on this exact version
|
||||||
futures = { version = "0.3", features = ["executor"] }
|
futures = { version = "0.3", features = ["executor"] }
|
||||||
sha1 = "0.10.5"
|
sha1 = "0.10.5"
|
||||||
critical-section = { version = "1.1.1", features = ["std"] }
|
critical-section = { version = "1.1.1", features = ["std"] }
|
||||||
ed25519-dalek = { version = "2", default_features = false, features = ["std", "rand_core", "digest"] }
|
|
||||||
|
[dev-dependencies.ed25519-dalek]
|
||||||
|
default_features = false
|
||||||
|
features = ["rand", "std", "u32_backend"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
ed25519-dalek = ["dep:ed25519-dalek", "_verify"]
|
ed25519-dalek = ["dep:ed25519-dalek", "_verify"]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use digest::typenum::U64;
|
use digest::typenum::U64;
|
||||||
use digest::{FixedOutput, HashMarker, OutputSizeUser, Update};
|
use digest::{FixedOutput, HashMarker, OutputSizeUser, Update};
|
||||||
use ed25519_dalek::Digest;
|
use ed25519_dalek::Digest as _;
|
||||||
|
|
||||||
pub struct Sha512(ed25519_dalek::Sha512);
|
pub struct Sha512(ed25519_dalek::Sha512);
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ impl Default for Sha512 {
|
|||||||
|
|
||||||
impl Update for Sha512 {
|
impl Update for Sha512 {
|
||||||
fn update(&mut self, data: &[u8]) {
|
fn update(&mut self, data: &[u8]) {
|
||||||
Digest::update(&mut self.0, data)
|
self.0.update(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,8 +79,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
|
|||||||
#[cfg(feature = "_verify")]
|
#[cfg(feature = "_verify")]
|
||||||
pub async fn verify_and_mark_updated(
|
pub async fn verify_and_mark_updated(
|
||||||
&mut self,
|
&mut self,
|
||||||
_public_key: &[u8; 32],
|
_public_key: &[u8],
|
||||||
_signature: &[u8; 64],
|
_signature: &[u8],
|
||||||
_update_len: u32,
|
_update_len: u32,
|
||||||
) -> Result<(), FirmwareUpdaterError> {
|
) -> Result<(), FirmwareUpdaterError> {
|
||||||
assert!(_update_len <= self.dfu.capacity() as u32);
|
assert!(_update_len <= self.dfu.capacity() as u32);
|
||||||
@ -89,14 +89,14 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
|
|||||||
|
|
||||||
#[cfg(feature = "ed25519-dalek")]
|
#[cfg(feature = "ed25519-dalek")]
|
||||||
{
|
{
|
||||||
use ed25519_dalek::{Signature, SignatureError, Verifier, VerifyingKey};
|
use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier};
|
||||||
|
|
||||||
use crate::digest_adapters::ed25519_dalek::Sha512;
|
use crate::digest_adapters::ed25519_dalek::Sha512;
|
||||||
|
|
||||||
let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into());
|
let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into());
|
||||||
|
|
||||||
let public_key = VerifyingKey::from_bytes(_public_key).map_err(into_signature_error)?;
|
let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?;
|
||||||
let signature = Signature::from_bytes(_signature);
|
let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?;
|
||||||
|
|
||||||
let mut chunk_buf = [0; 2];
|
let mut chunk_buf = [0; 2];
|
||||||
let mut message = [0; 64];
|
let mut message = [0; 64];
|
||||||
@ -106,6 +106,7 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "ed25519-salty")]
|
#[cfg(feature = "ed25519-salty")]
|
||||||
{
|
{
|
||||||
|
use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH};
|
||||||
use salty::{PublicKey, Signature};
|
use salty::{PublicKey, Signature};
|
||||||
|
|
||||||
use crate::digest_adapters::salty::Sha512;
|
use crate::digest_adapters::salty::Sha512;
|
||||||
@ -114,8 +115,10 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
|
|||||||
FirmwareUpdaterError::Signature(signature::Error::default())
|
FirmwareUpdaterError::Signature(signature::Error::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
let public_key = PublicKey::try_from(_public_key).map_err(into_signature_error)?;
|
let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?;
|
||||||
let signature = Signature::try_from(_signature).map_err(into_signature_error)?;
|
let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?;
|
||||||
|
let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?;
|
||||||
|
let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
|
||||||
|
|
||||||
let mut message = [0; 64];
|
let mut message = [0; 64];
|
||||||
let mut chunk_buf = [0; 2];
|
let mut chunk_buf = [0; 2];
|
||||||
|
@ -86,8 +86,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
|
|||||||
#[cfg(feature = "_verify")]
|
#[cfg(feature = "_verify")]
|
||||||
pub fn verify_and_mark_updated(
|
pub fn verify_and_mark_updated(
|
||||||
&mut self,
|
&mut self,
|
||||||
_public_key: &[u8; 32],
|
_public_key: &[u8],
|
||||||
_signature: &[u8; 64],
|
_signature: &[u8],
|
||||||
_update_len: u32,
|
_update_len: u32,
|
||||||
) -> Result<(), FirmwareUpdaterError> {
|
) -> Result<(), FirmwareUpdaterError> {
|
||||||
assert!(_update_len <= self.dfu.capacity() as u32);
|
assert!(_update_len <= self.dfu.capacity() as u32);
|
||||||
@ -96,14 +96,14 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
|
|||||||
|
|
||||||
#[cfg(feature = "ed25519-dalek")]
|
#[cfg(feature = "ed25519-dalek")]
|
||||||
{
|
{
|
||||||
use ed25519_dalek::{Signature, SignatureError, Verifier, VerifyingKey};
|
use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier};
|
||||||
|
|
||||||
use crate::digest_adapters::ed25519_dalek::Sha512;
|
use crate::digest_adapters::ed25519_dalek::Sha512;
|
||||||
|
|
||||||
let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into());
|
let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into());
|
||||||
|
|
||||||
let public_key = VerifyingKey::from_bytes(_public_key).map_err(into_signature_error)?;
|
let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?;
|
||||||
let signature = Signature::from_bytes(_signature);
|
let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?;
|
||||||
|
|
||||||
let mut message = [0; 64];
|
let mut message = [0; 64];
|
||||||
let mut chunk_buf = [0; 2];
|
let mut chunk_buf = [0; 2];
|
||||||
@ -113,6 +113,7 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "ed25519-salty")]
|
#[cfg(feature = "ed25519-salty")]
|
||||||
{
|
{
|
||||||
|
use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH};
|
||||||
use salty::{PublicKey, Signature};
|
use salty::{PublicKey, Signature};
|
||||||
|
|
||||||
use crate::digest_adapters::salty::Sha512;
|
use crate::digest_adapters::salty::Sha512;
|
||||||
@ -121,8 +122,10 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
|
|||||||
FirmwareUpdaterError::Signature(signature::Error::default())
|
FirmwareUpdaterError::Signature(signature::Error::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
let public_key = PublicKey::try_from(_public_key).map_err(into_signature_error)?;
|
let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?;
|
||||||
let signature = Signature::try_from(_signature).map_err(into_signature_error)?;
|
let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?;
|
||||||
|
let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?;
|
||||||
|
let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
|
||||||
|
|
||||||
let mut message = [0; 64];
|
let mut message = [0; 64];
|
||||||
let mut chunk_buf = [0; 2];
|
let mut chunk_buf = [0; 2];
|
||||||
@ -184,12 +187,10 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
|
|||||||
///
|
///
|
||||||
/// Failing to meet alignment and size requirements may result in a panic.
|
/// Failing to meet alignment and size requirements may result in a panic.
|
||||||
pub fn write_firmware(&mut self, offset: usize, data: &[u8]) -> Result<(), FirmwareUpdaterError> {
|
pub fn write_firmware(&mut self, offset: usize, data: &[u8]) -> Result<(), FirmwareUpdaterError> {
|
||||||
//assert!(data.len() >= DFU::ERASE_SIZE);
|
assert!(data.len() >= DFU::ERASE_SIZE);
|
||||||
self.state.verify_booted()?;
|
self.state.verify_booted()?;
|
||||||
|
|
||||||
if offset == 0 {
|
self.dfu.erase(offset as u32, (offset + data.len()) as u32)?;
|
||||||
self.dfu.erase(0, self.dfu.capacity() as u32)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.dfu.write(offset as u32, data)?;
|
self.dfu.write(offset as u32, data)?;
|
||||||
|
|
||||||
|
@ -275,19 +275,21 @@ mod tests {
|
|||||||
// The following key setup is based on:
|
// The following key setup is based on:
|
||||||
// https://docs.rs/ed25519-dalek/latest/ed25519_dalek/#example
|
// https://docs.rs/ed25519-dalek/latest/ed25519_dalek/#example
|
||||||
|
|
||||||
use ed25519_dalek::{Digest, Sha512, Signature, Signer, SigningKey, VerifyingKey};
|
use ed25519_dalek::Keypair;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
let mut csprng = OsRng {};
|
let mut csprng = OsRng {};
|
||||||
let keypair = SigningKey::generate(&mut csprng);
|
let keypair: Keypair = Keypair::generate(&mut csprng);
|
||||||
|
|
||||||
|
use ed25519_dalek::{Digest, Sha512, Signature, Signer};
|
||||||
let firmware: &[u8] = b"This are bytes that would otherwise be firmware bytes for DFU.";
|
let firmware: &[u8] = b"This are bytes that would otherwise be firmware bytes for DFU.";
|
||||||
let mut digest = Sha512::new();
|
let mut digest = Sha512::new();
|
||||||
digest.update(&firmware);
|
digest.update(&firmware);
|
||||||
let message = digest.finalize();
|
let message = digest.finalize();
|
||||||
let signature: Signature = keypair.sign(&message);
|
let signature: Signature = keypair.sign(&message);
|
||||||
|
|
||||||
let public_key = keypair.verifying_key();
|
use ed25519_dalek::PublicKey;
|
||||||
|
let public_key: PublicKey = keypair.public;
|
||||||
|
|
||||||
// Setup flash
|
// Setup flash
|
||||||
let flash = BlockingTestFlash::new(BootLoaderConfig {
|
let flash = BlockingTestFlash::new(BootLoaderConfig {
|
||||||
|
@ -4,12 +4,6 @@ name = "embassy-boot-nrf"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Bootloader lib for nRF chips"
|
description = "Bootloader lib for nRF chips"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/embassy-rs/embassy"
|
|
||||||
categories = [
|
|
||||||
"embedded",
|
|
||||||
"no-std",
|
|
||||||
"asynchronous",
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.metadata.embassy_docs]
|
[package.metadata.embassy_docs]
|
||||||
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/nrf/src/"
|
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/nrf/src/"
|
||||||
@ -31,7 +25,7 @@ embedded-storage = "0.3.1"
|
|||||||
embedded-storage-async = { version = "0.4.1" }
|
embedded-storage-async = { version = "0.4.1" }
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
|
|
||||||
nrf-softdevice-mbr = { version = "0.2.0", optional = true }
|
nrf-softdevice-mbr = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-softdevice.git", branch = "master", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
defmt = [
|
defmt = [
|
||||||
|
@ -4,12 +4,6 @@ name = "embassy-boot-rp"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Bootloader lib for RP2040 chips"
|
description = "Bootloader lib for RP2040 chips"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/embassy-rs/embassy"
|
|
||||||
categories = [
|
|
||||||
"embedded",
|
|
||||||
"no-std",
|
|
||||||
"asynchronous",
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.metadata.embassy_docs]
|
[package.metadata.embassy_docs]
|
||||||
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-rp-v$VERSION/src/"
|
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-rp-v$VERSION/src/"
|
||||||
|
@ -4,12 +4,6 @@ name = "embassy-boot-stm32"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Bootloader lib for STM32 chips"
|
description = "Bootloader lib for STM32 chips"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/embassy-rs/embassy"
|
|
||||||
categories = [
|
|
||||||
"embedded",
|
|
||||||
"no-std",
|
|
||||||
"asynchronous",
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.metadata.embassy_docs]
|
[package.metadata.embassy_docs]
|
||||||
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/stm32/src/"
|
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/stm32/src/"
|
||||||
|
@ -14,7 +14,7 @@ categories = [
|
|||||||
[package.metadata.embassy_docs]
|
[package.metadata.embassy_docs]
|
||||||
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/"
|
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/"
|
||||||
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/"
|
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/"
|
||||||
features = ["defmt"]
|
features = ["nightly", "defmt"]
|
||||||
flavors = [
|
flavors = [
|
||||||
{ name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] },
|
{ name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] },
|
||||||
{ name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] },
|
{ name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] },
|
||||||
@ -25,7 +25,7 @@ flavors = [
|
|||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
default-target = "thumbv7em-none-eabi"
|
default-target = "thumbv7em-none-eabi"
|
||||||
targets = ["thumbv7em-none-eabi"]
|
targets = ["thumbv7em-none-eabi"]
|
||||||
features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"]
|
features = ["nightly", "defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
defmt = { version = "0.3", optional = true }
|
defmt = { version = "0.3", optional = true }
|
||||||
|
@ -6,7 +6,8 @@ keywords = ["embedded", "ADIN1110", "embassy-net", "embedded-hal-async", "ethern
|
|||||||
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
|
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/embassy-rs/embassy"
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
heapless = "0.8"
|
heapless = "0.8"
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/// CRC32 lookup table.
|
|
||||||
pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [
|
pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [
|
||||||
0x0000_0000,
|
0x0000_0000,
|
||||||
0x7707_3096,
|
0x7707_3096,
|
||||||
@ -264,9 +263,8 @@ pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [
|
|||||||
pub struct ETH_FCS(pub u32);
|
pub struct ETH_FCS(pub u32);
|
||||||
|
|
||||||
impl ETH_FCS {
|
impl ETH_FCS {
|
||||||
const CRC32_OK: u32 = 0x2144_df1c;
|
pub const CRC32_OK: u32 = 0x2144_df1c;
|
||||||
|
|
||||||
/// Create a new frame check sequence from `data`.
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(data: &[u8]) -> Self {
|
pub fn new(data: &[u8]) -> Self {
|
||||||
let fcs = data.iter().fold(u32::MAX, |crc, byte| {
|
let fcs = data.iter().fold(u32::MAX, |crc, byte| {
|
||||||
@ -276,7 +274,6 @@ impl ETH_FCS {
|
|||||||
Self(fcs)
|
Self(fcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the frame check sequence with `data`.
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn update(self, data: &[u8]) -> Self {
|
pub fn update(self, data: &[u8]) -> Self {
|
||||||
let fcs = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| {
|
let fcs = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| {
|
||||||
@ -286,19 +283,16 @@ impl ETH_FCS {
|
|||||||
Self(fcs)
|
Self(fcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the frame check sequence is correct.
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn crc_ok(&self) -> bool {
|
pub fn crc_ok(&self) -> bool {
|
||||||
self.0 == Self::CRC32_OK
|
self.0 == Self::CRC32_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch byte order.
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn hton_bytes(&self) -> [u8; 4] {
|
pub fn hton_bytes(&self) -> [u8; 4] {
|
||||||
self.0.to_le_bytes()
|
self.0.to_le_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch byte order as a u32.
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn hton(&self) -> u32 {
|
pub fn hton(&self) -> u32 {
|
||||||
self.0.to_le()
|
self.0.to_le()
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#![allow(clippy::missing_errors_doc)]
|
#![allow(clippy::missing_errors_doc)]
|
||||||
#![allow(clippy::missing_panics_doc)]
|
#![allow(clippy::missing_panics_doc)]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
// must go first!
|
// must go first!
|
||||||
mod fmt;
|
mod fmt;
|
||||||
@ -27,9 +26,8 @@ use embedded_hal_async::digital::Wait;
|
|||||||
use embedded_hal_async::spi::{Error, Operation, SpiDevice};
|
use embedded_hal_async::spi::{Error, Operation, SpiDevice};
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
pub use mdio::MdioBus;
|
pub use mdio::MdioBus;
|
||||||
pub use phy::Phy10BaseT1x;
|
pub use phy::{Phy10BaseT1x, RegsC22, RegsC45};
|
||||||
use phy::{RegsC22, RegsC45};
|
pub use regs::{Config0, Config2, SpiRegisters as sr, Status0, Status1};
|
||||||
use regs::{Config0, Config2, SpiRegisters as sr, Status0, Status1};
|
|
||||||
|
|
||||||
use crate::fmt::Bytes;
|
use crate::fmt::Bytes;
|
||||||
use crate::regs::{LedCntrl, LedFunc, LedPol, LedPolarity, SpiHeader};
|
use crate::regs::{LedCntrl, LedFunc, LedPol, LedPolarity, SpiHeader};
|
||||||
@ -448,7 +446,6 @@ pub struct Runner<'d, SPI, INT, RST> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> {
|
impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> {
|
||||||
/// Run the driver.
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub async fn run(mut self) -> ! {
|
pub async fn run(mut self) -> ! {
|
||||||
loop {
|
loop {
|
||||||
|
@ -39,7 +39,6 @@ enum Reg13Op {
|
|||||||
///
|
///
|
||||||
/// Clause 45 methodes are bases on <https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf>
|
/// Clause 45 methodes are bases on <https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf>
|
||||||
pub trait MdioBus {
|
pub trait MdioBus {
|
||||||
/// Error type.
|
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
/// Read, Clause 22
|
/// Read, Clause 22
|
||||||
|
@ -2,7 +2,6 @@ use core::fmt::{Debug, Display};
|
|||||||
|
|
||||||
use bitfield::{bitfield, bitfield_bitrange, bitfield_fields};
|
use bitfield::{bitfield, bitfield_bitrange, bitfield_fields};
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
// must go first!
|
// must go first!
|
||||||
mod fmt;
|
mod fmt;
|
||||||
@ -16,9 +15,6 @@ use embassy_sync::blocking_mutex::Mutex;
|
|||||||
use embassy_sync::waitqueue::WakerRegistration;
|
use embassy_sync::waitqueue::WakerRegistration;
|
||||||
use embassy_sync::zerocopy_channel;
|
use embassy_sync::zerocopy_channel;
|
||||||
|
|
||||||
/// Channel state.
|
|
||||||
///
|
|
||||||
/// Holds a buffer of packets with size MTU, for both TX and RX.
|
|
||||||
pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
|
pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
|
||||||
rx: [PacketBuf<MTU>; N_RX],
|
rx: [PacketBuf<MTU>; N_RX],
|
||||||
tx: [PacketBuf<MTU>; N_TX],
|
tx: [PacketBuf<MTU>; N_TX],
|
||||||
@ -28,7 +24,6 @@ pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
|
|||||||
impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_TX> {
|
impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_TX> {
|
||||||
const NEW_PACKET: PacketBuf<MTU> = PacketBuf::new();
|
const NEW_PACKET: PacketBuf<MTU> = PacketBuf::new();
|
||||||
|
|
||||||
/// Create a new channel state.
|
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
rx: [Self::NEW_PACKET; N_RX],
|
rx: [Self::NEW_PACKET; N_RX],
|
||||||
@ -44,45 +39,33 @@ struct StateInner<'d, const MTU: usize> {
|
|||||||
shared: Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State of the LinkState
|
||||||
struct Shared {
|
struct Shared {
|
||||||
link_state: LinkState,
|
link_state: LinkState,
|
||||||
waker: WakerRegistration,
|
waker: WakerRegistration,
|
||||||
hardware_address: driver::HardwareAddress,
|
hardware_address: driver::HardwareAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel runner.
|
|
||||||
///
|
|
||||||
/// Holds the shared state and the lower end of channels for inbound and outbound packets.
|
|
||||||
pub struct Runner<'d, const MTU: usize> {
|
pub struct Runner<'d, const MTU: usize> {
|
||||||
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State runner.
|
|
||||||
///
|
|
||||||
/// Holds the shared state of the channel such as link state.
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct StateRunner<'d> {
|
pub struct StateRunner<'d> {
|
||||||
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RX runner.
|
|
||||||
///
|
|
||||||
/// Holds the lower end of the channel for passing inbound packets up the stack.
|
|
||||||
pub struct RxRunner<'d, const MTU: usize> {
|
pub struct RxRunner<'d, const MTU: usize> {
|
||||||
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TX runner.
|
|
||||||
///
|
|
||||||
/// Holds the lower end of the channel for passing outbound packets down the stack.
|
|
||||||
pub struct TxRunner<'d, const MTU: usize> {
|
pub struct TxRunner<'d, const MTU: usize> {
|
||||||
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, const MTU: usize> Runner<'d, MTU> {
|
impl<'d, const MTU: usize> Runner<'d, MTU> {
|
||||||
/// Split the runner into separate runners for controlling state, rx and tx.
|
|
||||||
pub fn split(self) -> (StateRunner<'d>, RxRunner<'d, MTU>, TxRunner<'d, MTU>) {
|
pub fn split(self) -> (StateRunner<'d>, RxRunner<'d, MTU>, TxRunner<'d, MTU>) {
|
||||||
(
|
(
|
||||||
StateRunner { shared: self.shared },
|
StateRunner { shared: self.shared },
|
||||||
@ -91,7 +74,6 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split the runner into separate runners for controlling state, rx and tx borrowing the underlying state.
|
|
||||||
pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) {
|
pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) {
|
||||||
(
|
(
|
||||||
StateRunner { shared: self.shared },
|
StateRunner { shared: self.shared },
|
||||||
@ -104,12 +86,10 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a state runner sharing the state channel.
|
|
||||||
pub fn state_runner(&self) -> StateRunner<'d> {
|
pub fn state_runner(&self) -> StateRunner<'d> {
|
||||||
StateRunner { shared: self.shared }
|
StateRunner { shared: self.shared }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the link state.
|
|
||||||
pub fn set_link_state(&mut self, state: LinkState) {
|
pub fn set_link_state(&mut self, state: LinkState) {
|
||||||
self.shared.lock(|s| {
|
self.shared.lock(|s| {
|
||||||
let s = &mut *s.borrow_mut();
|
let s = &mut *s.borrow_mut();
|
||||||
@ -118,7 +98,6 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the hardware address.
|
|
||||||
pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) {
|
pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) {
|
||||||
self.shared.lock(|s| {
|
self.shared.lock(|s| {
|
||||||
let s = &mut *s.borrow_mut();
|
let s = &mut *s.borrow_mut();
|
||||||
@ -127,19 +106,16 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until there is space for more inbound packets and return a slice they can be copied into.
|
|
||||||
pub async fn rx_buf(&mut self) -> &mut [u8] {
|
pub async fn rx_buf(&mut self) -> &mut [u8] {
|
||||||
let p = self.rx_chan.send().await;
|
let p = self.rx_chan.send().await;
|
||||||
&mut p.buf
|
&mut p.buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if there is space for more inbound packets right now.
|
|
||||||
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
|
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
|
||||||
let p = self.rx_chan.try_send()?;
|
let p = self.rx_chan.try_send()?;
|
||||||
Some(&mut p.buf)
|
Some(&mut p.buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Polling the inbound channel if there is space for packets.
|
|
||||||
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
||||||
match self.rx_chan.poll_send(cx) {
|
match self.rx_chan.poll_send(cx) {
|
||||||
Poll::Ready(p) => Poll::Ready(&mut p.buf),
|
Poll::Ready(p) => Poll::Ready(&mut p.buf),
|
||||||
@ -147,26 +123,22 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark packet of len bytes as pushed to the inbound channel.
|
|
||||||
pub fn rx_done(&mut self, len: usize) {
|
pub fn rx_done(&mut self, len: usize) {
|
||||||
let p = self.rx_chan.try_send().unwrap();
|
let p = self.rx_chan.try_send().unwrap();
|
||||||
p.len = len;
|
p.len = len;
|
||||||
self.rx_chan.send_done();
|
self.rx_chan.send_done();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until there is space for more outbound packets and return a slice they can be copied into.
|
|
||||||
pub async fn tx_buf(&mut self) -> &mut [u8] {
|
pub async fn tx_buf(&mut self) -> &mut [u8] {
|
||||||
let p = self.tx_chan.receive().await;
|
let p = self.tx_chan.receive().await;
|
||||||
&mut p.buf[..p.len]
|
&mut p.buf[..p.len]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if there is space for more outbound packets right now.
|
|
||||||
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
|
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
|
||||||
let p = self.tx_chan.try_receive()?;
|
let p = self.tx_chan.try_receive()?;
|
||||||
Some(&mut p.buf[..p.len])
|
Some(&mut p.buf[..p.len])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Polling the outbound channel if there is space for packets.
|
|
||||||
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
||||||
match self.tx_chan.poll_receive(cx) {
|
match self.tx_chan.poll_receive(cx) {
|
||||||
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
|
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
|
||||||
@ -174,14 +146,12 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark outbound packet as copied.
|
|
||||||
pub fn tx_done(&mut self) {
|
pub fn tx_done(&mut self) {
|
||||||
self.tx_chan.receive_done();
|
self.tx_chan.receive_done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> StateRunner<'d> {
|
impl<'d> StateRunner<'d> {
|
||||||
/// Set link state.
|
|
||||||
pub fn set_link_state(&self, state: LinkState) {
|
pub fn set_link_state(&self, state: LinkState) {
|
||||||
self.shared.lock(|s| {
|
self.shared.lock(|s| {
|
||||||
let s = &mut *s.borrow_mut();
|
let s = &mut *s.borrow_mut();
|
||||||
@ -190,7 +160,6 @@ impl<'d> StateRunner<'d> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the hardware address.
|
|
||||||
pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
|
pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
|
||||||
self.shared.lock(|s| {
|
self.shared.lock(|s| {
|
||||||
let s = &mut *s.borrow_mut();
|
let s = &mut *s.borrow_mut();
|
||||||
@ -201,19 +170,16 @@ impl<'d> StateRunner<'d> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, const MTU: usize> RxRunner<'d, MTU> {
|
impl<'d, const MTU: usize> RxRunner<'d, MTU> {
|
||||||
/// Wait until there is space for more inbound packets and return a slice they can be copied into.
|
|
||||||
pub async fn rx_buf(&mut self) -> &mut [u8] {
|
pub async fn rx_buf(&mut self) -> &mut [u8] {
|
||||||
let p = self.rx_chan.send().await;
|
let p = self.rx_chan.send().await;
|
||||||
&mut p.buf
|
&mut p.buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if there is space for more inbound packets right now.
|
|
||||||
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
|
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
|
||||||
let p = self.rx_chan.try_send()?;
|
let p = self.rx_chan.try_send()?;
|
||||||
Some(&mut p.buf)
|
Some(&mut p.buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Polling the inbound channel if there is space for packets.
|
|
||||||
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
||||||
match self.rx_chan.poll_send(cx) {
|
match self.rx_chan.poll_send(cx) {
|
||||||
Poll::Ready(p) => Poll::Ready(&mut p.buf),
|
Poll::Ready(p) => Poll::Ready(&mut p.buf),
|
||||||
@ -221,7 +187,6 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark packet of len bytes as pushed to the inbound channel.
|
|
||||||
pub fn rx_done(&mut self, len: usize) {
|
pub fn rx_done(&mut self, len: usize) {
|
||||||
let p = self.rx_chan.try_send().unwrap();
|
let p = self.rx_chan.try_send().unwrap();
|
||||||
p.len = len;
|
p.len = len;
|
||||||
@ -230,19 +195,16 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, const MTU: usize> TxRunner<'d, MTU> {
|
impl<'d, const MTU: usize> TxRunner<'d, MTU> {
|
||||||
/// Wait until there is space for more outbound packets and return a slice they can be copied into.
|
|
||||||
pub async fn tx_buf(&mut self) -> &mut [u8] {
|
pub async fn tx_buf(&mut self) -> &mut [u8] {
|
||||||
let p = self.tx_chan.receive().await;
|
let p = self.tx_chan.receive().await;
|
||||||
&mut p.buf[..p.len]
|
&mut p.buf[..p.len]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if there is space for more outbound packets right now.
|
|
||||||
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
|
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
|
||||||
let p = self.tx_chan.try_receive()?;
|
let p = self.tx_chan.try_receive()?;
|
||||||
Some(&mut p.buf[..p.len])
|
Some(&mut p.buf[..p.len])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Polling the outbound channel if there is space for packets.
|
|
||||||
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
||||||
match self.tx_chan.poll_receive(cx) {
|
match self.tx_chan.poll_receive(cx) {
|
||||||
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
|
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
|
||||||
@ -250,18 +212,11 @@ impl<'d, const MTU: usize> TxRunner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark outbound packet as copied.
|
|
||||||
pub fn tx_done(&mut self) {
|
pub fn tx_done(&mut self) {
|
||||||
self.tx_chan.receive_done();
|
self.tx_chan.receive_done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a channel.
|
|
||||||
///
|
|
||||||
/// Returns a pair of handles for interfacing with the peripheral and the networking stack.
|
|
||||||
///
|
|
||||||
/// The runner is interfacing with the peripheral at the lower part of the stack.
|
|
||||||
/// The device is interfacing with the networking stack on the layer above.
|
|
||||||
pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
|
pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
|
||||||
state: &'d mut State<MTU, N_RX, N_TX>,
|
state: &'d mut State<MTU, N_RX, N_TX>,
|
||||||
hardware_address: driver::HardwareAddress,
|
hardware_address: driver::HardwareAddress,
|
||||||
@ -302,22 +257,17 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a packet of size MTU.
|
|
||||||
pub struct PacketBuf<const MTU: usize> {
|
pub struct PacketBuf<const MTU: usize> {
|
||||||
len: usize,
|
len: usize,
|
||||||
buf: [u8; MTU],
|
buf: [u8; MTU],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const MTU: usize> PacketBuf<MTU> {
|
impl<const MTU: usize> PacketBuf<MTU> {
|
||||||
/// Create a new packet buffer.
|
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self { len: 0, buf: [0; MTU] }
|
Self { len: 0, buf: [0; MTU] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel device.
|
|
||||||
///
|
|
||||||
/// Holds the shared state and upper end of channels for inbound and outbound packets.
|
|
||||||
pub struct Device<'d, const MTU: usize> {
|
pub struct Device<'d, const MTU: usize> {
|
||||||
rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
@ -364,9 +314,6 @@ impl<'d, const MTU: usize> embassy_net_driver::Driver for Device<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A rx token.
|
|
||||||
///
|
|
||||||
/// Holds inbound receive channel and interfaces with embassy-net-driver.
|
|
||||||
pub struct RxToken<'a, const MTU: usize> {
|
pub struct RxToken<'a, const MTU: usize> {
|
||||||
rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>,
|
rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
@ -384,9 +331,6 @@ impl<'a, const MTU: usize> embassy_net_driver::RxToken for RxToken<'a, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A tx token.
|
|
||||||
///
|
|
||||||
/// Holds outbound transmit channel and interfaces with embassy-net-driver.
|
|
||||||
pub struct TxToken<'a, const MTU: usize> {
|
pub struct TxToken<'a, const MTU: usize> {
|
||||||
tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>,
|
tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
name = "embassy-net-esp-hosted"
|
name = "embassy-net-esp-hosted"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "embassy-net driver for ESP-Hosted"
|
|
||||||
keywords = ["embedded", "esp-hosted", "embassy-net", "embedded-hal-async", "wifi", "async"]
|
|
||||||
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
|
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
defmt = { version = "0.3", optional = true }
|
defmt = { version = "0.3", optional = true }
|
||||||
@ -19,7 +15,8 @@ embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-
|
|||||||
embedded-hal = { version = "1.0.0-rc.3" }
|
embedded-hal = { version = "1.0.0-rc.3" }
|
||||||
embedded-hal-async = { version = "=1.0.0-rc.3" }
|
embedded-hal-async = { version = "=1.0.0-rc.3" }
|
||||||
|
|
||||||
noproto = "0.1.0"
|
noproto = { git="https://github.com/embassy-rs/noproto", rev = "f5e6d1f325b6ad4e344f60452b09576e24671f62", default-features = false, features = ["derive"] }
|
||||||
|
#noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] }
|
||||||
heapless = "0.8"
|
heapless = "0.8"
|
||||||
|
|
||||||
[package.metadata.embassy_docs]
|
[package.metadata.embassy_docs]
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
# ESP-Hosted `embassy-net` integration
|
|
||||||
|
|
||||||
[`embassy-net`](https://crates.io/crates/embassy-net) integration for Espressif SoCs running the the ESP-Hosted stack.
|
|
||||||
|
|
||||||
See [`examples`](https://github.com/embassy-rs/embassy/tree/main/examples/nrf52840) directory for usage examples with the nRF52840.
|
|
||||||
|
|
||||||
## Supported chips
|
|
||||||
|
|
||||||
- W5500
|
|
||||||
- W5100S
|
|
||||||
|
|
||||||
## Interoperability
|
|
||||||
|
|
||||||
This crate can run on any executor.
|
|
||||||
|
|
||||||
It supports any SPI driver implementing [`embedded-hal-async`](https://crates.io/crates/embedded-hal-async).
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This work is licensed under either of
|
|
||||||
|
|
||||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
|
||||||
|
|
||||||
at your option.
|
|
@ -5,54 +5,38 @@ use heapless::String;
|
|||||||
use crate::ioctl::Shared;
|
use crate::ioctl::Shared;
|
||||||
use crate::proto::{self, CtrlMsg};
|
use crate::proto::{self, CtrlMsg};
|
||||||
|
|
||||||
/// Errors reported by control.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// The operation failed with the given error code.
|
|
||||||
Failed(u32),
|
Failed(u32),
|
||||||
/// The operation timed out.
|
|
||||||
Timeout,
|
Timeout,
|
||||||
/// Internal error.
|
|
||||||
Internal,
|
Internal,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle for managing the network and WiFI state.
|
|
||||||
pub struct Control<'a> {
|
pub struct Control<'a> {
|
||||||
state_ch: ch::StateRunner<'a>,
|
state_ch: ch::StateRunner<'a>,
|
||||||
shared: &'a Shared,
|
shared: &'a Shared,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// WiFi mode.
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
enum WifiMode {
|
enum WifiMode {
|
||||||
/// No mode.
|
|
||||||
None = 0,
|
None = 0,
|
||||||
/// Client station.
|
|
||||||
Sta = 1,
|
Sta = 1,
|
||||||
/// Access point mode.
|
|
||||||
Ap = 2,
|
Ap = 2,
|
||||||
/// Repeater mode.
|
|
||||||
ApSta = 3,
|
ApSta = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use proto::CtrlWifiSecProt as Security;
|
pub use proto::CtrlWifiSecProt as Security;
|
||||||
|
|
||||||
/// WiFi status.
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct Status {
|
pub struct Status {
|
||||||
/// Service Set Identifier.
|
|
||||||
pub ssid: String<32>,
|
pub ssid: String<32>,
|
||||||
/// Basic Service Set Identifier.
|
|
||||||
pub bssid: [u8; 6],
|
pub bssid: [u8; 6],
|
||||||
/// Received Signal Strength Indicator.
|
|
||||||
pub rssi: i32,
|
pub rssi: i32,
|
||||||
/// WiFi channel.
|
|
||||||
pub channel: u32,
|
pub channel: u32,
|
||||||
/// Security mode.
|
|
||||||
pub security: Security,
|
pub security: Security,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +65,6 @@ impl<'a> Control<'a> {
|
|||||||
Self { state_ch, shared }
|
Self { state_ch, shared }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize device.
|
|
||||||
pub async fn init(&mut self) -> Result<(), Error> {
|
pub async fn init(&mut self) -> Result<(), Error> {
|
||||||
debug!("wait for init event...");
|
debug!("wait for init event...");
|
||||||
self.shared.init_wait().await;
|
self.shared.init_wait().await;
|
||||||
@ -99,7 +82,6 @@ impl<'a> Control<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current status.
|
|
||||||
pub async fn get_status(&mut self) -> Result<Status, Error> {
|
pub async fn get_status(&mut self) -> Result<Status, Error> {
|
||||||
let req = proto::CtrlMsgReqGetApConfig {};
|
let req = proto::CtrlMsgReqGetApConfig {};
|
||||||
ioctl!(self, ReqGetApConfig, RespGetApConfig, req, resp);
|
ioctl!(self, ReqGetApConfig, RespGetApConfig, req, resp);
|
||||||
@ -113,7 +95,6 @@ impl<'a> Control<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connect to the network identified by ssid using the provided password.
|
|
||||||
pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> {
|
pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> {
|
||||||
let req = proto::CtrlMsgReqConnectAp {
|
let req = proto::CtrlMsgReqConnectAp {
|
||||||
ssid: unwrap!(String::try_from(ssid)),
|
ssid: unwrap!(String::try_from(ssid)),
|
||||||
@ -127,7 +108,6 @@ impl<'a> Control<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disconnect from any currently connected network.
|
|
||||||
pub async fn disconnect(&mut self) -> Result<(), Error> {
|
pub async fn disconnect(&mut self) -> Result<(), Error> {
|
||||||
let req = proto::CtrlMsgReqGetStatus {};
|
let req = proto::CtrlMsgReqGetStatus {};
|
||||||
ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp);
|
ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp);
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![doc = include_str!("../README.md")]
|
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
use embassy_futures::select::{select4, Either4};
|
use embassy_futures::select::{select4, Either4};
|
||||||
use embassy_net_driver_channel as ch;
|
use embassy_net_driver_channel as ch;
|
||||||
@ -99,14 +97,12 @@ enum InterfaceType {
|
|||||||
const MAX_SPI_BUFFER_SIZE: usize = 1600;
|
const MAX_SPI_BUFFER_SIZE: usize = 1600;
|
||||||
const HEARTBEAT_MAX_GAP: Duration = Duration::from_secs(20);
|
const HEARTBEAT_MAX_GAP: Duration = Duration::from_secs(20);
|
||||||
|
|
||||||
/// State for the esp-hosted driver.
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
shared: Shared,
|
shared: Shared,
|
||||||
ch: ch::State<MTU, 4, 4>,
|
ch: ch::State<MTU, 4, 4>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
/// Create a new state.
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
shared: Shared::new(),
|
shared: Shared::new(),
|
||||||
@ -115,13 +111,8 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type alias for network driver.
|
|
||||||
pub type NetDriver<'a> = ch::Device<'a, MTU>;
|
pub type NetDriver<'a> = ch::Device<'a, MTU>;
|
||||||
|
|
||||||
/// Create a new esp-hosted driver using the provided state, SPI peripheral and pins.
|
|
||||||
///
|
|
||||||
/// Returns a device handle for interfacing with embassy-net, a control handle for
|
|
||||||
/// interacting with the driver, and a runner for communicating with the WiFi device.
|
|
||||||
pub async fn new<'a, SPI, IN, OUT>(
|
pub async fn new<'a, SPI, IN, OUT>(
|
||||||
state: &'a mut State,
|
state: &'a mut State,
|
||||||
spi: SPI,
|
spi: SPI,
|
||||||
@ -153,7 +144,6 @@ where
|
|||||||
(device, Control::new(state_ch, &state.shared), runner)
|
(device, Control::new(state_ch, &state.shared), runner)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runner for communicating with the WiFi device.
|
|
||||||
pub struct Runner<'a, SPI, IN, OUT> {
|
pub struct Runner<'a, SPI, IN, OUT> {
|
||||||
ch: ch::Runner<'a, MTU>,
|
ch: ch::Runner<'a, MTU>,
|
||||||
state_ch: ch::StateRunner<'a>,
|
state_ch: ch::StateRunner<'a>,
|
||||||
@ -176,7 +166,6 @@ where
|
|||||||
{
|
{
|
||||||
async fn init(&mut self) {}
|
async fn init(&mut self) {}
|
||||||
|
|
||||||
/// Run the packet processing.
|
|
||||||
pub async fn run(mut self) -> ! {
|
pub async fn run(mut self) -> ! {
|
||||||
debug!("resetting...");
|
debug!("resetting...");
|
||||||
self.reset.set_low().unwrap();
|
self.reset.set_low().unwrap();
|
||||||
|
@ -4,7 +4,7 @@ use heapless::{String, Vec};
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct ScanResult {
|
pub struct ScanResult {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub ssid: String<32>,
|
pub ssid: String<32>,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -19,7 +19,7 @@ pub(crate) struct ScanResult {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct ConnectedStaList {
|
pub struct ConnectedStaList {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub mac: String<32>,
|
pub mac: String<32>,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -29,14 +29,14 @@ pub(crate) struct ConnectedStaList {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqGetMacAddress {
|
pub struct CtrlMsgReqGetMacAddress {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub mode: u32,
|
pub mode: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespGetMacAddress {
|
pub struct CtrlMsgRespGetMacAddress {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub mac: String<32>,
|
pub mac: String<32>,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -45,11 +45,11 @@ pub(crate) struct CtrlMsgRespGetMacAddress {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqGetMode {}
|
pub struct CtrlMsgReqGetMode {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespGetMode {
|
pub struct CtrlMsgRespGetMode {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub mode: u32,
|
pub mode: u32,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -58,32 +58,32 @@ pub(crate) struct CtrlMsgRespGetMode {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqSetMode {
|
pub struct CtrlMsgReqSetMode {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub mode: u32,
|
pub mode: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespSetMode {
|
pub struct CtrlMsgRespSetMode {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqGetStatus {}
|
pub struct CtrlMsgReqGetStatus {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespGetStatus {
|
pub struct CtrlMsgRespGetStatus {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqSetMacAddress {
|
pub struct CtrlMsgReqSetMacAddress {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub mac: String<32>,
|
pub mac: String<32>,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -92,18 +92,18 @@ pub(crate) struct CtrlMsgReqSetMacAddress {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespSetMacAddress {
|
pub struct CtrlMsgRespSetMacAddress {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqGetApConfig {}
|
pub struct CtrlMsgReqGetApConfig {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespGetApConfig {
|
pub struct CtrlMsgRespGetApConfig {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub ssid: String<32>,
|
pub ssid: String<32>,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -120,7 +120,7 @@ pub(crate) struct CtrlMsgRespGetApConfig {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqConnectAp {
|
pub struct CtrlMsgReqConnectAp {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub ssid: String<32>,
|
pub ssid: String<32>,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -135,7 +135,7 @@ pub(crate) struct CtrlMsgReqConnectAp {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespConnectAp {
|
pub struct CtrlMsgRespConnectAp {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -144,11 +144,11 @@ pub(crate) struct CtrlMsgRespConnectAp {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqGetSoftApConfig {}
|
pub struct CtrlMsgReqGetSoftApConfig {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespGetSoftApConfig {
|
pub struct CtrlMsgRespGetSoftApConfig {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub ssid: String<32>,
|
pub ssid: String<32>,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -169,7 +169,7 @@ pub(crate) struct CtrlMsgRespGetSoftApConfig {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqStartSoftAp {
|
pub struct CtrlMsgReqStartSoftAp {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub ssid: String<32>,
|
pub ssid: String<32>,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -188,7 +188,7 @@ pub(crate) struct CtrlMsgReqStartSoftAp {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespStartSoftAp {
|
pub struct CtrlMsgRespStartSoftAp {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -197,11 +197,11 @@ pub(crate) struct CtrlMsgRespStartSoftAp {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqScanResult {}
|
pub struct CtrlMsgReqScanResult {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespScanResult {
|
pub struct CtrlMsgRespScanResult {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub count: u32,
|
pub count: u32,
|
||||||
#[noproto(repeated, tag = "2")]
|
#[noproto(repeated, tag = "2")]
|
||||||
@ -212,11 +212,11 @@ pub(crate) struct CtrlMsgRespScanResult {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqSoftApConnectedSta {}
|
pub struct CtrlMsgReqSoftApConnectedSta {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespSoftApConnectedSta {
|
pub struct CtrlMsgRespSoftApConnectedSta {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub num: u32,
|
pub num: u32,
|
||||||
#[noproto(repeated, tag = "2")]
|
#[noproto(repeated, tag = "2")]
|
||||||
@ -227,43 +227,43 @@ pub(crate) struct CtrlMsgRespSoftApConnectedSta {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqOtaBegin {}
|
pub struct CtrlMsgReqOtaBegin {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespOtaBegin {
|
pub struct CtrlMsgRespOtaBegin {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqOtaWrite {
|
pub struct CtrlMsgReqOtaWrite {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub ota_data: Vec<u8, 1024>,
|
pub ota_data: Vec<u8, 1024>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespOtaWrite {
|
pub struct CtrlMsgRespOtaWrite {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqOtaEnd {}
|
pub struct CtrlMsgReqOtaEnd {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespOtaEnd {
|
pub struct CtrlMsgRespOtaEnd {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqVendorIeData {
|
pub struct CtrlMsgReqVendorIeData {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub element_id: u32,
|
pub element_id: u32,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -278,7 +278,7 @@ pub(crate) struct CtrlMsgReqVendorIeData {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqSetSoftApVendorSpecificIe {
|
pub struct CtrlMsgReqSetSoftApVendorSpecificIe {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -291,32 +291,32 @@ pub(crate) struct CtrlMsgReqSetSoftApVendorSpecificIe {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespSetSoftApVendorSpecificIe {
|
pub struct CtrlMsgRespSetSoftApVendorSpecificIe {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqSetWifiMaxTxPower {
|
pub struct CtrlMsgReqSetWifiMaxTxPower {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub wifi_max_tx_power: u32,
|
pub wifi_max_tx_power: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespSetWifiMaxTxPower {
|
pub struct CtrlMsgRespSetWifiMaxTxPower {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqGetWifiCurrTxPower {}
|
pub struct CtrlMsgReqGetWifiCurrTxPower {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespGetWifiCurrTxPower {
|
pub struct CtrlMsgRespGetWifiCurrTxPower {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub wifi_curr_tx_power: u32,
|
pub wifi_curr_tx_power: u32,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -325,7 +325,7 @@ pub(crate) struct CtrlMsgRespGetWifiCurrTxPower {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgReqConfigHeartbeat {
|
pub struct CtrlMsgReqConfigHeartbeat {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -334,7 +334,7 @@ pub(crate) struct CtrlMsgReqConfigHeartbeat {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgRespConfigHeartbeat {
|
pub struct CtrlMsgRespConfigHeartbeat {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
@ -342,28 +342,28 @@ pub(crate) struct CtrlMsgRespConfigHeartbeat {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgEventEspInit {
|
pub struct CtrlMsgEventEspInit {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub init_data: Vec<u8, 64>,
|
pub init_data: Vec<u8, 64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgEventHeartbeat {
|
pub struct CtrlMsgEventHeartbeat {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub hb_num: u32,
|
pub hb_num: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgEventStationDisconnectFromAp {
|
pub struct CtrlMsgEventStationDisconnectFromAp {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsgEventStationDisconnectFromEspSoftAp {
|
pub struct CtrlMsgEventStationDisconnectFromEspSoftAp {
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub resp: u32,
|
pub resp: u32,
|
||||||
#[noproto(tag = "2")]
|
#[noproto(tag = "2")]
|
||||||
@ -372,7 +372,7 @@ pub(crate) struct CtrlMsgEventStationDisconnectFromEspSoftAp {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct CtrlMsg {
|
pub struct CtrlMsg {
|
||||||
/// msg_type could be req, resp or Event
|
/// msg_type could be req, resp or Event
|
||||||
#[noproto(tag = "1")]
|
#[noproto(tag = "1")]
|
||||||
pub msg_type: CtrlMsgType,
|
pub msg_type: CtrlMsgType,
|
||||||
@ -390,7 +390,7 @@ pub(crate) struct CtrlMsg {
|
|||||||
/// union of all msg ids
|
/// union of all msg ids
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, noproto::Oneof)]
|
#[derive(Debug, Clone, Eq, PartialEq, noproto::Oneof)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlMsgPayload {
|
pub enum CtrlMsgPayload {
|
||||||
/// * Requests *
|
/// * Requests *
|
||||||
#[noproto(tag = "101")]
|
#[noproto(tag = "101")]
|
||||||
ReqGetMacAddress(CtrlMsgReqGetMacAddress),
|
ReqGetMacAddress(CtrlMsgReqGetMacAddress),
|
||||||
@ -492,7 +492,7 @@ pub(crate) enum CtrlMsgPayload {
|
|||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlVendorIeType {
|
pub enum CtrlVendorIeType {
|
||||||
#[default]
|
#[default]
|
||||||
Beacon = 0,
|
Beacon = 0,
|
||||||
ProbeReq = 1,
|
ProbeReq = 1,
|
||||||
@ -504,7 +504,7 @@ pub(crate) enum CtrlVendorIeType {
|
|||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlVendorIeid {
|
pub enum CtrlVendorIeid {
|
||||||
#[default]
|
#[default]
|
||||||
Id0 = 0,
|
Id0 = 0,
|
||||||
Id1 = 1,
|
Id1 = 1,
|
||||||
@ -513,7 +513,7 @@ pub(crate) enum CtrlVendorIeid {
|
|||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlWifiMode {
|
pub enum CtrlWifiMode {
|
||||||
#[default]
|
#[default]
|
||||||
None = 0,
|
None = 0,
|
||||||
Sta = 1,
|
Sta = 1,
|
||||||
@ -524,7 +524,7 @@ pub(crate) enum CtrlWifiMode {
|
|||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlWifiBw {
|
pub enum CtrlWifiBw {
|
||||||
#[default]
|
#[default]
|
||||||
BwInvalid = 0,
|
BwInvalid = 0,
|
||||||
Ht20 = 1,
|
Ht20 = 1,
|
||||||
@ -534,15 +534,13 @@ pub(crate) enum CtrlWifiBw {
|
|||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlWifiPowerSave {
|
pub enum CtrlWifiPowerSave {
|
||||||
#[default]
|
#[default]
|
||||||
PsInvalid = 0,
|
PsInvalid = 0,
|
||||||
MinModem = 1,
|
MinModem = 1,
|
||||||
MaxModem = 2,
|
MaxModem = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wifi Security Settings
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@ -562,7 +560,7 @@ pub enum CtrlWifiSecProt {
|
|||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlStatus {
|
pub enum CtrlStatus {
|
||||||
#[default]
|
#[default]
|
||||||
Connected = 0,
|
Connected = 0,
|
||||||
NotConnected = 1,
|
NotConnected = 1,
|
||||||
@ -575,7 +573,7 @@ pub(crate) enum CtrlStatus {
|
|||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlMsgType {
|
pub enum CtrlMsgType {
|
||||||
#[default]
|
#[default]
|
||||||
MsgTypeInvalid = 0,
|
MsgTypeInvalid = 0,
|
||||||
Req = 1,
|
Req = 1,
|
||||||
@ -587,7 +585,7 @@ pub(crate) enum CtrlMsgType {
|
|||||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) enum CtrlMsgId {
|
pub enum CtrlMsgId {
|
||||||
#[default]
|
#[default]
|
||||||
MsgIdInvalid = 0,
|
MsgIdInvalid = 0,
|
||||||
/// * Request Msgs *
|
/// * Request Msgs *
|
||||||
|
@ -6,7 +6,6 @@ keywords = ["embedded", "tuntap", "embassy-net", "embedded-hal-async", "ethernet
|
|||||||
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
|
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/embassy-rs/embassy"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
|
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#![warn(missing_docs)]
|
|
||||||
#![doc = include_str!("../README.md")]
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
@ -9,19 +7,12 @@ use async_io::Async;
|
|||||||
use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState};
|
use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState};
|
||||||
use log::*;
|
use log::*;
|
||||||
|
|
||||||
/// Get the MTU of the given interface.
|
|
||||||
pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
|
pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
|
||||||
/// Get the index of the given interface.
|
|
||||||
pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933;
|
pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933;
|
||||||
/// Capture all packages.
|
|
||||||
pub const _ETH_P_ALL: libc::c_short = 0x0003;
|
pub const _ETH_P_ALL: libc::c_short = 0x0003;
|
||||||
/// Set the interface flags.
|
|
||||||
pub const TUNSETIFF: libc::c_ulong = 0x400454CA;
|
pub const TUNSETIFF: libc::c_ulong = 0x400454CA;
|
||||||
/// TUN device.
|
|
||||||
pub const _IFF_TUN: libc::c_int = 0x0001;
|
pub const _IFF_TUN: libc::c_int = 0x0001;
|
||||||
/// TAP device.
|
|
||||||
pub const IFF_TAP: libc::c_int = 0x0002;
|
pub const IFF_TAP: libc::c_int = 0x0002;
|
||||||
/// No packet information.
|
|
||||||
pub const IFF_NO_PI: libc::c_int = 0x1000;
|
pub const IFF_NO_PI: libc::c_int = 0x1000;
|
||||||
|
|
||||||
const ETHERNET_HEADER_LEN: usize = 14;
|
const ETHERNET_HEADER_LEN: usize = 14;
|
||||||
@ -56,7 +47,6 @@ fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq, cmd: libc::c_ulong) -> io:
|
|||||||
Ok(ifreq.ifr_data)
|
Ok(ifreq.ifr_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A TUN/TAP device.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TunTap {
|
pub struct TunTap {
|
||||||
fd: libc::c_int,
|
fd: libc::c_int,
|
||||||
@ -70,7 +60,6 @@ impl AsRawFd for TunTap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TunTap {
|
impl TunTap {
|
||||||
/// Create a new TUN/TAP device.
|
|
||||||
pub fn new(name: &str) -> io::Result<TunTap> {
|
pub fn new(name: &str) -> io::Result<TunTap> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let fd = libc::open(
|
let fd = libc::open(
|
||||||
@ -137,13 +126,11 @@ impl io::Write for TunTap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A TUN/TAP device, wrapped in an async interface.
|
|
||||||
pub struct TunTapDevice {
|
pub struct TunTapDevice {
|
||||||
device: Async<TunTap>,
|
device: Async<TunTap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TunTapDevice {
|
impl TunTapDevice {
|
||||||
/// Create a new TUN/TAP device.
|
|
||||||
pub fn new(name: &str) -> io::Result<TunTapDevice> {
|
pub fn new(name: &str) -> io::Result<TunTapDevice> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
device: Async::new(TunTap::new(name)?)?,
|
device: Async::new(TunTap::new(name)?)?,
|
||||||
|
@ -6,7 +6,6 @@ keywords = ["embedded", "wiznet", "embassy-net", "embedded-hal-async", "ethernet
|
|||||||
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
|
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/embassy-rs/embassy"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embedded-hal = { version = "1.0.0-rc.3" }
|
embedded-hal = { version = "1.0.0-rc.3" }
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! Wiznet W5100s and W5500 family driver.
|
|
||||||
mod w5500;
|
mod w5500;
|
||||||
pub use w5500::W5500;
|
pub use w5500::W5500;
|
||||||
mod w5100s;
|
mod w5100s;
|
||||||
@ -46,5 +45,4 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for Wiznet chips.
|
|
||||||
pub trait Chip: sealed::Chip {}
|
pub trait Chip: sealed::Chip {}
|
||||||
|
@ -4,7 +4,6 @@ const SOCKET_BASE: u16 = 0x400;
|
|||||||
const TX_BASE: u16 = 0x4000;
|
const TX_BASE: u16 = 0x4000;
|
||||||
const RX_BASE: u16 = 0x6000;
|
const RX_BASE: u16 = 0x6000;
|
||||||
|
|
||||||
/// Wizard W5100S chip.
|
|
||||||
pub enum W5100S {}
|
pub enum W5100S {}
|
||||||
|
|
||||||
impl super::Chip for W5100S {}
|
impl super::Chip for W5100S {}
|
||||||
|
@ -8,7 +8,6 @@ pub enum RegisterBlock {
|
|||||||
RxBuf = 0x03,
|
RxBuf = 0x03,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wiznet W5500 chip.
|
|
||||||
pub enum W5500 {}
|
pub enum W5500 {}
|
||||||
|
|
||||||
impl super::Chip for W5500 {}
|
impl super::Chip for W5500 {}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
pub mod chip;
|
pub mod chip;
|
||||||
mod device;
|
mod device;
|
||||||
@ -48,7 +47,6 @@ pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
|
|||||||
|
|
||||||
/// You must call this in a background task for the driver to operate.
|
/// You must call this in a background task for the driver to operate.
|
||||||
impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
|
impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
|
||||||
/// Run the driver.
|
|
||||||
pub async fn run(mut self) -> ! {
|
pub async fn run(mut self) -> ! {
|
||||||
let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
|
let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
|
||||||
let mut tick = Ticker::every(Duration::from_millis(500));
|
let mut tick = Ticker::every(Duration::from_millis(500));
|
||||||
|
@ -411,12 +411,10 @@ impl<D: Driver> Stack<D> {
|
|||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// let config = embassy_net::Config::dhcpv4(Default::default());
|
/// let config = embassy_net::Config::dhcpv4(Default::default());
|
||||||
///// Init network stack
|
///// Init network stack
|
||||||
/// static RESOURCES: StaticCell<embassy_net::StackResources<2> = StaticCell::new();
|
/// let stack = &*make_static!(embassy_net::Stack::new(
|
||||||
/// static STACK: StaticCell<embassy_net::Stack> = StaticCell::new();
|
|
||||||
/// let stack = &*STACK.init(embassy_net::Stack::new(
|
|
||||||
/// device,
|
/// device,
|
||||||
/// config,
|
/// config,
|
||||||
/// RESOURCES.init(embassy_net::StackResources::new()),
|
/// make_static!(embassy_net::StackResources::<2>::new()),
|
||||||
/// seed
|
/// seed
|
||||||
/// ));
|
/// ));
|
||||||
/// // Launch network task that runs `stack.run().await`
|
/// // Launch network task that runs `stack.run().await`
|
||||||
|
@ -87,5 +87,5 @@ pio = {version= "0.2.1" }
|
|||||||
rp2040-boot2 = "0.3"
|
rp2040-boot2 = "0.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
embassy-executor = { version = "0.4.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] }
|
embassy-executor = { version = "0.4.0", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] }
|
||||||
static_cell = { version = "2" }
|
static_cell = { version = "2" }
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! ADC driver.
|
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
@ -17,7 +16,6 @@ use crate::{dma, interrupt, pac, peripherals, Peripheral, RegExt};
|
|||||||
|
|
||||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||||
|
|
||||||
/// ADC config.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct Config {}
|
pub struct Config {}
|
||||||
|
|
||||||
@ -32,11 +30,9 @@ enum Source<'p> {
|
|||||||
TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>),
|
TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ADC channel.
|
|
||||||
pub struct Channel<'p>(Source<'p>);
|
pub struct Channel<'p>(Source<'p>);
|
||||||
|
|
||||||
impl<'p> Channel<'p> {
|
impl<'p> Channel<'p> {
|
||||||
/// Create a new ADC channel from pin with the provided [Pull] configuration.
|
|
||||||
pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self {
|
pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self {
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
pin.pad_ctrl().modify(|w| {
|
pin.pad_ctrl().modify(|w| {
|
||||||
@ -53,7 +49,6 @@ impl<'p> Channel<'p> {
|
|||||||
Self(Source::Pin(pin.map_into()))
|
Self(Source::Pin(pin.map_into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new ADC channel for the internal temperature sensor.
|
|
||||||
pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self {
|
pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self {
|
||||||
let r = pac::ADC;
|
let r = pac::ADC;
|
||||||
r.cs().write_set(|w| w.set_ts_en(true));
|
r.cs().write_set(|w| w.set_ts_en(true));
|
||||||
@ -88,44 +83,35 @@ impl<'p> Drop for Source<'p> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ADC sample.
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Sample(u16);
|
pub struct Sample(u16);
|
||||||
|
|
||||||
impl Sample {
|
impl Sample {
|
||||||
/// Sample is valid.
|
|
||||||
pub fn good(&self) -> bool {
|
pub fn good(&self) -> bool {
|
||||||
self.0 < 0x8000
|
self.0 < 0x8000
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sample value.
|
|
||||||
pub fn value(&self) -> u16 {
|
pub fn value(&self) -> u16 {
|
||||||
self.0 & !0x8000
|
self.0 & !0x8000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ADC error.
|
|
||||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Error converting value.
|
|
||||||
ConversionFailed,
|
ConversionFailed,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ADC mode.
|
|
||||||
pub trait Mode {}
|
pub trait Mode {}
|
||||||
|
|
||||||
/// ADC async mode.
|
|
||||||
pub struct Async;
|
pub struct Async;
|
||||||
impl Mode for Async {}
|
impl Mode for Async {}
|
||||||
|
|
||||||
/// ADC blocking mode.
|
|
||||||
pub struct Blocking;
|
pub struct Blocking;
|
||||||
impl Mode for Blocking {}
|
impl Mode for Blocking {}
|
||||||
|
|
||||||
/// ADC driver.
|
|
||||||
pub struct Adc<'d, M: Mode> {
|
pub struct Adc<'d, M: Mode> {
|
||||||
phantom: PhantomData<(&'d ADC, M)>,
|
phantom: PhantomData<(&'d ADC, M)>,
|
||||||
}
|
}
|
||||||
@ -164,7 +150,6 @@ impl<'d, M: Mode> Adc<'d, M> {
|
|||||||
while !r.cs().read().ready() {}
|
while !r.cs().read().ready() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sample a value from a channel in blocking mode.
|
|
||||||
pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> {
|
pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> {
|
||||||
let r = Self::regs();
|
let r = Self::regs();
|
||||||
r.cs().modify(|w| {
|
r.cs().modify(|w| {
|
||||||
@ -181,7 +166,6 @@ impl<'d, M: Mode> Adc<'d, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> Adc<'d, Async> {
|
impl<'d> Adc<'d, Async> {
|
||||||
/// Create ADC driver in async mode.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
_inner: impl Peripheral<P = ADC> + 'd,
|
_inner: impl Peripheral<P = ADC> + 'd,
|
||||||
_irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>,
|
_irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>,
|
||||||
@ -210,7 +194,6 @@ impl<'d> Adc<'d, Async> {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sample a value from a channel until completed.
|
|
||||||
pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> {
|
pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> {
|
||||||
let r = Self::regs();
|
let r = Self::regs();
|
||||||
r.cs().modify(|w| {
|
r.cs().modify(|w| {
|
||||||
@ -289,7 +272,6 @@ impl<'d> Adc<'d, Async> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sample multiple values from a channel using DMA.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn read_many<S: AdcSample>(
|
pub async fn read_many<S: AdcSample>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -301,7 +283,6 @@ impl<'d> Adc<'d, Async> {
|
|||||||
self.read_many_inner(ch, buf, false, div, dma).await
|
self.read_many_inner(ch, buf, false, div, dma).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sample multiple values from a channel using DMA with errors inlined in samples.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn read_many_raw(
|
pub async fn read_many_raw(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -318,7 +299,6 @@ impl<'d> Adc<'d, Async> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> Adc<'d, Blocking> {
|
impl<'d> Adc<'d, Blocking> {
|
||||||
/// Create ADC driver in blocking mode.
|
|
||||||
pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self {
|
pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self {
|
||||||
Self::setup();
|
Self::setup();
|
||||||
|
|
||||||
@ -326,7 +306,6 @@ impl<'d> Adc<'d, Blocking> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interrupt handler.
|
|
||||||
pub struct InterruptHandler {
|
pub struct InterruptHandler {
|
||||||
_empty: (),
|
_empty: (),
|
||||||
}
|
}
|
||||||
@ -345,7 +324,6 @@ mod sealed {
|
|||||||
pub trait AdcChannel {}
|
pub trait AdcChannel {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ADC sample.
|
|
||||||
pub trait AdcSample: sealed::AdcSample {}
|
pub trait AdcSample: sealed::AdcSample {}
|
||||||
|
|
||||||
impl sealed::AdcSample for u16 {}
|
impl sealed::AdcSample for u16 {}
|
||||||
@ -354,9 +332,7 @@ impl AdcSample for u16 {}
|
|||||||
impl sealed::AdcSample for u8 {}
|
impl sealed::AdcSample for u8 {}
|
||||||
impl AdcSample for u8 {}
|
impl AdcSample for u8 {}
|
||||||
|
|
||||||
/// ADC channel.
|
|
||||||
pub trait AdcChannel: sealed::AdcChannel {}
|
pub trait AdcChannel: sealed::AdcChannel {}
|
||||||
/// ADC pin.
|
|
||||||
pub trait AdcPin: AdcChannel + gpio::Pin {}
|
pub trait AdcPin: AdcChannel + gpio::Pin {}
|
||||||
|
|
||||||
macro_rules! impl_pin {
|
macro_rules! impl_pin {
|
||||||
|
@ -45,20 +45,15 @@ static CLOCKS: Clocks = Clocks {
|
|||||||
rtc: AtomicU16::new(0),
|
rtc: AtomicU16::new(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Peripheral clock sources.
|
/// Enumeration of supported clock sources.
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum PeriClkSrc {
|
pub enum PeriClkSrc {
|
||||||
/// SYS.
|
|
||||||
Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _,
|
Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _,
|
||||||
/// PLL SYS.
|
|
||||||
PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
||||||
/// PLL USB.
|
|
||||||
PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
||||||
/// ROSC.
|
|
||||||
Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _,
|
Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _,
|
||||||
/// XOSC.
|
|
||||||
Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _,
|
Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _,
|
||||||
// Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
// Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
||||||
// Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
// Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
||||||
@ -88,7 +83,6 @@ pub struct ClockConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ClockConfig {
|
impl ClockConfig {
|
||||||
/// Clock configuration derived from external crystal.
|
|
||||||
pub fn crystal(crystal_hz: u32) -> Self {
|
pub fn crystal(crystal_hz: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rosc: Some(RoscConfig {
|
rosc: Some(RoscConfig {
|
||||||
@ -147,7 +141,6 @@ impl ClockConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clock configuration from internal oscillator.
|
|
||||||
pub fn rosc() -> Self {
|
pub fn rosc() -> Self {
|
||||||
Self {
|
Self {
|
||||||
rosc: Some(RoscConfig {
|
rosc: Some(RoscConfig {
|
||||||
@ -197,18 +190,13 @@ impl ClockConfig {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ROSC freq range.
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum RoscRange {
|
pub enum RoscRange {
|
||||||
/// Low range.
|
|
||||||
Low = pac::rosc::vals::FreqRange::LOW.0,
|
Low = pac::rosc::vals::FreqRange::LOW.0,
|
||||||
/// Medium range (1.33x low)
|
|
||||||
Medium = pac::rosc::vals::FreqRange::MEDIUM.0,
|
Medium = pac::rosc::vals::FreqRange::MEDIUM.0,
|
||||||
/// High range (2x low)
|
|
||||||
High = pac::rosc::vals::FreqRange::HIGH.0,
|
High = pac::rosc::vals::FreqRange::HIGH.0,
|
||||||
/// Too high. Should not be used.
|
|
||||||
TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0,
|
TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,136 +239,96 @@ pub struct PllConfig {
|
|||||||
pub post_div2: u8,
|
pub post_div2: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reference clock config.
|
/// Reference
|
||||||
pub struct RefClkConfig {
|
pub struct RefClkConfig {
|
||||||
/// Reference clock source.
|
|
||||||
pub src: RefClkSrc,
|
pub src: RefClkSrc,
|
||||||
/// Reference clock divider.
|
|
||||||
pub div: u8,
|
pub div: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reference clock source.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum RefClkSrc {
|
pub enum RefClkSrc {
|
||||||
/// XOSC.
|
// main sources
|
||||||
Xosc,
|
Xosc,
|
||||||
/// ROSC.
|
|
||||||
Rosc,
|
Rosc,
|
||||||
/// PLL USB.
|
// aux sources
|
||||||
PllUsb,
|
PllUsb,
|
||||||
// Gpin0,
|
// Gpin0,
|
||||||
// Gpin1,
|
// Gpin1,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SYS clock source.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum SysClkSrc {
|
pub enum SysClkSrc {
|
||||||
/// REF.
|
// main sources
|
||||||
Ref,
|
Ref,
|
||||||
/// PLL SYS.
|
// aux sources
|
||||||
PllSys,
|
PllSys,
|
||||||
/// PLL USB.
|
|
||||||
PllUsb,
|
PllUsb,
|
||||||
/// ROSC.
|
|
||||||
Rosc,
|
Rosc,
|
||||||
/// XOSC.
|
|
||||||
Xosc,
|
Xosc,
|
||||||
// Gpin0,
|
// Gpin0,
|
||||||
// Gpin1,
|
// Gpin1,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SYS clock config.
|
|
||||||
pub struct SysClkConfig {
|
pub struct SysClkConfig {
|
||||||
/// SYS clock source.
|
|
||||||
pub src: SysClkSrc,
|
pub src: SysClkSrc,
|
||||||
/// SYS clock divider.
|
|
||||||
pub div_int: u32,
|
pub div_int: u32,
|
||||||
/// SYS clock fraction.
|
|
||||||
pub div_frac: u8,
|
pub div_frac: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB clock source.
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum UsbClkSrc {
|
pub enum UsbClkSrc {
|
||||||
/// PLL USB.
|
|
||||||
PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
||||||
/// PLL SYS.
|
|
||||||
PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
||||||
/// ROSC.
|
|
||||||
Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _,
|
Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _,
|
||||||
/// XOSC.
|
|
||||||
Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _,
|
Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _,
|
||||||
// Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
// Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
||||||
// Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
// Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB clock config.
|
|
||||||
pub struct UsbClkConfig {
|
pub struct UsbClkConfig {
|
||||||
/// USB clock source.
|
|
||||||
pub src: UsbClkSrc,
|
pub src: UsbClkSrc,
|
||||||
/// USB clock divider.
|
|
||||||
pub div: u8,
|
pub div: u8,
|
||||||
/// USB clock phase.
|
|
||||||
pub phase: u8,
|
pub phase: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ADC clock source.
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum AdcClkSrc {
|
pub enum AdcClkSrc {
|
||||||
/// PLL USB.
|
|
||||||
PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
||||||
/// PLL SYS.
|
|
||||||
PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
||||||
/// ROSC.
|
|
||||||
Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
|
Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
|
||||||
/// XOSC.
|
|
||||||
Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _,
|
Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _,
|
||||||
// Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
// Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
||||||
// Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
// Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ADC clock config.
|
|
||||||
pub struct AdcClkConfig {
|
pub struct AdcClkConfig {
|
||||||
/// ADC clock source.
|
|
||||||
pub src: AdcClkSrc,
|
pub src: AdcClkSrc,
|
||||||
/// ADC clock divider.
|
|
||||||
pub div: u8,
|
pub div: u8,
|
||||||
/// ADC clock phase.
|
|
||||||
pub phase: u8,
|
pub phase: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RTC clock source.
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum RtcClkSrc {
|
pub enum RtcClkSrc {
|
||||||
/// PLL USB.
|
|
||||||
PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
||||||
/// PLL SYS.
|
|
||||||
PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
||||||
/// ROSC.
|
|
||||||
Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
|
Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
|
||||||
/// XOSC.
|
|
||||||
Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _,
|
Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _,
|
||||||
// Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
// Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
||||||
// Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
// Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RTC clock config.
|
|
||||||
pub struct RtcClkConfig {
|
pub struct RtcClkConfig {
|
||||||
/// RTC clock source.
|
|
||||||
pub src: RtcClkSrc,
|
pub src: RtcClkSrc,
|
||||||
/// RTC clock divider.
|
|
||||||
pub div_int: u32,
|
pub div_int: u32,
|
||||||
/// RTC clock divider fraction.
|
|
||||||
pub div_frac: u8,
|
pub div_frac: u8,
|
||||||
/// RTC clock phase.
|
|
||||||
pub phase: u8,
|
pub phase: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,12 +605,10 @@ fn configure_rosc(config: RoscConfig) -> u32 {
|
|||||||
config.hz
|
config.hz
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ROSC clock frequency.
|
|
||||||
pub fn rosc_freq() -> u32 {
|
pub fn rosc_freq() -> u32 {
|
||||||
CLOCKS.rosc.load(Ordering::Relaxed)
|
CLOCKS.rosc.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// XOSC clock frequency.
|
|
||||||
pub fn xosc_freq() -> u32 {
|
pub fn xosc_freq() -> u32 {
|
||||||
CLOCKS.xosc.load(Ordering::Relaxed)
|
CLOCKS.xosc.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
@ -674,42 +620,34 @@ pub fn xosc_freq() -> u32 {
|
|||||||
// CLOCKS.gpin1.load(Ordering::Relaxed)
|
// CLOCKS.gpin1.load(Ordering::Relaxed)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/// PLL SYS clock frequency.
|
|
||||||
pub fn pll_sys_freq() -> u32 {
|
pub fn pll_sys_freq() -> u32 {
|
||||||
CLOCKS.pll_sys.load(Ordering::Relaxed)
|
CLOCKS.pll_sys.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PLL USB clock frequency.
|
|
||||||
pub fn pll_usb_freq() -> u32 {
|
pub fn pll_usb_freq() -> u32 {
|
||||||
CLOCKS.pll_usb.load(Ordering::Relaxed)
|
CLOCKS.pll_usb.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SYS clock frequency.
|
|
||||||
pub fn clk_sys_freq() -> u32 {
|
pub fn clk_sys_freq() -> u32 {
|
||||||
CLOCKS.sys.load(Ordering::Relaxed)
|
CLOCKS.sys.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// REF clock frequency.
|
|
||||||
pub fn clk_ref_freq() -> u32 {
|
pub fn clk_ref_freq() -> u32 {
|
||||||
CLOCKS.reference.load(Ordering::Relaxed)
|
CLOCKS.reference.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peripheral clock frequency.
|
|
||||||
pub fn clk_peri_freq() -> u32 {
|
pub fn clk_peri_freq() -> u32 {
|
||||||
CLOCKS.peri.load(Ordering::Relaxed)
|
CLOCKS.peri.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB clock frequency.
|
|
||||||
pub fn clk_usb_freq() -> u32 {
|
pub fn clk_usb_freq() -> u32 {
|
||||||
CLOCKS.usb.load(Ordering::Relaxed)
|
CLOCKS.usb.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ADC clock frequency.
|
|
||||||
pub fn clk_adc_freq() -> u32 {
|
pub fn clk_adc_freq() -> u32 {
|
||||||
CLOCKS.adc.load(Ordering::Relaxed)
|
CLOCKS.adc.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RTC clock frequency.
|
|
||||||
pub fn clk_rtc_freq() -> u16 {
|
pub fn clk_rtc_freq() -> u16 {
|
||||||
CLOCKS.rtc.load(Ordering::Relaxed)
|
CLOCKS.rtc.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
@ -770,9 +708,7 @@ fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 {
|
|||||||
vco_freq / ((config.post_div1 * config.post_div2) as u32)
|
vco_freq / ((config.post_div1 * config.post_div2) as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// General purpose input clock pin.
|
|
||||||
pub trait GpinPin: crate::gpio::Pin {
|
pub trait GpinPin: crate::gpio::Pin {
|
||||||
/// Pin number.
|
|
||||||
const NR: usize;
|
const NR: usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,14 +723,12 @@ macro_rules! impl_gpinpin {
|
|||||||
impl_gpinpin!(PIN_20, 20, 0);
|
impl_gpinpin!(PIN_20, 20, 0);
|
||||||
impl_gpinpin!(PIN_22, 22, 1);
|
impl_gpinpin!(PIN_22, 22, 1);
|
||||||
|
|
||||||
/// General purpose clock input driver.
|
|
||||||
pub struct Gpin<'d, T: Pin> {
|
pub struct Gpin<'d, T: Pin> {
|
||||||
gpin: PeripheralRef<'d, AnyPin>,
|
gpin: PeripheralRef<'d, AnyPin>,
|
||||||
_phantom: PhantomData<T>,
|
_phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> Gpin<'d, T> {
|
impl<'d, T: Pin> Gpin<'d, T> {
|
||||||
/// Create new gpin driver.
|
|
||||||
pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> {
|
pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> {
|
||||||
into_ref!(gpin);
|
into_ref!(gpin);
|
||||||
|
|
||||||
@ -820,9 +754,7 @@ impl<'d, T: Pin> Drop for Gpin<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// General purpose clock output pin.
|
|
||||||
pub trait GpoutPin: crate::gpio::Pin {
|
pub trait GpoutPin: crate::gpio::Pin {
|
||||||
/// Pin number.
|
|
||||||
fn number(&self) -> usize;
|
fn number(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -841,38 +773,26 @@ impl_gpoutpin!(PIN_23, 1);
|
|||||||
impl_gpoutpin!(PIN_24, 2);
|
impl_gpoutpin!(PIN_24, 2);
|
||||||
impl_gpoutpin!(PIN_25, 3);
|
impl_gpoutpin!(PIN_25, 3);
|
||||||
|
|
||||||
/// Gpout clock source.
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum GpoutSrc {
|
pub enum GpoutSrc {
|
||||||
/// Sys PLL.
|
|
||||||
PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _,
|
||||||
// Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
// Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
|
||||||
// Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
// Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
||||||
/// USB PLL.
|
|
||||||
PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
||||||
/// ROSC.
|
|
||||||
Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _,
|
Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _,
|
||||||
/// XOSC.
|
|
||||||
Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _,
|
Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _,
|
||||||
/// SYS.
|
|
||||||
Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _,
|
Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _,
|
||||||
/// USB.
|
|
||||||
Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _,
|
Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _,
|
||||||
/// ADC.
|
|
||||||
Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _,
|
Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _,
|
||||||
/// RTC.
|
|
||||||
Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _,
|
Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _,
|
||||||
/// REF.
|
|
||||||
Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _,
|
Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// General purpose clock output driver.
|
|
||||||
pub struct Gpout<'d, T: GpoutPin> {
|
pub struct Gpout<'d, T: GpoutPin> {
|
||||||
gpout: PeripheralRef<'d, T>,
|
gpout: PeripheralRef<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: GpoutPin> Gpout<'d, T> {
|
impl<'d, T: GpoutPin> Gpout<'d, T> {
|
||||||
/// Create new general purpose cloud output.
|
|
||||||
pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self {
|
pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self {
|
||||||
into_ref!(gpout);
|
into_ref!(gpout);
|
||||||
|
|
||||||
@ -881,7 +801,6 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
|
|||||||
Self { gpout }
|
Self { gpout }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set clock divider.
|
|
||||||
pub fn set_div(&self, int: u32, frac: u8) {
|
pub fn set_div(&self, int: u32, frac: u8) {
|
||||||
let c = pac::CLOCKS;
|
let c = pac::CLOCKS;
|
||||||
c.clk_gpout_div(self.gpout.number()).write(|w| {
|
c.clk_gpout_div(self.gpout.number()).write(|w| {
|
||||||
@ -890,7 +809,6 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set clock source.
|
|
||||||
pub fn set_src(&self, src: GpoutSrc) {
|
pub fn set_src(&self, src: GpoutSrc) {
|
||||||
let c = pac::CLOCKS;
|
let c = pac::CLOCKS;
|
||||||
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
|
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
|
||||||
@ -898,7 +816,6 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable clock.
|
|
||||||
pub fn enable(&self) {
|
pub fn enable(&self) {
|
||||||
let c = pac::CLOCKS;
|
let c = pac::CLOCKS;
|
||||||
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
|
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
|
||||||
@ -906,7 +823,6 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable clock.
|
|
||||||
pub fn disable(&self) {
|
pub fn disable(&self) {
|
||||||
let c = pac::CLOCKS;
|
let c = pac::CLOCKS;
|
||||||
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
|
c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
|
||||||
@ -914,7 +830,6 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clock frequency.
|
|
||||||
pub fn get_freq(&self) -> u32 {
|
pub fn get_freq(&self) -> u32 {
|
||||||
let c = pac::CLOCKS;
|
let c = pac::CLOCKS;
|
||||||
let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc();
|
let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc();
|
||||||
|
@ -38,9 +38,6 @@ pub(crate) unsafe fn init() {
|
|||||||
interrupt::DMA_IRQ_0.enable();
|
interrupt::DMA_IRQ_0.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMA read.
|
|
||||||
///
|
|
||||||
/// SAFETY: Slice must point to a valid location reachable by DMA.
|
|
||||||
pub unsafe fn read<'a, C: Channel, W: Word>(
|
pub unsafe fn read<'a, C: Channel, W: Word>(
|
||||||
ch: impl Peripheral<P = C> + 'a,
|
ch: impl Peripheral<P = C> + 'a,
|
||||||
from: *const W,
|
from: *const W,
|
||||||
@ -60,9 +57,6 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMA write.
|
|
||||||
///
|
|
||||||
/// SAFETY: Slice must point to a valid location reachable by DMA.
|
|
||||||
pub unsafe fn write<'a, C: Channel, W: Word>(
|
pub unsafe fn write<'a, C: Channel, W: Word>(
|
||||||
ch: impl Peripheral<P = C> + 'a,
|
ch: impl Peripheral<P = C> + 'a,
|
||||||
from: *const [W],
|
from: *const [W],
|
||||||
@ -85,9 +79,6 @@ pub unsafe fn write<'a, C: Channel, W: Word>(
|
|||||||
// static mut so that this is allocated in RAM.
|
// static mut so that this is allocated in RAM.
|
||||||
static mut DUMMY: u32 = 0;
|
static mut DUMMY: u32 = 0;
|
||||||
|
|
||||||
/// DMA repeated write.
|
|
||||||
///
|
|
||||||
/// SAFETY: Slice must point to a valid location reachable by DMA.
|
|
||||||
pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
|
pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
|
||||||
ch: impl Peripheral<P = C> + 'a,
|
ch: impl Peripheral<P = C> + 'a,
|
||||||
to: *mut W,
|
to: *mut W,
|
||||||
@ -106,9 +97,6 @@ pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMA copy between slices.
|
|
||||||
///
|
|
||||||
/// SAFETY: Slices must point to locations reachable by DMA.
|
|
||||||
pub unsafe fn copy<'a, C: Channel, W: Word>(
|
pub unsafe fn copy<'a, C: Channel, W: Word>(
|
||||||
ch: impl Peripheral<P = C> + 'a,
|
ch: impl Peripheral<P = C> + 'a,
|
||||||
from: &[W],
|
from: &[W],
|
||||||
@ -164,7 +152,6 @@ fn copy_inner<'a, C: Channel>(
|
|||||||
Transfer::new(ch)
|
Transfer::new(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMA transfer driver.
|
|
||||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||||
pub struct Transfer<'a, C: Channel> {
|
pub struct Transfer<'a, C: Channel> {
|
||||||
channel: PeripheralRef<'a, C>,
|
channel: PeripheralRef<'a, C>,
|
||||||
@ -214,25 +201,19 @@ mod sealed {
|
|||||||
pub trait Word {}
|
pub trait Word {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMA channel interface.
|
|
||||||
pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static {
|
pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static {
|
||||||
/// Channel number.
|
|
||||||
fn number(&self) -> u8;
|
fn number(&self) -> u8;
|
||||||
|
|
||||||
/// Channel registry block.
|
|
||||||
fn regs(&self) -> pac::dma::Channel {
|
fn regs(&self) -> pac::dma::Channel {
|
||||||
pac::DMA.ch(self.number() as _)
|
pac::DMA.ch(self.number() as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert into type-erased [AnyChannel].
|
|
||||||
fn degrade(self) -> AnyChannel {
|
fn degrade(self) -> AnyChannel {
|
||||||
AnyChannel { number: self.number() }
|
AnyChannel { number: self.number() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMA word.
|
|
||||||
pub trait Word: sealed::Word {
|
pub trait Word: sealed::Word {
|
||||||
/// Word size.
|
|
||||||
fn size() -> vals::DataSize;
|
fn size() -> vals::DataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +238,6 @@ impl Word for u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type erased DMA channel.
|
|
||||||
pub struct AnyChannel {
|
pub struct AnyChannel {
|
||||||
number: u8,
|
number: u8,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! Flash driver.
|
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
@ -14,10 +13,9 @@ use crate::dma::{AnyChannel, Channel, Transfer};
|
|||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::peripherals::FLASH;
|
use crate::peripherals::FLASH;
|
||||||
|
|
||||||
/// Flash base address.
|
|
||||||
pub const FLASH_BASE: *const u32 = 0x10000000 as _;
|
pub const FLASH_BASE: *const u32 = 0x10000000 as _;
|
||||||
|
|
||||||
/// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead.
|
// 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.
|
// 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");
|
pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram");
|
||||||
|
|
||||||
@ -26,15 +24,10 @@ pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram");
|
|||||||
// These limitations are currently enforced because of using the
|
// These limitations are currently enforced because of using the
|
||||||
// RP2040 boot-rom flash functions, that are optimized for flash compatibility
|
// RP2040 boot-rom flash functions, that are optimized for flash compatibility
|
||||||
// rather than performance.
|
// rather than performance.
|
||||||
/// Flash page size.
|
|
||||||
pub const PAGE_SIZE: usize = 256;
|
pub const PAGE_SIZE: usize = 256;
|
||||||
/// Flash write size.
|
|
||||||
pub const WRITE_SIZE: usize = 1;
|
pub const WRITE_SIZE: usize = 1;
|
||||||
/// Flash read size.
|
|
||||||
pub const READ_SIZE: usize = 1;
|
pub const READ_SIZE: usize = 1;
|
||||||
/// Flash erase size.
|
|
||||||
pub const ERASE_SIZE: usize = 4096;
|
pub const ERASE_SIZE: usize = 4096;
|
||||||
/// Flash DMA read size.
|
|
||||||
pub const ASYNC_READ_SIZE: usize = 4;
|
pub const ASYNC_READ_SIZE: usize = 4;
|
||||||
|
|
||||||
/// Error type for NVMC operations.
|
/// Error type for NVMC operations.
|
||||||
@ -45,9 +38,7 @@ pub enum Error {
|
|||||||
OutOfBounds,
|
OutOfBounds,
|
||||||
/// Unaligned operation or using unaligned buffers.
|
/// Unaligned operation or using unaligned buffers.
|
||||||
Unaligned,
|
Unaligned,
|
||||||
/// Accessed from the wrong core.
|
|
||||||
InvalidCore,
|
InvalidCore,
|
||||||
/// Other error
|
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,18 +96,12 @@ impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Drop for BackgroundRead<'a, '
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flash driver.
|
|
||||||
pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> {
|
pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> {
|
||||||
dma: Option<PeripheralRef<'d, AnyChannel>>,
|
dma: Option<PeripheralRef<'d, AnyChannel>>,
|
||||||
phantom: PhantomData<(&'d mut T, M)>,
|
phantom: PhantomData<(&'d mut T, M)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> {
|
impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> {
|
||||||
/// Blocking read.
|
|
||||||
///
|
|
||||||
/// The offset and buffer must be aligned.
|
|
||||||
///
|
|
||||||
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
|
|
||||||
pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
|
pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
|
||||||
trace!(
|
trace!(
|
||||||
"Reading from 0x{:x} to 0x{:x}",
|
"Reading from 0x{:x} to 0x{:x}",
|
||||||
@ -131,14 +116,10 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flash capacity.
|
|
||||||
pub fn capacity(&self) -> usize {
|
pub fn capacity(&self) -> usize {
|
||||||
FLASH_SIZE
|
FLASH_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking erase.
|
|
||||||
///
|
|
||||||
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
|
|
||||||
pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
|
pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
|
||||||
check_erase(self, from, to)?;
|
check_erase(self, from, to)?;
|
||||||
|
|
||||||
@ -155,11 +136,6 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking write.
|
|
||||||
///
|
|
||||||
/// The offset and buffer must be aligned.
|
|
||||||
///
|
|
||||||
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
|
|
||||||
pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
|
pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
|
||||||
check_write(self, offset, bytes.len())?;
|
check_write(self, offset, bytes.len())?;
|
||||||
|
|
||||||
@ -243,7 +219,6 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> {
|
impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> {
|
||||||
/// Create a new flash driver in blocking mode.
|
|
||||||
pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self {
|
pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self {
|
||||||
Self {
|
Self {
|
||||||
dma: None,
|
dma: None,
|
||||||
@ -253,7 +228,6 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
|
impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
|
||||||
/// Create a new flash driver in async mode.
|
|
||||||
pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self {
|
pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self {
|
||||||
into_ref!(dma);
|
into_ref!(dma);
|
||||||
Self {
|
Self {
|
||||||
@ -262,11 +236,6 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start a background read operation.
|
|
||||||
///
|
|
||||||
/// The offset and buffer must be aligned.
|
|
||||||
///
|
|
||||||
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
|
|
||||||
pub fn background_read<'a>(
|
pub fn background_read<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
offset: u32,
|
offset: u32,
|
||||||
@ -310,11 +279,6 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Async read.
|
|
||||||
///
|
|
||||||
/// The offset and buffer must be aligned.
|
|
||||||
///
|
|
||||||
/// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
|
|
||||||
pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
|
pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
@ -910,9 +874,7 @@ mod sealed {
|
|||||||
pub trait Mode {}
|
pub trait Mode {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flash instance.
|
|
||||||
pub trait Instance: sealed::Instance {}
|
pub trait Instance: sealed::Instance {}
|
||||||
/// Flash mode.
|
|
||||||
pub trait Mode: sealed::Mode {}
|
pub trait Mode: sealed::Mode {}
|
||||||
|
|
||||||
impl sealed::Instance for FLASH {}
|
impl sealed::Instance for FLASH {}
|
||||||
@ -925,9 +887,7 @@ macro_rules! impl_mode {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flash blocking mode.
|
|
||||||
pub struct Blocking;
|
pub struct Blocking;
|
||||||
/// Flash async mode.
|
|
||||||
pub struct Async;
|
pub struct Async;
|
||||||
|
|
||||||
impl_mode!(Blocking);
|
impl_mode!(Blocking);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! GPIO driver.
|
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
@ -24,9 +23,7 @@ static QSPI_WAKERS: [AtomicWaker; QSPI_PIN_COUNT] = [NEW_AW; QSPI_PIN_COUNT];
|
|||||||
/// Represents a digital input or output level.
|
/// Represents a digital input or output level.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
pub enum Level {
|
pub enum Level {
|
||||||
/// Logical low.
|
|
||||||
Low,
|
Low,
|
||||||
/// Logical high.
|
|
||||||
High,
|
High,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,66 +48,48 @@ impl From<Level> for bool {
|
|||||||
/// Represents a pull setting for an input.
|
/// Represents a pull setting for an input.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
pub enum Pull {
|
pub enum Pull {
|
||||||
/// No pull.
|
|
||||||
None,
|
None,
|
||||||
/// Internal pull-up resistor.
|
|
||||||
Up,
|
Up,
|
||||||
/// Internal pull-down resistor.
|
|
||||||
Down,
|
Down,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drive strength of an output
|
/// Drive strength of an output
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub enum Drive {
|
pub enum Drive {
|
||||||
/// 2 mA drive.
|
|
||||||
_2mA,
|
_2mA,
|
||||||
/// 4 mA drive.
|
|
||||||
_4mA,
|
_4mA,
|
||||||
/// 8 mA drive.
|
|
||||||
_8mA,
|
_8mA,
|
||||||
/// 1 2mA drive.
|
|
||||||
_12mA,
|
_12mA,
|
||||||
}
|
}
|
||||||
/// Slew rate of an output
|
/// Slew rate of an output
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub enum SlewRate {
|
pub enum SlewRate {
|
||||||
/// Fast slew rate.
|
|
||||||
Fast,
|
Fast,
|
||||||
/// Slow slew rate.
|
|
||||||
Slow,
|
Slow,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A GPIO bank with up to 32 pins.
|
/// A GPIO bank with up to 32 pins.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub enum Bank {
|
pub enum Bank {
|
||||||
/// Bank 0.
|
|
||||||
Bank0 = 0,
|
Bank0 = 0,
|
||||||
/// QSPI.
|
|
||||||
#[cfg(feature = "qspi-as-gpio")]
|
#[cfg(feature = "qspi-as-gpio")]
|
||||||
Qspi = 1,
|
Qspi = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dormant mode config.
|
|
||||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
|
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DormantWakeConfig {
|
pub struct DormantWakeConfig {
|
||||||
/// Wake on edge high.
|
|
||||||
pub edge_high: bool,
|
pub edge_high: bool,
|
||||||
/// Wake on edge low.
|
|
||||||
pub edge_low: bool,
|
pub edge_low: bool,
|
||||||
/// Wake on level high.
|
|
||||||
pub level_high: bool,
|
pub level_high: bool,
|
||||||
/// Wake on level low.
|
|
||||||
pub level_low: bool,
|
pub level_low: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GPIO input driver.
|
|
||||||
pub struct Input<'d, T: Pin> {
|
pub struct Input<'d, T: Pin> {
|
||||||
pin: Flex<'d, T>,
|
pin: Flex<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> Input<'d, T> {
|
impl<'d, T: Pin> Input<'d, T> {
|
||||||
/// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
|
pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
|
||||||
let mut pin = Flex::new(pin);
|
let mut pin = Flex::new(pin);
|
||||||
@ -125,13 +104,11 @@ impl<'d, T: Pin> Input<'d, T> {
|
|||||||
self.pin.set_schmitt(enable)
|
self.pin.set_schmitt(enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get whether the pin input level is high.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_high(&mut self) -> bool {
|
pub fn is_high(&mut self) -> bool {
|
||||||
self.pin.is_high()
|
self.pin.is_high()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get whether the pin input level is low.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_low(&mut self) -> bool {
|
pub fn is_low(&mut self) -> bool {
|
||||||
self.pin.is_low()
|
self.pin.is_low()
|
||||||
@ -143,37 +120,31 @@ impl<'d, T: Pin> Input<'d, T> {
|
|||||||
self.pin.get_level()
|
self.pin.get_level()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until the pin is high. If it is already high, return immediately.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_high(&mut self) {
|
pub async fn wait_for_high(&mut self) {
|
||||||
self.pin.wait_for_high().await;
|
self.pin.wait_for_high().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until the pin is low. If it is already low, return immediately.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_low(&mut self) {
|
pub async fn wait_for_low(&mut self) {
|
||||||
self.pin.wait_for_low().await;
|
self.pin.wait_for_low().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo a transition from low to high.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_rising_edge(&mut self) {
|
pub async fn wait_for_rising_edge(&mut self) {
|
||||||
self.pin.wait_for_rising_edge().await;
|
self.pin.wait_for_rising_edge().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo a transition from high to low.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_falling_edge(&mut self) {
|
pub async fn wait_for_falling_edge(&mut self) {
|
||||||
self.pin.wait_for_falling_edge().await;
|
self.pin.wait_for_falling_edge().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo any transition, i.e low to high OR high to low.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_any_edge(&mut self) {
|
pub async fn wait_for_any_edge(&mut self) {
|
||||||
self.pin.wait_for_any_edge().await;
|
self.pin.wait_for_any_edge().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure dormant wake.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
|
pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
|
||||||
self.pin.dormant_wake(cfg)
|
self.pin.dormant_wake(cfg)
|
||||||
@ -184,15 +155,10 @@ impl<'d, T: Pin> Input<'d, T> {
|
|||||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum InterruptTrigger {
|
pub enum InterruptTrigger {
|
||||||
/// Trigger on pin low.
|
|
||||||
LevelLow,
|
LevelLow,
|
||||||
/// Trigger on pin high.
|
|
||||||
LevelHigh,
|
LevelHigh,
|
||||||
/// Trigger on high to low transition.
|
|
||||||
EdgeLow,
|
EdgeLow,
|
||||||
/// Trigger on low to high transition.
|
|
||||||
EdgeHigh,
|
EdgeHigh,
|
||||||
/// Trigger on any transition.
|
|
||||||
AnyEdge,
|
AnyEdge,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +226,6 @@ struct InputFuture<'a, T: Pin> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> InputFuture<'d, T> {
|
impl<'d, T: Pin> InputFuture<'d, T> {
|
||||||
/// Create a new future wiating for input trigger.
|
|
||||||
pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self {
|
pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self {
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
let pin_group = (pin.pin() % 8) as usize;
|
let pin_group = (pin.pin() % 8) as usize;
|
||||||
@ -343,13 +308,11 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GPIO output driver.
|
|
||||||
pub struct Output<'d, T: Pin> {
|
pub struct Output<'d, T: Pin> {
|
||||||
pin: Flex<'d, T>,
|
pin: Flex<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> Output<'d, T> {
|
impl<'d, T: Pin> Output<'d, T> {
|
||||||
/// Create GPIO output driver for a [Pin] with the provided [Level].
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
|
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
|
||||||
let mut pin = Flex::new(pin);
|
let mut pin = Flex::new(pin);
|
||||||
@ -368,7 +331,7 @@ impl<'d, T: Pin> Output<'d, T> {
|
|||||||
self.pin.set_drive_strength(strength)
|
self.pin.set_drive_strength(strength)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the pin's slew rate.
|
// Set the pin's slew rate.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
|
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
|
||||||
self.pin.set_slew_rate(slew_rate)
|
self.pin.set_slew_rate(slew_rate)
|
||||||
@ -423,7 +386,6 @@ pub struct OutputOpenDrain<'d, T: Pin> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> OutputOpenDrain<'d, T> {
|
impl<'d, T: Pin> OutputOpenDrain<'d, T> {
|
||||||
/// Create GPIO output driver for a [Pin] in open drain mode with the provided [Level].
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
|
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
|
||||||
let mut pin = Flex::new(pin);
|
let mut pin = Flex::new(pin);
|
||||||
@ -441,7 +403,7 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
|
|||||||
self.pin.set_drive_strength(strength)
|
self.pin.set_drive_strength(strength)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the pin's slew rate.
|
// Set the pin's slew rate.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
|
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
|
||||||
self.pin.set_slew_rate(slew_rate)
|
self.pin.set_slew_rate(slew_rate)
|
||||||
@ -494,13 +456,11 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
|
|||||||
self.pin.toggle_set_as_output()
|
self.pin.toggle_set_as_output()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get whether the pin input level is high.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_high(&mut self) -> bool {
|
pub fn is_high(&mut self) -> bool {
|
||||||
self.pin.is_high()
|
self.pin.is_high()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get whether the pin input level is low.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_low(&mut self) -> bool {
|
pub fn is_low(&mut self) -> bool {
|
||||||
self.pin.is_low()
|
self.pin.is_low()
|
||||||
@ -512,31 +472,26 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
|
|||||||
self.is_high().into()
|
self.is_high().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until the pin is high. If it is already high, return immediately.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_high(&mut self) {
|
pub async fn wait_for_high(&mut self) {
|
||||||
self.pin.wait_for_high().await;
|
self.pin.wait_for_high().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until the pin is low. If it is already low, return immediately.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_low(&mut self) {
|
pub async fn wait_for_low(&mut self) {
|
||||||
self.pin.wait_for_low().await;
|
self.pin.wait_for_low().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo a transition from low to high.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_rising_edge(&mut self) {
|
pub async fn wait_for_rising_edge(&mut self) {
|
||||||
self.pin.wait_for_rising_edge().await;
|
self.pin.wait_for_rising_edge().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo a transition from high to low.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_falling_edge(&mut self) {
|
pub async fn wait_for_falling_edge(&mut self) {
|
||||||
self.pin.wait_for_falling_edge().await;
|
self.pin.wait_for_falling_edge().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo any transition, i.e low to high OR high to low.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_any_edge(&mut self) {
|
pub async fn wait_for_any_edge(&mut self) {
|
||||||
self.pin.wait_for_any_edge().await;
|
self.pin.wait_for_any_edge().await;
|
||||||
@ -553,10 +508,6 @@ pub struct Flex<'d, T: Pin> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> Flex<'d, T> {
|
impl<'d, T: Pin> Flex<'d, T> {
|
||||||
/// Wrap the pin in a `Flex`.
|
|
||||||
///
|
|
||||||
/// The pin remains disconnected. The initial output level is unspecified, but can be changed
|
|
||||||
/// before the pin is put into output mode.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self {
|
pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self {
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
@ -605,7 +556,7 @@ impl<'d, T: Pin> Flex<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the pin's slew rate.
|
// Set the pin's slew rate.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
|
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
|
||||||
self.pin.pad_ctrl().modify(|w| {
|
self.pin.pad_ctrl().modify(|w| {
|
||||||
@ -638,7 +589,6 @@ impl<'d, T: Pin> Flex<'d, T> {
|
|||||||
self.pin.sio_oe().value_set().write_value(self.bit())
|
self.pin.sio_oe().value_set().write_value(self.bit())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set as output pin.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_set_as_output(&mut self) -> bool {
|
pub fn is_set_as_output(&mut self) -> bool {
|
||||||
self.ref_is_set_as_output()
|
self.ref_is_set_as_output()
|
||||||
@ -649,18 +599,15 @@ impl<'d, T: Pin> Flex<'d, T> {
|
|||||||
(self.pin.sio_oe().value().read() & self.bit()) != 0
|
(self.pin.sio_oe().value().read() & self.bit()) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toggle output pin.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn toggle_set_as_output(&mut self) {
|
pub fn toggle_set_as_output(&mut self) {
|
||||||
self.pin.sio_oe().value_xor().write_value(self.bit())
|
self.pin.sio_oe().value_xor().write_value(self.bit())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get whether the pin input level is high.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_high(&mut self) -> bool {
|
pub fn is_high(&mut self) -> bool {
|
||||||
!self.is_low()
|
!self.is_low()
|
||||||
}
|
}
|
||||||
/// Get whether the pin input level is low.
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_low(&mut self) -> bool {
|
pub fn is_low(&mut self) -> bool {
|
||||||
@ -728,37 +675,31 @@ impl<'d, T: Pin> Flex<'d, T> {
|
|||||||
self.pin.sio_out().value_xor().write_value(self.bit())
|
self.pin.sio_out().value_xor().write_value(self.bit())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until the pin is high. If it is already high, return immediately.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_high(&mut self) {
|
pub async fn wait_for_high(&mut self) {
|
||||||
InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await;
|
InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait until the pin is low. If it is already low, return immediately.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_low(&mut self) {
|
pub async fn wait_for_low(&mut self) {
|
||||||
InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await;
|
InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo a transition from low to high.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_rising_edge(&mut self) {
|
pub async fn wait_for_rising_edge(&mut self) {
|
||||||
InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await;
|
InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo a transition from high to low.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_falling_edge(&mut self) {
|
pub async fn wait_for_falling_edge(&mut self) {
|
||||||
InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await;
|
InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for the pin to undergo any transition, i.e low to high OR high to low.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn wait_for_any_edge(&mut self) {
|
pub async fn wait_for_any_edge(&mut self) {
|
||||||
InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await;
|
InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure dormant wake.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
|
pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
|
||||||
let idx = self.pin._pin() as usize;
|
let idx = self.pin._pin() as usize;
|
||||||
@ -796,7 +737,6 @@ impl<'d, T: Pin> Drop for Flex<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dormant wake driver.
|
|
||||||
pub struct DormantWake<'w, T: Pin> {
|
pub struct DormantWake<'w, T: Pin> {
|
||||||
pin: PeripheralRef<'w, T>,
|
pin: PeripheralRef<'w, T>,
|
||||||
cfg: DormantWakeConfig,
|
cfg: DormantWakeConfig,
|
||||||
@ -878,7 +818,6 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
|
|
||||||
pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
|
pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
|
||||||
/// Degrade to a generic pin struct
|
/// Degrade to a generic pin struct
|
||||||
fn degrade(self) -> AnyPin {
|
fn degrade(self) -> AnyPin {
|
||||||
@ -900,7 +839,6 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type-erased GPIO pin
|
|
||||||
pub struct AnyPin {
|
pub struct AnyPin {
|
||||||
pin_bank: u8,
|
pin_bank: u8,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! I2C driver.
|
|
||||||
use core::future;
|
use core::future;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
@ -23,7 +22,6 @@ pub enum AbortReason {
|
|||||||
ArbitrationLoss,
|
ArbitrationLoss,
|
||||||
/// Transmit ended with data still in fifo
|
/// Transmit ended with data still in fifo
|
||||||
TxNotEmpty(u16),
|
TxNotEmpty(u16),
|
||||||
/// Other reason.
|
|
||||||
Other(u32),
|
Other(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,11 +41,9 @@ pub enum Error {
|
|||||||
AddressReserved(u16),
|
AddressReserved(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// I2C config.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Frequency.
|
|
||||||
pub frequency: u32,
|
pub frequency: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,16 +53,13 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Size of I2C FIFO.
|
|
||||||
pub const FIFO_SIZE: u8 = 16;
|
pub const FIFO_SIZE: u8 = 16;
|
||||||
|
|
||||||
/// I2C driver.
|
|
||||||
pub struct I2c<'d, T: Instance, M: Mode> {
|
pub struct I2c<'d, T: Instance, M: Mode> {
|
||||||
phantom: PhantomData<(&'d mut T, M)>,
|
phantom: PhantomData<(&'d mut T, M)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> I2c<'d, T, Blocking> {
|
impl<'d, T: Instance> I2c<'d, T, Blocking> {
|
||||||
/// Create a new driver instance in blocking mode.
|
|
||||||
pub fn new_blocking(
|
pub fn new_blocking(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||||
@ -79,7 +72,6 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> I2c<'d, T, Async> {
|
impl<'d, T: Instance> I2c<'d, T, Async> {
|
||||||
/// Create a new driver instance in async mode.
|
|
||||||
pub fn new_async(
|
pub fn new_async(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||||
@ -300,19 +292,16 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read from address into buffer using DMA.
|
|
||||||
pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> {
|
pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
Self::setup(addr)?;
|
Self::setup(addr)?;
|
||||||
self.read_async_internal(buffer, true, true).await
|
self.read_async_internal(buffer, true, true).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write to address from buffer using DMA.
|
|
||||||
pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> {
|
pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> {
|
||||||
Self::setup(addr)?;
|
Self::setup(addr)?;
|
||||||
self.write_async_internal(bytes, true).await
|
self.write_async_internal(bytes, true).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write to address from bytes and read from address into buffer using DMA.
|
|
||||||
pub async fn write_read_async(
|
pub async fn write_read_async(
|
||||||
&mut self,
|
&mut self,
|
||||||
addr: u16,
|
addr: u16,
|
||||||
@ -325,7 +314,6 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interrupt handler.
|
|
||||||
pub struct InterruptHandler<T: Instance> {
|
pub struct InterruptHandler<T: Instance> {
|
||||||
_uart: PhantomData<T>,
|
_uart: PhantomData<T>,
|
||||||
}
|
}
|
||||||
@ -581,20 +569,17 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
|
|||||||
// Blocking public API
|
// Blocking public API
|
||||||
// =========================
|
// =========================
|
||||||
|
|
||||||
/// Read from address into buffer blocking caller until done.
|
|
||||||
pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
|
pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
|
||||||
Self::setup(address.into())?;
|
Self::setup(address.into())?;
|
||||||
self.read_blocking_internal(read, true, true)
|
self.read_blocking_internal(read, true, true)
|
||||||
// Automatic Stop
|
// Automatic Stop
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write to address from buffer blocking caller until done.
|
|
||||||
pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
|
pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
|
||||||
Self::setup(address.into())?;
|
Self::setup(address.into())?;
|
||||||
self.write_blocking_internal(write, true)
|
self.write_blocking_internal(write, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write to address from bytes and read from address into buffer blocking caller until done.
|
|
||||||
pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
|
pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
|
||||||
Self::setup(address.into())?;
|
Self::setup(address.into())?;
|
||||||
self.write_blocking_internal(write, false)?;
|
self.write_blocking_internal(write, false)?;
|
||||||
@ -757,7 +742,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if address is reserved.
|
|
||||||
pub fn i2c_reserved_addr(addr: u16) -> bool {
|
pub fn i2c_reserved_addr(addr: u16) -> bool {
|
||||||
((addr & 0x78) == 0 || (addr & 0x78) == 0x78) && addr != 0
|
((addr & 0x78) == 0 || (addr & 0x78) == 0x78) && addr != 0
|
||||||
}
|
}
|
||||||
@ -784,7 +768,6 @@ mod sealed {
|
|||||||
pub trait SclPin<T: Instance> {}
|
pub trait SclPin<T: Instance> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Driver mode.
|
|
||||||
pub trait Mode: sealed::Mode {}
|
pub trait Mode: sealed::Mode {}
|
||||||
|
|
||||||
macro_rules! impl_mode {
|
macro_rules! impl_mode {
|
||||||
@ -794,15 +777,12 @@ macro_rules! impl_mode {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking mode.
|
|
||||||
pub struct Blocking;
|
pub struct Blocking;
|
||||||
/// Async mode.
|
|
||||||
pub struct Async;
|
pub struct Async;
|
||||||
|
|
||||||
impl_mode!(Blocking);
|
impl_mode!(Blocking);
|
||||||
impl_mode!(Async);
|
impl_mode!(Async);
|
||||||
|
|
||||||
/// I2C instance.
|
|
||||||
pub trait Instance: sealed::Instance {}
|
pub trait Instance: sealed::Instance {}
|
||||||
|
|
||||||
macro_rules! impl_instance {
|
macro_rules! impl_instance {
|
||||||
@ -839,9 +819,7 @@ macro_rules! impl_instance {
|
|||||||
impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33);
|
impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33);
|
||||||
impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35);
|
impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35);
|
||||||
|
|
||||||
/// SDA pin.
|
|
||||||
pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {}
|
pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {}
|
||||||
/// SCL pin.
|
|
||||||
pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {}
|
pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {}
|
||||||
|
|
||||||
macro_rules! impl_pin {
|
macro_rules! impl_pin {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! I2C slave driver.
|
|
||||||
use core::future;
|
use core::future;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
@ -64,13 +63,11 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// I2CSlave driver.
|
|
||||||
pub struct I2cSlave<'d, T: Instance> {
|
pub struct I2cSlave<'d, T: Instance> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> I2cSlave<'d, T> {
|
impl<'d, T: Instance> I2cSlave<'d, T> {
|
||||||
/// Create a new instance.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
_peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
// This mod MUST go first, so that the others see its macros.
|
// This mod MUST go first, so that the others see its macros.
|
||||||
pub(crate) mod fmt;
|
pub(crate) mod fmt;
|
||||||
@ -247,6 +246,7 @@ select_bootloader! {
|
|||||||
/// # Usage
|
/// # Usage
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
|
/// #![feature(type_alias_impl_trait)]
|
||||||
/// use embassy_rp::install_core0_stack_guard;
|
/// use embassy_rp::install_core0_stack_guard;
|
||||||
/// use embassy_executor::{Executor, Spawner};
|
/// use embassy_executor::{Executor, Spawner};
|
||||||
///
|
///
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
//! # Usage
|
//! # Usage
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
|
//! # #![feature(type_alias_impl_trait)]
|
||||||
//! use embassy_rp::multicore::Stack;
|
//! use embassy_rp::multicore::Stack;
|
||||||
//! use static_cell::StaticCell;
|
//! use static_cell::StaticCell;
|
||||||
//! use embassy_executor::Executor;
|
//! use embassy_executor::Executor;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! PIO driver.
|
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::pin::Pin as FuturePin;
|
use core::pin::Pin as FuturePin;
|
||||||
|
@ -119,13 +119,11 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create PWM driver without any configured pins.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self {
|
pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self {
|
||||||
Self::new_inner(inner, None, None, config, Divmode::DIV)
|
Self::new_inner(inner, None, None, config, Divmode::DIV)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create PWM driver with a single 'a' as output.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_output_a(
|
pub fn new_output_a(
|
||||||
inner: impl Peripheral<P = T> + 'd,
|
inner: impl Peripheral<P = T> + 'd,
|
||||||
@ -136,7 +134,6 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV)
|
Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create PWM driver with a single 'b' pin as output.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_output_b(
|
pub fn new_output_b(
|
||||||
inner: impl Peripheral<P = T> + 'd,
|
inner: impl Peripheral<P = T> + 'd,
|
||||||
@ -147,7 +144,6 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV)
|
Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create PWM driver with a 'a' and 'b' pins as output.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_output_ab(
|
pub fn new_output_ab(
|
||||||
inner: impl Peripheral<P = T> + 'd,
|
inner: impl Peripheral<P = T> + 'd,
|
||||||
@ -159,7 +155,6 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, Divmode::DIV)
|
Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, Divmode::DIV)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create PWM driver with a single 'b' as input pin.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_input(
|
pub fn new_input(
|
||||||
inner: impl Peripheral<P = T> + 'd,
|
inner: impl Peripheral<P = T> + 'd,
|
||||||
@ -171,7 +166,6 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
Self::new_inner(inner, None, Some(b.map_into()), config, mode.into())
|
Self::new_inner(inner, None, Some(b.map_into()), config, mode.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create PWM driver with a 'a' and 'b' pins in the desired input mode.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_output_input(
|
pub fn new_output_input(
|
||||||
inner: impl Peripheral<P = T> + 'd,
|
inner: impl Peripheral<P = T> + 'd,
|
||||||
@ -184,7 +178,6 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, mode.into())
|
Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, mode.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the PWM config.
|
|
||||||
pub fn set_config(&mut self, config: &Config) {
|
pub fn set_config(&mut self, config: &Config) {
|
||||||
Self::configure(self.inner.regs(), config);
|
Self::configure(self.inner.regs(), config);
|
||||||
}
|
}
|
||||||
@ -228,33 +221,28 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
while p.csr().read().ph_ret() {}
|
while p.csr().read().ph_ret() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read PWM counter.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn counter(&self) -> u16 {
|
pub fn counter(&self) -> u16 {
|
||||||
self.inner.regs().ctr().read().ctr()
|
self.inner.regs().ctr().read().ctr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write PWM counter.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_counter(&self, ctr: u16) {
|
pub fn set_counter(&self, ctr: u16) {
|
||||||
self.inner.regs().ctr().write(|w| w.set_ctr(ctr))
|
self.inner.regs().ctr().write(|w| w.set_ctr(ctr))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for channel interrupt.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wait_for_wrap(&mut self) {
|
pub fn wait_for_wrap(&mut self) {
|
||||||
while !self.wrapped() {}
|
while !self.wrapped() {}
|
||||||
self.clear_wrapped();
|
self.clear_wrapped();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if interrupt for channel is set.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wrapped(&mut self) -> bool {
|
pub fn wrapped(&mut self) -> bool {
|
||||||
pac::PWM.intr().read().0 & self.bit() != 0
|
pac::PWM.intr().read().0 & self.bit() != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Clear interrupt flag.
|
|
||||||
pub fn clear_wrapped(&mut self) {
|
pub fn clear_wrapped(&mut self) {
|
||||||
pac::PWM.intr().write_value(Intr(self.bit() as _));
|
pac::PWM.intr().write_value(Intr(self.bit() as _));
|
||||||
}
|
}
|
||||||
@ -265,18 +253,15 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Batch representation of PWM channels.
|
|
||||||
pub struct PwmBatch(u32);
|
pub struct PwmBatch(u32);
|
||||||
|
|
||||||
impl PwmBatch {
|
impl PwmBatch {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Enable a PWM channel in this batch.
|
|
||||||
pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) {
|
pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) {
|
||||||
self.0 |= pwm.bit();
|
self.0 |= pwm.bit();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Enable channels in this batch in a PWM.
|
|
||||||
pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) {
|
pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) {
|
||||||
let mut en = PwmBatch(0);
|
let mut en = PwmBatch(0);
|
||||||
batch(&mut en);
|
batch(&mut en);
|
||||||
@ -304,12 +289,9 @@ mod sealed {
|
|||||||
pub trait Channel {}
|
pub trait Channel {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PWM Channel.
|
|
||||||
pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static {
|
pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static {
|
||||||
/// Channel number.
|
|
||||||
fn number(&self) -> u8;
|
fn number(&self) -> u8;
|
||||||
|
|
||||||
/// Channel register block.
|
|
||||||
fn regs(&self) -> pac::pwm::Channel {
|
fn regs(&self) -> pac::pwm::Channel {
|
||||||
pac::PWM.ch(self.number() as _)
|
pac::PWM.ch(self.number() as _)
|
||||||
}
|
}
|
||||||
@ -335,9 +317,7 @@ channel!(PWM_CH5, 5);
|
|||||||
channel!(PWM_CH6, 6);
|
channel!(PWM_CH6, 6);
|
||||||
channel!(PWM_CH7, 7);
|
channel!(PWM_CH7, 7);
|
||||||
|
|
||||||
/// PWM Pin A.
|
|
||||||
pub trait PwmPinA<T: Channel>: GpioPin {}
|
pub trait PwmPinA<T: Channel>: GpioPin {}
|
||||||
/// PWM Pin B.
|
|
||||||
pub trait PwmPinB<T: Channel>: GpioPin {}
|
pub trait PwmPinB<T: Channel>: GpioPin {}
|
||||||
|
|
||||||
macro_rules! impl_pin {
|
macro_rules! impl_pin {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! RTC driver.
|
|
||||||
mod filter;
|
mod filter;
|
||||||
|
|
||||||
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
|
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! Timer driver.
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
|
|
||||||
use atomic_polyfill::{AtomicU8, Ordering};
|
use atomic_polyfill::{AtomicU8, Ordering};
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! Buffered UART driver.
|
|
||||||
use core::future::{poll_fn, Future};
|
use core::future::{poll_fn, Future};
|
||||||
use core::slice;
|
use core::slice;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! UART driver.
|
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
@ -948,7 +947,7 @@ pub struct Async;
|
|||||||
impl_mode!(Blocking);
|
impl_mode!(Blocking);
|
||||||
impl_mode!(Async);
|
impl_mode!(Async);
|
||||||
|
|
||||||
/// UART instance.
|
/// UART instance trait.
|
||||||
pub trait Instance: sealed::Instance {}
|
pub trait Instance: sealed::Instance {}
|
||||||
|
|
||||||
macro_rules! impl_instance {
|
macro_rules! impl_instance {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//! USB driver.
|
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::slice;
|
use core::slice;
|
||||||
|
@ -26,7 +26,7 @@ aligned = "0.4.1"
|
|||||||
|
|
||||||
bit_field = "0.10.2"
|
bit_field = "0.10.2"
|
||||||
stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
|
stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
|
||||||
stm32wb-hci = { git = "https://github.com/Dirbaio/stm32wb-hci", rev = "0aff47e009c30c5fc5d520672625173d75f7505c", optional = true }
|
stm32wb-hci = { version = "0.1.4", optional = true }
|
||||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||||
bitflags = { version = "2.3.3", optional = true }
|
bitflags = { version = "2.3.3", optional = true }
|
||||||
|
|
||||||
|
@ -56,8 +56,9 @@ cortex-m = "0.7.6"
|
|||||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||||
rand_core = "0.6.3"
|
rand_core = "0.6.3"
|
||||||
sdio-host = "0.5.0"
|
sdio-host = "0.5.0"
|
||||||
|
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
||||||
critical-section = "1.1"
|
critical-section = "1.1"
|
||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2234f380f51d16d0398b8e547088b33ea623cc7c" }
|
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-91cee0d1fdcb4e447b65a09756b506f4af91b7e2" }
|
||||||
vcell = "0.1.3"
|
vcell = "0.1.3"
|
||||||
bxcan = "0.7.0"
|
bxcan = "0.7.0"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
@ -75,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] }
|
|||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
proc-macro2 = "1.0.36"
|
proc-macro2 = "1.0.36"
|
||||||
quote = "1.0.15"
|
quote = "1.0.15"
|
||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2234f380f51d16d0398b8e547088b33ea623cc7c", default-features = false, features = ["metadata"]}
|
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-91cee0d1fdcb4e447b65a09756b506f4af91b7e2", default-features = false, features = ["metadata"]}
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -23,10 +23,6 @@ use crate::pac::bdma::{regs, vals};
|
|||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct TransferOptions {
|
pub struct TransferOptions {
|
||||||
/// Enable circular DMA
|
/// Enable circular DMA
|
||||||
///
|
|
||||||
/// Note:
|
|
||||||
/// If you enable circular mode manually, you may want to build and `.await` the `Transfer` in a separate task.
|
|
||||||
/// Since DMA in circular mode need manually stop, `.await` in current task would block the task forever.
|
|
||||||
pub circular: bool,
|
pub circular: bool,
|
||||||
/// Enable half transfer interrupt
|
/// Enable half transfer interrupt
|
||||||
pub half_transfer_ir: bool,
|
pub half_transfer_ir: bool,
|
||||||
@ -307,14 +303,20 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
ch.cr().write(|w| {
|
ch.cr().write(|w| {
|
||||||
w.set_psize(data_size.into());
|
w.set_psize(data_size.into());
|
||||||
w.set_msize(data_size.into());
|
w.set_msize(data_size.into());
|
||||||
w.set_minc(incr_mem);
|
if incr_mem {
|
||||||
|
w.set_minc(vals::Inc::ENABLED);
|
||||||
|
} else {
|
||||||
|
w.set_minc(vals::Inc::DISABLED);
|
||||||
|
}
|
||||||
w.set_dir(dir.into());
|
w.set_dir(dir.into());
|
||||||
w.set_teie(true);
|
w.set_teie(true);
|
||||||
w.set_tcie(options.complete_transfer_ir);
|
w.set_tcie(options.complete_transfer_ir);
|
||||||
w.set_htie(options.half_transfer_ir);
|
w.set_htie(options.half_transfer_ir);
|
||||||
w.set_circ(options.circular);
|
|
||||||
if options.circular {
|
if options.circular {
|
||||||
|
w.set_circ(vals::Circ::ENABLED);
|
||||||
debug!("Setting circular mode");
|
debug!("Setting circular mode");
|
||||||
|
} else {
|
||||||
|
w.set_circ(vals::Circ::DISABLED);
|
||||||
}
|
}
|
||||||
w.set_pl(vals::Pl::VERYHIGH);
|
w.set_pl(vals::Pl::VERYHIGH);
|
||||||
w.set_en(true);
|
w.set_en(true);
|
||||||
@ -350,7 +352,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
pub fn is_running(&mut self) -> bool {
|
pub fn is_running(&mut self) -> bool {
|
||||||
let ch = self.channel.regs().ch(self.channel.num());
|
let ch = self.channel.regs().ch(self.channel.num());
|
||||||
let en = ch.cr().read().en();
|
let en = ch.cr().read().en();
|
||||||
let circular = ch.cr().read().circ();
|
let circular = ch.cr().read().circ() == vals::Circ::ENABLED;
|
||||||
let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0;
|
let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0;
|
||||||
en && (circular || !tcif)
|
en && (circular || !tcif)
|
||||||
}
|
}
|
||||||
@ -465,12 +467,12 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
|
|||||||
let mut w = regs::Cr(0);
|
let mut w = regs::Cr(0);
|
||||||
w.set_psize(data_size.into());
|
w.set_psize(data_size.into());
|
||||||
w.set_msize(data_size.into());
|
w.set_msize(data_size.into());
|
||||||
w.set_minc(true);
|
w.set_minc(vals::Inc::ENABLED);
|
||||||
w.set_dir(dir.into());
|
w.set_dir(dir.into());
|
||||||
w.set_teie(true);
|
w.set_teie(true);
|
||||||
w.set_htie(true);
|
w.set_htie(true);
|
||||||
w.set_tcie(true);
|
w.set_tcie(true);
|
||||||
w.set_circ(true);
|
w.set_circ(vals::Circ::ENABLED);
|
||||||
w.set_pl(vals::Pl::VERYHIGH);
|
w.set_pl(vals::Pl::VERYHIGH);
|
||||||
w.set_en(true);
|
w.set_en(true);
|
||||||
|
|
||||||
@ -623,12 +625,12 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
|
|||||||
let mut w = regs::Cr(0);
|
let mut w = regs::Cr(0);
|
||||||
w.set_psize(data_size.into());
|
w.set_psize(data_size.into());
|
||||||
w.set_msize(data_size.into());
|
w.set_msize(data_size.into());
|
||||||
w.set_minc(true);
|
w.set_minc(vals::Inc::ENABLED);
|
||||||
w.set_dir(dir.into());
|
w.set_dir(dir.into());
|
||||||
w.set_teie(true);
|
w.set_teie(true);
|
||||||
w.set_htie(true);
|
w.set_htie(true);
|
||||||
w.set_tcie(true);
|
w.set_tcie(true);
|
||||||
w.set_circ(true);
|
w.set_circ(vals::Circ::ENABLED);
|
||||||
w.set_pl(vals::Pl::VERYHIGH);
|
w.set_pl(vals::Pl::VERYHIGH);
|
||||||
w.set_en(true);
|
w.set_en(true);
|
||||||
|
|
||||||
|
@ -30,10 +30,6 @@ pub struct TransferOptions {
|
|||||||
/// FIFO threshold for DMA FIFO mode. If none, direct mode is used.
|
/// FIFO threshold for DMA FIFO mode. If none, direct mode is used.
|
||||||
pub fifo_threshold: Option<FifoThreshold>,
|
pub fifo_threshold: Option<FifoThreshold>,
|
||||||
/// Enable circular DMA
|
/// Enable circular DMA
|
||||||
///
|
|
||||||
/// Note:
|
|
||||||
/// If you enable circular mode manually, you may want to build and `.await` the `Transfer` in a separate task.
|
|
||||||
/// Since DMA in circular mode need manually stop, `.await` in current task would block the task forever.
|
|
||||||
pub circular: bool,
|
pub circular: bool,
|
||||||
/// Enable half transfer interrupt
|
/// Enable half transfer interrupt
|
||||||
pub half_transfer_ir: bool,
|
pub half_transfer_ir: bool,
|
||||||
@ -386,13 +382,18 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
w.set_msize(data_size.into());
|
w.set_msize(data_size.into());
|
||||||
w.set_psize(data_size.into());
|
w.set_psize(data_size.into());
|
||||||
w.set_pl(vals::Pl::VERYHIGH);
|
w.set_pl(vals::Pl::VERYHIGH);
|
||||||
w.set_minc(incr_mem);
|
w.set_minc(match incr_mem {
|
||||||
w.set_pinc(false);
|
true => vals::Inc::INCREMENTED,
|
||||||
|
false => vals::Inc::FIXED,
|
||||||
|
});
|
||||||
|
w.set_pinc(vals::Inc::FIXED);
|
||||||
w.set_teie(true);
|
w.set_teie(true);
|
||||||
w.set_tcie(options.complete_transfer_ir);
|
w.set_tcie(options.complete_transfer_ir);
|
||||||
w.set_circ(options.circular);
|
|
||||||
if options.circular {
|
if options.circular {
|
||||||
|
w.set_circ(vals::Circ::ENABLED);
|
||||||
debug!("Setting circular mode");
|
debug!("Setting circular mode");
|
||||||
|
} else {
|
||||||
|
w.set_circ(vals::Circ::DISABLED);
|
||||||
}
|
}
|
||||||
#[cfg(dma_v1)]
|
#[cfg(dma_v1)]
|
||||||
w.set_trbuff(true);
|
w.set_trbuff(true);
|
||||||
@ -544,8 +545,8 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
|
|||||||
w.set_msize(data_size.into());
|
w.set_msize(data_size.into());
|
||||||
w.set_psize(data_size.into());
|
w.set_psize(data_size.into());
|
||||||
w.set_pl(vals::Pl::VERYHIGH);
|
w.set_pl(vals::Pl::VERYHIGH);
|
||||||
w.set_minc(true);
|
w.set_minc(vals::Inc::INCREMENTED);
|
||||||
w.set_pinc(false);
|
w.set_pinc(vals::Inc::FIXED);
|
||||||
w.set_teie(true);
|
w.set_teie(true);
|
||||||
w.set_tcie(true);
|
w.set_tcie(true);
|
||||||
#[cfg(dma_v1)]
|
#[cfg(dma_v1)]
|
||||||
@ -702,12 +703,12 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
|
|||||||
w.set_msize(data_size.into());
|
w.set_msize(data_size.into());
|
||||||
w.set_psize(data_size.into());
|
w.set_psize(data_size.into());
|
||||||
w.set_pl(vals::Pl::VERYHIGH);
|
w.set_pl(vals::Pl::VERYHIGH);
|
||||||
w.set_minc(true);
|
w.set_minc(vals::Inc::INCREMENTED);
|
||||||
w.set_pinc(false);
|
w.set_pinc(vals::Inc::FIXED);
|
||||||
w.set_teie(true);
|
w.set_teie(true);
|
||||||
w.set_htie(options.half_transfer_ir);
|
w.set_htie(options.half_transfer_ir);
|
||||||
w.set_tcie(true);
|
w.set_tcie(true);
|
||||||
w.set_circ(true);
|
w.set_circ(vals::Circ::ENABLED);
|
||||||
#[cfg(dma_v1)]
|
#[cfg(dma_v1)]
|
||||||
w.set_trbuff(true);
|
w.set_trbuff(true);
|
||||||
#[cfg(dma_v2)]
|
#[cfg(dma_v2)]
|
||||||
@ -877,12 +878,12 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
|
|||||||
w.set_msize(data_size.into());
|
w.set_msize(data_size.into());
|
||||||
w.set_psize(data_size.into());
|
w.set_psize(data_size.into());
|
||||||
w.set_pl(vals::Pl::VERYHIGH);
|
w.set_pl(vals::Pl::VERYHIGH);
|
||||||
w.set_minc(true);
|
w.set_minc(vals::Inc::INCREMENTED);
|
||||||
w.set_pinc(false);
|
w.set_pinc(vals::Inc::FIXED);
|
||||||
w.set_teie(true);
|
w.set_teie(true);
|
||||||
w.set_htie(options.half_transfer_ir);
|
w.set_htie(options.half_transfer_ir);
|
||||||
w.set_tcie(true);
|
w.set_tcie(true);
|
||||||
w.set_circ(true);
|
w.set_circ(vals::Circ::ENABLED);
|
||||||
#[cfg(dma_v1)]
|
#[cfg(dma_v1)]
|
||||||
w.set_trbuff(true);
|
w.set_trbuff(true);
|
||||||
#[cfg(dma_v2)]
|
#[cfg(dma_v2)]
|
||||||
|
@ -16,7 +16,6 @@ use crate::interrupt::Priority;
|
|||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::pac::gpdma::vals;
|
use crate::pac::gpdma::vals;
|
||||||
|
|
||||||
/// GPDMA transfer options.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@ -114,13 +113,10 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::gpdma::Gpdma, channel_num: usize, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMA request type alias. (also known as DMA channel number in some chips)
|
|
||||||
pub type Request = u8;
|
pub type Request = u8;
|
||||||
|
|
||||||
/// DMA channel.
|
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {}
|
pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {}
|
||||||
/// DMA channel.
|
|
||||||
#[cfg(not(dmamux))]
|
#[cfg(not(dmamux))]
|
||||||
pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {}
|
pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {}
|
||||||
|
|
||||||
@ -135,14 +131,12 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMA transfer.
|
|
||||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||||
pub struct Transfer<'a, C: Channel> {
|
pub struct Transfer<'a, C: Channel> {
|
||||||
channel: PeripheralRef<'a, C>,
|
channel: PeripheralRef<'a, C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, C: Channel> Transfer<'a, C> {
|
impl<'a, C: Channel> Transfer<'a, C> {
|
||||||
/// Create a new read DMA transfer (peripheral to memory).
|
|
||||||
pub unsafe fn new_read<W: Word>(
|
pub unsafe fn new_read<W: Word>(
|
||||||
channel: impl Peripheral<P = C> + 'a,
|
channel: impl Peripheral<P = C> + 'a,
|
||||||
request: Request,
|
request: Request,
|
||||||
@ -153,7 +147,6 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
Self::new_read_raw(channel, request, peri_addr, buf, options)
|
Self::new_read_raw(channel, request, peri_addr, buf, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new read DMA transfer (peripheral to memory), using raw pointers.
|
|
||||||
pub unsafe fn new_read_raw<W: Word>(
|
pub unsafe fn new_read_raw<W: Word>(
|
||||||
channel: impl Peripheral<P = C> + 'a,
|
channel: impl Peripheral<P = C> + 'a,
|
||||||
request: Request,
|
request: Request,
|
||||||
@ -179,7 +172,6 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new write DMA transfer (memory to peripheral).
|
|
||||||
pub unsafe fn new_write<W: Word>(
|
pub unsafe fn new_write<W: Word>(
|
||||||
channel: impl Peripheral<P = C> + 'a,
|
channel: impl Peripheral<P = C> + 'a,
|
||||||
request: Request,
|
request: Request,
|
||||||
@ -190,7 +182,6 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
Self::new_write_raw(channel, request, buf, peri_addr, options)
|
Self::new_write_raw(channel, request, buf, peri_addr, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new write DMA transfer (memory to peripheral), using raw pointers.
|
|
||||||
pub unsafe fn new_write_raw<W: Word>(
|
pub unsafe fn new_write_raw<W: Word>(
|
||||||
channel: impl Peripheral<P = C> + 'a,
|
channel: impl Peripheral<P = C> + 'a,
|
||||||
request: Request,
|
request: Request,
|
||||||
@ -216,7 +207,6 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly.
|
|
||||||
pub unsafe fn new_write_repeated<W: Word>(
|
pub unsafe fn new_write_repeated<W: Word>(
|
||||||
channel: impl Peripheral<P = C> + 'a,
|
channel: impl Peripheral<P = C> + 'a,
|
||||||
request: Request,
|
request: Request,
|
||||||
@ -307,9 +297,6 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request the transfer to stop.
|
|
||||||
///
|
|
||||||
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
|
|
||||||
pub fn request_stop(&mut self) {
|
pub fn request_stop(&mut self) {
|
||||||
let ch = self.channel.regs().ch(self.channel.num());
|
let ch = self.channel.regs().ch(self.channel.num());
|
||||||
ch.cr().modify(|w| {
|
ch.cr().modify(|w| {
|
||||||
@ -317,10 +304,6 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether this transfer is still running.
|
|
||||||
///
|
|
||||||
/// If this returns `false`, it can be because either the transfer finished, or
|
|
||||||
/// it was requested to stop early with [`request_stop`](Self::request_stop).
|
|
||||||
pub fn is_running(&mut self) -> bool {
|
pub fn is_running(&mut self) -> bool {
|
||||||
let ch = self.channel.regs().ch(self.channel.num());
|
let ch = self.channel.regs().ch(self.channel.num());
|
||||||
let sr = ch.sr().read();
|
let sr = ch.sr().read();
|
||||||
@ -334,7 +317,6 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
|||||||
ch.br1().read().bndt()
|
ch.br1().read().bndt()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking wait until the transfer finishes.
|
|
||||||
pub fn blocking_wait(mut self) {
|
pub fn blocking_wait(mut self) {
|
||||||
while self.is_running() {}
|
while self.is_running() {}
|
||||||
|
|
||||||
|
@ -15,42 +15,38 @@ use crate::rcc::get_freqs;
|
|||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
|
||||||
/// HRTIM burst controller instance.
|
pub enum Source {
|
||||||
|
Master,
|
||||||
|
ChA,
|
||||||
|
ChB,
|
||||||
|
ChC,
|
||||||
|
ChD,
|
||||||
|
ChE,
|
||||||
|
#[cfg(hrtim_v2)]
|
||||||
|
ChF,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BurstController<T: Instance> {
|
pub struct BurstController<T: Instance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM master instance.
|
|
||||||
pub struct Master<T: Instance> {
|
pub struct Master<T: Instance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM channel A instance.
|
|
||||||
pub struct ChA<T: Instance> {
|
pub struct ChA<T: Instance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM channel B instance.
|
|
||||||
pub struct ChB<T: Instance> {
|
pub struct ChB<T: Instance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM channel C instance.
|
|
||||||
pub struct ChC<T: Instance> {
|
pub struct ChC<T: Instance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM channel D instance.
|
|
||||||
pub struct ChD<T: Instance> {
|
pub struct ChD<T: Instance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM channel E instance.
|
|
||||||
pub struct ChE<T: Instance> {
|
pub struct ChE<T: Instance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM channel F instance.
|
|
||||||
#[cfg(hrtim_v2)]
|
#[cfg(hrtim_v2)]
|
||||||
pub struct ChF<T: Instance> {
|
pub struct ChF<T: Instance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
@ -64,26 +60,22 @@ mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advanced channel instance trait.
|
|
||||||
pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {}
|
pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {}
|
||||||
|
|
||||||
/// HRTIM PWM pin.
|
pub struct PwmPin<'d, Perip, Channel> {
|
||||||
pub struct PwmPin<'d, T, C> {
|
|
||||||
_pin: PeripheralRef<'d, AnyPin>,
|
_pin: PeripheralRef<'d, AnyPin>,
|
||||||
phantom: PhantomData<(T, C)>,
|
phantom: PhantomData<(Perip, Channel)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM complementary PWM pin.
|
pub struct ComplementaryPwmPin<'d, Perip, Channel> {
|
||||||
pub struct ComplementaryPwmPin<'d, T, C> {
|
|
||||||
_pin: PeripheralRef<'d, AnyPin>,
|
_pin: PeripheralRef<'d, AnyPin>,
|
||||||
phantom: PhantomData<(T, C)>,
|
phantom: PhantomData<(Perip, Channel)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! advanced_channel_impl {
|
macro_rules! advanced_channel_impl {
|
||||||
($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
|
($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
|
||||||
impl<'d, T: Instance> PwmPin<'d, T, $channel<T>> {
|
impl<'d, Perip: Instance> PwmPin<'d, Perip, $channel<Perip>> {
|
||||||
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
|
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
|
||||||
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self {
|
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
pin.set_low();
|
pin.set_low();
|
||||||
@ -98,9 +90,8 @@ macro_rules! advanced_channel_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> ComplementaryPwmPin<'d, T, $channel<T>> {
|
impl<'d, Perip: Instance> ComplementaryPwmPin<'d, Perip, $channel<Perip>> {
|
||||||
#[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
|
pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self {
|
||||||
pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<T>> + 'd) -> Self {
|
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
pin.set_low();
|
pin.set_low();
|
||||||
@ -135,29 +126,18 @@ advanced_channel_impl!(new_chf, ChF, 5, ChannelFPin, ChannelFComplementaryPin);
|
|||||||
/// Struct used to divide a high resolution timer into multiple channels
|
/// Struct used to divide a high resolution timer into multiple channels
|
||||||
pub struct AdvancedPwm<'d, T: Instance> {
|
pub struct AdvancedPwm<'d, T: Instance> {
|
||||||
_inner: PeripheralRef<'d, T>,
|
_inner: PeripheralRef<'d, T>,
|
||||||
/// Master instance.
|
|
||||||
pub master: Master<T>,
|
pub master: Master<T>,
|
||||||
/// Burst controller.
|
|
||||||
pub burst_controller: BurstController<T>,
|
pub burst_controller: BurstController<T>,
|
||||||
/// Channel A.
|
|
||||||
pub ch_a: ChA<T>,
|
pub ch_a: ChA<T>,
|
||||||
/// Channel B.
|
|
||||||
pub ch_b: ChB<T>,
|
pub ch_b: ChB<T>,
|
||||||
/// Channel C.
|
|
||||||
pub ch_c: ChC<T>,
|
pub ch_c: ChC<T>,
|
||||||
/// Channel D.
|
|
||||||
pub ch_d: ChD<T>,
|
pub ch_d: ChD<T>,
|
||||||
/// Channel E.
|
|
||||||
pub ch_e: ChE<T>,
|
pub ch_e: ChE<T>,
|
||||||
/// Channel F.
|
|
||||||
#[cfg(hrtim_v2)]
|
#[cfg(hrtim_v2)]
|
||||||
pub ch_f: ChF<T>,
|
pub ch_f: ChF<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> AdvancedPwm<'d, T> {
|
impl<'d, T: Instance> AdvancedPwm<'d, T> {
|
||||||
/// Create a new HRTIM driver.
|
|
||||||
///
|
|
||||||
/// This splits the HRTIM into its constituent parts, which you can then use individually.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tim: impl Peripheral<P = T> + 'd,
|
tim: impl Peripheral<P = T> + 'd,
|
||||||
_cha: Option<PwmPin<'d, T, ChA<T>>>,
|
_cha: Option<PwmPin<'d, T, ChA<T>>>,
|
||||||
@ -220,7 +200,13 @@ impl<'d, T: Instance> AdvancedPwm<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fixed-frequency bridge converter driver.
|
impl<T: Instance> BurstController<T> {
|
||||||
|
pub fn set_source(&mut self, _source: Source) {
|
||||||
|
todo!("burst mode control registers not implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a fixed-frequency bridge converter
|
||||||
///
|
///
|
||||||
/// Our implementation of the bridge converter uses a single channel and three compare registers,
|
/// Our implementation of the bridge converter uses a single channel and three compare registers,
|
||||||
/// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous
|
/// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous
|
||||||
@ -239,7 +225,6 @@ pub struct BridgeConverter<T: Instance, C: AdvancedChannel<T>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
|
impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
|
||||||
/// Create a new HRTIM bridge converter driver.
|
|
||||||
pub fn new(_channel: C, frequency: Hertz) -> Self {
|
pub fn new(_channel: C, frequency: Hertz) -> Self {
|
||||||
use crate::pac::hrtim::vals::{Activeeffect, Inactiveeffect};
|
use crate::pac::hrtim::vals::{Activeeffect, Inactiveeffect};
|
||||||
|
|
||||||
@ -296,17 +281,14 @@ impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start HRTIM.
|
|
||||||
pub fn start(&mut self) {
|
pub fn start(&mut self) {
|
||||||
T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true));
|
T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stop HRTIM.
|
|
||||||
pub fn stop(&mut self) {
|
pub fn stop(&mut self) {
|
||||||
T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false));
|
T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable burst mode.
|
|
||||||
pub fn enable_burst_mode(&mut self) {
|
pub fn enable_burst_mode(&mut self) {
|
||||||
T::regs().tim(C::raw()).outr().modify(|w| {
|
T::regs().tim(C::raw()).outr().modify(|w| {
|
||||||
// Enable Burst Mode
|
// Enable Burst Mode
|
||||||
@ -319,7 +301,6 @@ impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable burst mode.
|
|
||||||
pub fn disable_burst_mode(&mut self) {
|
pub fn disable_burst_mode(&mut self) {
|
||||||
T::regs().tim(C::raw()).outr().modify(|w| {
|
T::regs().tim(C::raw()).outr().modify(|w| {
|
||||||
// Disable Burst Mode
|
// Disable Burst Mode
|
||||||
@ -376,7 +357,7 @@ impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Variable-frequency resonant converter driver.
|
/// Represents a variable-frequency resonant converter
|
||||||
///
|
///
|
||||||
/// This implementation of a resonsant converter is appropriate for a half or full bridge,
|
/// This implementation of a resonsant converter is appropriate for a half or full bridge,
|
||||||
/// but does not include secondary rectification, which is appropriate for applications
|
/// but does not include secondary rectification, which is appropriate for applications
|
||||||
@ -389,7 +370,6 @@ pub struct ResonantConverter<T: Instance, C: AdvancedChannel<T>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
|
impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
|
||||||
/// Create a new variable-frequency resonant converter driver.
|
|
||||||
pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self {
|
pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self {
|
||||||
T::set_channel_frequency(C::raw(), min_frequency);
|
T::set_channel_frequency(C::raw(), min_frequency);
|
||||||
|
|
||||||
@ -428,7 +408,6 @@ impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
|
|||||||
T::set_channel_dead_time(C::raw(), value);
|
T::set_channel_dead_time(C::raw(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the timer period.
|
|
||||||
pub fn set_period(&mut self, period: u16) {
|
pub fn set_period(&mut self, period: u16) {
|
||||||
assert!(period < self.max_period);
|
assert!(period < self.max_period);
|
||||||
assert!(period > self.min_period);
|
assert!(period > self.min_period);
|
||||||
|
@ -125,6 +125,7 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the dead time as a proportion of max_duty
|
/// Set the dead time as a proportion of max_duty
|
||||||
|
|
||||||
fn set_channel_dead_time(channel: usize, dead_time: u16) {
|
fn set_channel_dead_time(channel: usize, dead_time: u16) {
|
||||||
let regs = Self::regs();
|
let regs = Self::regs();
|
||||||
|
|
||||||
@ -147,10 +148,13 @@ pub(crate) mod sealed {
|
|||||||
w.set_dtr(dt_val as u16);
|
w.set_dtr(dt_val as u16);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn enable_outputs(enable: bool);
|
||||||
|
//
|
||||||
|
// fn enable_channel(&mut self, channel: usize, enable: bool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HRTIM instance trait.
|
|
||||||
pub trait Instance: sealed::Instance + 'static {}
|
pub trait Instance: sealed::Instance + 'static {}
|
||||||
|
|
||||||
foreach_interrupt! {
|
foreach_interrupt! {
|
||||||
|
@ -148,20 +148,31 @@ struct Timeout {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl Timeout {
|
impl Timeout {
|
||||||
|
#[cfg(not(feature = "time"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn check(self) -> Result<(), Error> {
|
fn check(self) -> Result<(), Error> {
|
||||||
#[cfg(feature = "time")]
|
|
||||||
if Instant::now() > self.deadline {
|
|
||||||
return Err(Error::Timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
#[inline]
|
||||||
|
fn check(self) -> Result<(), Error> {
|
||||||
|
if Instant::now() > self.deadline {
|
||||||
|
Err(Error::Timeout)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "time"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> {
|
fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> {
|
||||||
|
fut
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "time")]
|
#[cfg(feature = "time")]
|
||||||
{
|
#[inline]
|
||||||
|
fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> {
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
|
|
||||||
embassy_futures::select::select(embassy_time::Timer::at(self.deadline), fut).map(|r| match r {
|
embassy_futures::select::select(embassy_time::Timer::at(self.deadline), fut).map(|r| match r {
|
||||||
@ -169,10 +180,6 @@ impl Timeout {
|
|||||||
embassy_futures::select::Either::Second(r) => r,
|
embassy_futures::select::Either::Second(r) => r,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "time"))]
|
|
||||||
fut
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! Inter-Process Communication Controller (IPCC)
|
|
||||||
|
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
@ -43,7 +41,6 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_RX> for Receive
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TX interrupt handler.
|
|
||||||
pub struct TransmitInterruptHandler {}
|
pub struct TransmitInterruptHandler {}
|
||||||
|
|
||||||
impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for TransmitInterruptHandler {
|
impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for TransmitInterruptHandler {
|
||||||
@ -75,7 +72,6 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for Transmi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// IPCC config.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
@ -83,8 +79,6 @@ pub struct Config {
|
|||||||
// reserved for future use
|
// reserved for future use
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel.
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum IpccChannel {
|
pub enum IpccChannel {
|
||||||
@ -96,11 +90,9 @@ pub enum IpccChannel {
|
|||||||
Channel6 = 5,
|
Channel6 = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// IPCC driver.
|
|
||||||
pub struct Ipcc;
|
pub struct Ipcc;
|
||||||
|
|
||||||
impl Ipcc {
|
impl Ipcc {
|
||||||
/// Enable IPCC.
|
|
||||||
pub fn enable(_config: Config) {
|
pub fn enable(_config: Config) {
|
||||||
IPCC::enable_and_reset();
|
IPCC::enable_and_reset();
|
||||||
IPCC::set_cpu2(true);
|
IPCC::set_cpu2(true);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#![cfg_attr(not(test), no_std)]
|
#![cfg_attr(not(test), no_std)]
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
//! ## Feature flags
|
//! ## Feature flags
|
||||||
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
|
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
|
||||||
@ -80,7 +79,6 @@ pub(crate) mod _generated {
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
#![allow(missing_docs)]
|
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
|
include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
|
||||||
}
|
}
|
||||||
|
@ -1,54 +1,50 @@
|
|||||||
//! Low-power support.
|
/// The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
|
||||||
//!
|
/// to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
|
||||||
//! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
|
/// can use knowledge of which peripherals are currently blocked upon to transparently and safely
|
||||||
//! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
|
/// enter such low-power modes (currently, only `STOP2`) when idle.
|
||||||
//! can use knowledge of which peripherals are currently blocked upon to transparently and safely
|
///
|
||||||
//! enter such low-power modes (currently, only `STOP2`) when idle.
|
/// The executor determines which peripherals are active by their RCC state; consequently,
|
||||||
//!
|
/// low-power states can only be entered if all peripherals have been `drop`'d. There are a few
|
||||||
//! The executor determines which peripherals are active by their RCC state; consequently,
|
/// exceptions to this rule:
|
||||||
//! low-power states can only be entered if all peripherals have been `drop`'d. There are a few
|
///
|
||||||
//! exceptions to this rule:
|
/// * `GPIO`
|
||||||
//!
|
/// * `RCC`
|
||||||
//! * `GPIO`
|
///
|
||||||
//! * `RCC`
|
/// Since entering and leaving low-power modes typically incurs a significant latency, the
|
||||||
//!
|
/// low-power executor will only attempt to enter when the next timer event is at least
|
||||||
//! Since entering and leaving low-power modes typically incurs a significant latency, the
|
/// [`time_driver::MIN_STOP_PAUSE`] in the future.
|
||||||
//! low-power executor will only attempt to enter when the next timer event is at least
|
///
|
||||||
//! [`time_driver::MIN_STOP_PAUSE`] in the future.
|
/// Currently there is no macro analogous to `embassy_executor::main` for this executor;
|
||||||
//!
|
/// consequently one must define their entrypoint manually. Moveover, you must relinquish control
|
||||||
//! Currently there is no macro analogous to `embassy_executor::main` for this executor;
|
/// of the `RTC` peripheral to the executor. This will typically look like
|
||||||
//! consequently one must define their entrypoint manually. Moveover, you must relinquish control
|
///
|
||||||
//! of the `RTC` peripheral to the executor. This will typically look like
|
/// ```rust,no_run
|
||||||
//!
|
/// use embassy_executor::Spawner;
|
||||||
//! ```rust,no_run
|
/// use embassy_stm32::low_power::Executor;
|
||||||
//! use embassy_executor::Spawner;
|
/// use embassy_stm32::rtc::{Rtc, RtcConfig};
|
||||||
//! use embassy_stm32::low_power::Executor;
|
/// use static_cell::make_static;
|
||||||
//! use embassy_stm32::rtc::{Rtc, RtcConfig};
|
///
|
||||||
//! use static_cell::StaticCell;
|
/// #[cortex_m_rt::entry]
|
||||||
//!
|
/// fn main() -> ! {
|
||||||
//! #[cortex_m_rt::entry]
|
/// Executor::take().run(|spawner| {
|
||||||
//! fn main() -> ! {
|
/// unwrap!(spawner.spawn(async_main(spawner)));
|
||||||
//! Executor::take().run(|spawner| {
|
/// });
|
||||||
//! unwrap!(spawner.spawn(async_main(spawner)));
|
/// }
|
||||||
//! });
|
///
|
||||||
//! }
|
/// #[embassy_executor::task]
|
||||||
//!
|
/// async fn async_main(spawner: Spawner) {
|
||||||
//! #[embassy_executor::task]
|
/// // initialize the platform...
|
||||||
//! async fn async_main(spawner: Spawner) {
|
/// let mut config = embassy_stm32::Config::default();
|
||||||
//! // initialize the platform...
|
/// let p = embassy_stm32::init(config);
|
||||||
//! let mut config = embassy_stm32::Config::default();
|
///
|
||||||
//! let p = embassy_stm32::init(config);
|
/// // give the RTC to the executor...
|
||||||
//!
|
/// let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
|
||||||
//! // give the RTC to the executor...
|
/// let rtc = make_static!(rtc);
|
||||||
//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
|
/// embassy_stm32::low_power::stop_with_rtc(rtc);
|
||||||
//! static RTC: StaticCell<Rtc> = StaticCell::new();
|
///
|
||||||
//! let rtc = RTC.init(rtc);
|
/// // your application here...
|
||||||
//! embassy_stm32::low_power::stop_with_rtc(rtc);
|
/// }
|
||||||
//!
|
/// ```
|
||||||
//! // your application here...
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
@ -68,7 +64,6 @@ static mut EXECUTOR: Option<Executor> = None;
|
|||||||
foreach_interrupt! {
|
foreach_interrupt! {
|
||||||
(RTC, rtc, $block:ident, WKUP, $irq:ident) => {
|
(RTC, rtc, $block:ident, WKUP, $irq:ident) => {
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
#[allow(non_snake_case)]
|
|
||||||
unsafe fn $irq() {
|
unsafe fn $irq() {
|
||||||
EXECUTOR.as_mut().unwrap().on_wakeup_irq();
|
EXECUTOR.as_mut().unwrap().on_wakeup_irq();
|
||||||
}
|
}
|
||||||
@ -80,15 +75,10 @@ pub(crate) unsafe fn on_wakeup_irq() {
|
|||||||
EXECUTOR.as_mut().unwrap().on_wakeup_irq();
|
EXECUTOR.as_mut().unwrap().on_wakeup_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure STOP mode with RTC.
|
|
||||||
pub fn stop_with_rtc(rtc: &'static Rtc) {
|
pub fn stop_with_rtc(rtc: &'static Rtc) {
|
||||||
unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
|
unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get whether the core is ready to enter the given stop mode.
|
|
||||||
///
|
|
||||||
/// This will return false if some peripheral driver is in use that
|
|
||||||
/// prevents entering the given stop mode.
|
|
||||||
pub fn stop_ready(stop_mode: StopMode) -> bool {
|
pub fn stop_ready(stop_mode: StopMode) -> bool {
|
||||||
match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() {
|
match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() {
|
||||||
Some(StopMode::Stop2) => true,
|
Some(StopMode::Stop2) => true,
|
||||||
@ -97,13 +87,10 @@ pub fn stop_ready(stop_mode: StopMode) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Available stop modes.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum StopMode {
|
pub enum StopMode {
|
||||||
/// STOP 1
|
|
||||||
Stop1,
|
Stop1,
|
||||||
/// STOP 2
|
|
||||||
Stop2,
|
Stop2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
//! Operational Amplifier (OPAMP)
|
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
|
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
|
||||||
/// Gain
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum OpAmpGain {
|
pub enum OpAmpGain {
|
||||||
Mul1,
|
Mul1,
|
||||||
@ -16,8 +13,6 @@ pub enum OpAmpGain {
|
|||||||
Mul16,
|
Mul16,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Speed
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum OpAmpSpeed {
|
pub enum OpAmpSpeed {
|
||||||
Normal,
|
Normal,
|
||||||
@ -185,7 +180,6 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opamp instance trait.
|
|
||||||
pub trait Instance: sealed::Instance + 'static {}
|
pub trait Instance: sealed::Instance + 'static {}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
@ -204,11 +198,8 @@ pub(crate) mod sealed {
|
|||||||
pub trait OutputPin<T: Instance> {}
|
pub trait OutputPin<T: Instance> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Non-inverting pin trait.
|
|
||||||
pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {}
|
pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {}
|
||||||
/// Inverting pin trait.
|
|
||||||
pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {}
|
pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {}
|
||||||
/// Output pin trait.
|
|
||||||
pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {}
|
pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {}
|
||||||
|
|
||||||
macro_rules! impl_opamp_external_output {
|
macro_rules! impl_opamp_external_output {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! Enums used in QSPI configuration.
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum QspiMode {
|
pub(crate) enum QspiMode {
|
||||||
|
@ -14,7 +14,6 @@ use crate::pac::quadspi::Quadspi as Regs;
|
|||||||
use crate::rcc::RccPeripheral;
|
use crate::rcc::RccPeripheral;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{peripherals, Peripheral};
|
||||||
|
|
||||||
/// QSPI transfer configuration.
|
|
||||||
pub struct TransferConfig {
|
pub struct TransferConfig {
|
||||||
/// Instraction width (IMODE)
|
/// Instraction width (IMODE)
|
||||||
pub iwidth: QspiWidth,
|
pub iwidth: QspiWidth,
|
||||||
@ -46,7 +45,6 @@ impl Default for TransferConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// QSPI driver configuration.
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen.
|
/// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen.
|
||||||
/// If you need other value the whose predefined use `Other` variant.
|
/// If you need other value the whose predefined use `Other` variant.
|
||||||
@ -73,7 +71,6 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// QSPI driver.
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct Qspi<'d, T: Instance, Dma> {
|
pub struct Qspi<'d, T: Instance, Dma> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
@ -88,7 +85,6 @@ pub struct Qspi<'d, T: Instance, Dma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
||||||
/// Create a new QSPI driver for bank 1.
|
|
||||||
pub fn new_bk1(
|
pub fn new_bk1(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
|
||||||
@ -129,7 +125,6 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new QSPI driver for bank 2.
|
|
||||||
pub fn new_bk2(
|
pub fn new_bk2(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
|
d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
|
||||||
@ -228,7 +223,6 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do a QSPI command.
|
|
||||||
pub fn command(&mut self, transaction: TransferConfig) {
|
pub fn command(&mut self, transaction: TransferConfig) {
|
||||||
#[cfg(not(stm32h7))]
|
#[cfg(not(stm32h7))]
|
||||||
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
||||||
@ -238,7 +232,6 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
|||||||
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking read data.
|
|
||||||
pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {
|
pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {
|
||||||
#[cfg(not(stm32h7))]
|
#[cfg(not(stm32h7))]
|
||||||
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
T::REGS.cr().modify(|v| v.set_dmaen(false));
|
||||||
@ -263,7 +256,6 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
|||||||
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking write data.
|
|
||||||
pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) {
|
pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) {
|
||||||
// STM32H7 does not have dmaen
|
// STM32H7 does not have dmaen
|
||||||
#[cfg(not(stm32h7))]
|
#[cfg(not(stm32h7))]
|
||||||
@ -286,7 +278,6 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
|||||||
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
T::REGS.fcr().modify(|v| v.set_ctcf(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking read data, using DMA.
|
|
||||||
pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig)
|
pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig)
|
||||||
where
|
where
|
||||||
Dma: QuadDma<T>,
|
Dma: QuadDma<T>,
|
||||||
@ -319,7 +310,6 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
|
|||||||
transfer.blocking_wait();
|
transfer.blocking_wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking write data, using DMA.
|
|
||||||
pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig)
|
pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig)
|
||||||
where
|
where
|
||||||
Dma: QuadDma<T>,
|
Dma: QuadDma<T>,
|
||||||
@ -389,7 +379,6 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// QSPI instance trait.
|
|
||||||
pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
|
pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
|
||||||
|
|
||||||
pin_trait!(SckPin, Instance);
|
pin_trait!(SckPin, Instance);
|
||||||
|
@ -80,7 +80,6 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
let _ = self.next_u32();
|
let _ = self.next_u32();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset the RNG.
|
|
||||||
#[cfg(not(rng_v1))]
|
#[cfg(not(rng_v1))]
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
T::regs().cr().write(|reg| {
|
T::regs().cr().write(|reg| {
|
||||||
|
@ -130,7 +130,7 @@ impl RtcTimeProvider {
|
|||||||
let weekday = day_of_week_from_u8(dr.wdu()).map_err(RtcError::InvalidDateTime)?;
|
let weekday = day_of_week_from_u8(dr.wdu()).map_err(RtcError::InvalidDateTime)?;
|
||||||
let day = bcd2_to_byte((dr.dt(), dr.du()));
|
let day = bcd2_to_byte((dr.dt(), dr.du()));
|
||||||
let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
|
let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
|
||||||
let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16;
|
let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
|
||||||
|
|
||||||
DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
|
DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
|
||||||
})
|
})
|
||||||
@ -261,7 +261,7 @@ impl Rtc {
|
|||||||
let (dt, du) = byte_to_bcd2(t.day() as u8);
|
let (dt, du) = byte_to_bcd2(t.day() as u8);
|
||||||
let (mt, mu) = byte_to_bcd2(t.month() as u8);
|
let (mt, mu) = byte_to_bcd2(t.month() as u8);
|
||||||
let yr = t.year() as u16;
|
let yr = t.year() as u16;
|
||||||
let yr_offset = (yr - 2000_u16) as u8;
|
let yr_offset = (yr - 1970_u16) as u8;
|
||||||
let (yt, yu) = byte_to_bcd2(yr_offset);
|
let (yt, yu) = byte_to_bcd2(yr_offset);
|
||||||
|
|
||||||
use crate::pac::rtc::vals::Ampm;
|
use crate::pac::rtc::vals::Ampm;
|
||||||
|
@ -54,7 +54,6 @@ const SD_INIT_FREQ: Hertz = Hertz(400_000);
|
|||||||
|
|
||||||
/// The signalling scheme used on the SDMMC bus
|
/// The signalling scheme used on the SDMMC bus
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Signalling {
|
pub enum Signalling {
|
||||||
@ -71,9 +70,6 @@ impl Default for Signalling {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Aligned data block for SDMMC transfers.
|
|
||||||
///
|
|
||||||
/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
|
|
||||||
#[repr(align(4))]
|
#[repr(align(4))]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@ -98,23 +94,17 @@ impl DerefMut for DataBlock {
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Timeout reported by the hardware
|
|
||||||
Timeout,
|
Timeout,
|
||||||
/// Timeout reported by the software driver.
|
|
||||||
SoftwareTimeout,
|
SoftwareTimeout,
|
||||||
/// Unsupported card version.
|
|
||||||
UnsupportedCardVersion,
|
UnsupportedCardVersion,
|
||||||
/// Unsupported card type.
|
|
||||||
UnsupportedCardType,
|
UnsupportedCardType,
|
||||||
/// CRC error.
|
|
||||||
Crc,
|
Crc,
|
||||||
/// No card inserted.
|
DataCrcFail,
|
||||||
|
RxOverFlow,
|
||||||
NoCard,
|
NoCard,
|
||||||
/// Bad clock supplied to the SDMMC peripheral.
|
|
||||||
BadClock,
|
BadClock,
|
||||||
/// Signaling switch failed.
|
|
||||||
SignalingSwitchFailed,
|
SignalingSwitchFailed,
|
||||||
/// ST bit error.
|
PeripheralBusy,
|
||||||
#[cfg(sdmmc_v1)]
|
#[cfg(sdmmc_v1)]
|
||||||
StBitErr,
|
StBitErr,
|
||||||
}
|
}
|
||||||
@ -293,7 +283,6 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
|
|||||||
|
|
||||||
#[cfg(sdmmc_v1)]
|
#[cfg(sdmmc_v1)]
|
||||||
impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
||||||
/// Create a new SDMMC driver, with 1 data lane.
|
|
||||||
pub fn new_1bit(
|
pub fn new_1bit(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -328,7 +317,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new SDMMC driver, with 4 data lanes.
|
|
||||||
pub fn new_4bit(
|
pub fn new_4bit(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -375,7 +363,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
|||||||
|
|
||||||
#[cfg(sdmmc_v2)]
|
#[cfg(sdmmc_v2)]
|
||||||
impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
||||||
/// Create a new SDMMC driver, with 1 data lane.
|
|
||||||
pub fn new_1bit(
|
pub fn new_1bit(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -409,7 +396,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new SDMMC driver, with 4 data lanes.
|
|
||||||
pub fn new_4bit(
|
pub fn new_4bit(
|
||||||
sdmmc: impl Peripheral<P = T> + 'd,
|
sdmmc: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -511,7 +497,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Data transfer is in progress
|
/// Data transfer is in progress
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
fn data_active() -> bool {
|
fn data_active() -> bool {
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
|
||||||
@ -523,7 +509,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Coammand transfer is in progress
|
/// Coammand transfer is in progress
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
fn cmd_active() -> bool {
|
fn cmd_active() -> bool {
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
|
||||||
@ -535,7 +521,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
|
/// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
fn wait_idle() {
|
fn wait_idle() {
|
||||||
while Self::data_active() || Self::cmd_active() {}
|
while Self::data_active() || Self::cmd_active() {}
|
||||||
}
|
}
|
||||||
@ -851,7 +837,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Clear flags in interrupt clear register
|
/// Clear flags in interrupt clear register
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
fn clear_interrupt_flags() {
|
fn clear_interrupt_flags() {
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
regs.icr().write(|w| {
|
regs.icr().write(|w| {
|
||||||
@ -1166,8 +1152,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a data block.
|
#[inline(always)]
|
||||||
#[inline]
|
|
||||||
pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
|
pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
|
||||||
let card_capacity = self.card()?.card_type;
|
let card_capacity = self.card()?.card_type;
|
||||||
|
|
||||||
@ -1219,7 +1204,6 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a data block.
|
|
||||||
pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
|
pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
|
||||||
let card = self.card.as_mut().ok_or(Error::NoCard)?;
|
let card = self.card.as_mut().ok_or(Error::NoCard)?;
|
||||||
|
|
||||||
@ -1299,7 +1283,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
|
|||||||
///
|
///
|
||||||
/// Returns Error::NoCard if [`init_card`](#method.init_card)
|
/// Returns Error::NoCard if [`init_card`](#method.init_card)
|
||||||
/// has not previously succeeded
|
/// has not previously succeeded
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn card(&self) -> Result<&Card, Error> {
|
pub fn card(&self) -> Result<&Card, Error> {
|
||||||
self.card.as_ref().ok_or(Error::NoCard)
|
self.card.as_ref().ok_or(Error::NoCard)
|
||||||
}
|
}
|
||||||
@ -1435,9 +1419,7 @@ pub(crate) mod sealed {
|
|||||||
pub trait Pins<T: Instance> {}
|
pub trait Pins<T: Instance> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SDMMC instance trait.
|
|
||||||
pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
|
pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
|
||||||
|
|
||||||
pin_trait!(CkPin, Instance);
|
pin_trait!(CkPin, Instance);
|
||||||
pin_trait!(CmdPin, Instance);
|
pin_trait!(CmdPin, Instance);
|
||||||
pin_trait!(D0Pin, Instance);
|
pin_trait!(D0Pin, Instance);
|
||||||
@ -1452,10 +1434,7 @@ pin_trait!(D7Pin, Instance);
|
|||||||
#[cfg(sdmmc_v1)]
|
#[cfg(sdmmc_v1)]
|
||||||
dma_trait!(SdmmcDma, Instance);
|
dma_trait!(SdmmcDma, Instance);
|
||||||
|
|
||||||
/// DMA instance trait.
|
// SDMMCv2 uses internal DMA
|
||||||
///
|
|
||||||
/// This is only implemented for `NoDma`, since SDMMCv2 has DMA built-in, instead of
|
|
||||||
/// using ST's system-wide DMA peripheral.
|
|
||||||
#[cfg(sdmmc_v2)]
|
#[cfg(sdmmc_v2)]
|
||||||
pub trait SdmmcDma<T: Instance> {}
|
pub trait SdmmcDma<T: Instance> {}
|
||||||
#[cfg(sdmmc_v2)]
|
#[cfg(sdmmc_v2)]
|
||||||
@ -1538,3 +1517,53 @@ foreach_peripheral!(
|
|||||||
impl Instance for peripherals::$inst {}
|
impl Instance for peripherals::$inst {}
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "embedded-sdmmc")]
|
||||||
|
mod sdmmc_rs {
|
||||||
|
use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
impl<'d, T: Instance, Dma: SdmmcDma<T>> BlockDevice for Sdmmc<'d, T, Dma> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
async fn read(
|
||||||
|
&mut self,
|
||||||
|
blocks: &mut [Block],
|
||||||
|
start_block_idx: BlockIdx,
|
||||||
|
_reason: &str,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
let mut address = start_block_idx.0;
|
||||||
|
|
||||||
|
for block in blocks.iter_mut() {
|
||||||
|
let block: &mut [u8; 512] = &mut block.contents;
|
||||||
|
|
||||||
|
// NOTE(unsafe) Block uses align(4)
|
||||||
|
let block = unsafe { &mut *(block as *mut _ as *mut DataBlock) };
|
||||||
|
self.read_block(address, block).await?;
|
||||||
|
address += 1;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write(&mut self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
|
||||||
|
let mut address = start_block_idx.0;
|
||||||
|
|
||||||
|
for block in blocks.iter() {
|
||||||
|
let block: &[u8; 512] = &block.contents;
|
||||||
|
|
||||||
|
// NOTE(unsafe) DataBlock uses align 4
|
||||||
|
let block = unsafe { &*(block as *const _ as *const DataBlock) };
|
||||||
|
self.write_block(address, block).await?;
|
||||||
|
address += 1;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn num_blocks(&self) -> Result<BlockCount, Self::Error> {
|
||||||
|
let card = self.card()?;
|
||||||
|
let count = card.csd.block_count();
|
||||||
|
Ok(BlockCount(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,38 +16,27 @@ use crate::rcc::RccPeripheral;
|
|||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{peripherals, Peripheral};
|
||||||
|
|
||||||
/// SPI error.
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Invalid framing.
|
|
||||||
Framing,
|
Framing,
|
||||||
/// CRC error (only if hardware CRC checking is enabled).
|
|
||||||
Crc,
|
Crc,
|
||||||
/// Mode fault
|
|
||||||
ModeFault,
|
ModeFault,
|
||||||
/// Overrun.
|
|
||||||
Overrun,
|
Overrun,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SPI bit order
|
// TODO move upwards in the tree
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum BitOrder {
|
pub enum BitOrder {
|
||||||
/// Least significant bit first.
|
|
||||||
LsbFirst,
|
LsbFirst,
|
||||||
/// Most significant bit first.
|
|
||||||
MsbFirst,
|
MsbFirst,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SPI configuration.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// SPI mode.
|
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
/// Bit order.
|
|
||||||
pub bit_order: BitOrder,
|
pub bit_order: BitOrder,
|
||||||
/// Clock frequency.
|
|
||||||
pub frequency: Hertz,
|
pub frequency: Hertz,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +73,6 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SPI driver.
|
|
||||||
pub struct Spi<'d, T: Instance, Tx, Rx> {
|
pub struct Spi<'d, T: Instance, Tx, Rx> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
sck: Option<PeripheralRef<'d, AnyPin>>,
|
sck: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
@ -96,7 +84,6 @@ pub struct Spi<'d, T: Instance, Tx, Rx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||||
/// Create a new SPI driver.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
@ -131,7 +118,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI).
|
|
||||||
pub fn new_rxonly(
|
pub fn new_rxonly(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
@ -157,7 +143,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO).
|
|
||||||
pub fn new_txonly(
|
pub fn new_txonly(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
sck: impl Peripheral<P = impl SckPin<T>> + 'd,
|
||||||
@ -183,9 +168,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new SPI driver, in TX-only mode, without SCK pin.
|
|
||||||
///
|
|
||||||
/// This can be useful for bit-banging non-SPI protocols.
|
|
||||||
pub fn new_txonly_nosck(
|
pub fn new_txonly_nosck(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
|
||||||
@ -373,7 +355,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current SPI configuration.
|
|
||||||
pub fn get_current_config(&self) -> Config {
|
pub fn get_current_config(&self) -> Config {
|
||||||
#[cfg(any(spi_v1, spi_f1, spi_v2))]
|
#[cfg(any(spi_v1, spi_f1, spi_v2))]
|
||||||
let cfg = T::REGS.cr1().read();
|
let cfg = T::REGS.cr1().read();
|
||||||
@ -463,7 +444,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
self.current_word_size = word_size;
|
self.current_word_size = word_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SPI write, using DMA.
|
|
||||||
pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
|
pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Tx: TxDma<T>,
|
Tx: TxDma<T>,
|
||||||
@ -497,7 +477,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SPI read, using DMA.
|
|
||||||
pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Tx: TxDma<T>,
|
Tx: TxDma<T>,
|
||||||
@ -601,12 +580,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bidirectional transfer, using DMA.
|
|
||||||
///
|
|
||||||
/// This transfers both buffers at the same time, so it is NOT equivalent to `write` followed by `read`.
|
|
||||||
///
|
|
||||||
/// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
|
|
||||||
/// If `write` is shorter it is padded with zero bytes.
|
|
||||||
pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error>
|
pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Tx: TxDma<T>,
|
Tx: TxDma<T>,
|
||||||
@ -615,9 +588,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
self.transfer_inner(read, write).await
|
self.transfer_inner(read, write).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In-place bidirectional transfer, using DMA.
|
|
||||||
///
|
|
||||||
/// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
|
|
||||||
pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Tx: TxDma<T>,
|
Tx: TxDma<T>,
|
||||||
@ -626,7 +596,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
self.transfer_inner(data, data).await
|
self.transfer_inner(data, data).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking write.
|
|
||||||
pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
|
pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
|
||||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||||
flush_rx_fifo(T::REGS);
|
flush_rx_fifo(T::REGS);
|
||||||
@ -637,7 +606,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking read.
|
|
||||||
pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
|
pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
|
||||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||||
flush_rx_fifo(T::REGS);
|
flush_rx_fifo(T::REGS);
|
||||||
@ -648,9 +616,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking in-place bidirectional transfer.
|
|
||||||
///
|
|
||||||
/// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
|
|
||||||
pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
|
pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
|
||||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||||
flush_rx_fifo(T::REGS);
|
flush_rx_fifo(T::REGS);
|
||||||
@ -661,12 +626,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocking bidirectional transfer.
|
|
||||||
///
|
|
||||||
/// This transfers both buffers at the same time, so it is NOT equivalent to `write` followed by `read`.
|
|
||||||
///
|
|
||||||
/// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
|
|
||||||
/// If `write` is shorter it is padded with zero bytes.
|
|
||||||
pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
|
pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
|
||||||
T::REGS.cr1().modify(|w| w.set_spe(true));
|
T::REGS.cr1().modify(|w| w.set_spe(true));
|
||||||
flush_rx_fifo(T::REGS);
|
flush_rx_fifo(T::REGS);
|
||||||
@ -987,7 +946,6 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Word sizes usable for SPI.
|
|
||||||
pub trait Word: word::Word + sealed::Word {}
|
pub trait Word: word::Word + sealed::Word {}
|
||||||
|
|
||||||
macro_rules! impl_word {
|
macro_rules! impl_word {
|
||||||
@ -1067,9 +1025,7 @@ mod word_impl {
|
|||||||
impl_word!(u32, 32 - 1);
|
impl_word!(u32, 32 - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SPI instance trait.
|
|
||||||
pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
|
pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
|
||||||
|
|
||||||
pin_trait!(SckPin, Instance);
|
pin_trait!(SckPin, Instance);
|
||||||
pin_trait!(MosiPin, Instance);
|
pin_trait!(MosiPin, Instance);
|
||||||
pin_trait!(MisoPin, Instance);
|
pin_trait!(MisoPin, Instance);
|
||||||
|
@ -8,17 +8,14 @@ use core::ops::{Div, Mul};
|
|||||||
pub struct Hertz(pub u32);
|
pub struct Hertz(pub u32);
|
||||||
|
|
||||||
impl Hertz {
|
impl Hertz {
|
||||||
/// Create a `Hertz` from the given hertz.
|
|
||||||
pub const fn hz(hertz: u32) -> Self {
|
pub const fn hz(hertz: u32) -> Self {
|
||||||
Self(hertz)
|
Self(hertz)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `Hertz` from the given kilohertz.
|
|
||||||
pub const fn khz(kilohertz: u32) -> Self {
|
pub const fn khz(kilohertz: u32) -> Self {
|
||||||
Self(kilohertz * 1_000)
|
Self(kilohertz * 1_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `Hertz` from the given megahertz.
|
|
||||||
pub const fn mhz(megahertz: u32) -> Self {
|
pub const fn mhz(megahertz: u32) -> Self {
|
||||||
Self(megahertz * 1_000_000)
|
Self(megahertz * 1_000_000)
|
||||||
}
|
}
|
||||||
|
@ -13,19 +13,15 @@ use crate::gpio::{AnyPin, OutputType};
|
|||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
|
||||||
/// Complementary PWM pin wrapper.
|
pub struct ComplementaryPwmPin<'d, Perip, Channel> {
|
||||||
///
|
|
||||||
/// This wraps a pin to make it usable with PWM.
|
|
||||||
pub struct ComplementaryPwmPin<'d, T, C> {
|
|
||||||
_pin: PeripheralRef<'d, AnyPin>,
|
_pin: PeripheralRef<'d, AnyPin>,
|
||||||
phantom: PhantomData<(T, C)>,
|
phantom: PhantomData<(Perip, Channel)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! complementary_channel_impl {
|
macro_rules! complementary_channel_impl {
|
||||||
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
||||||
impl<'d, T: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> {
|
impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> {
|
||||||
#[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
|
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self {
|
||||||
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
|
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
pin.set_low();
|
pin.set_low();
|
||||||
@ -47,13 +43,11 @@ complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin);
|
|||||||
complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
|
complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
|
||||||
complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
|
complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
|
||||||
|
|
||||||
/// PWM driver with support for standard and complementary outputs.
|
|
||||||
pub struct ComplementaryPwm<'d, T> {
|
pub struct ComplementaryPwm<'d, T> {
|
||||||
inner: PeripheralRef<'d, T>,
|
inner: PeripheralRef<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
|
impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
|
||||||
/// Create a new complementary PWM driver.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tim: impl Peripheral<P = T> + 'd,
|
tim: impl Peripheral<P = T> + 'd,
|
||||||
_ch1: Option<PwmPin<'d, T, Ch1>>,
|
_ch1: Option<PwmPin<'d, T, Ch1>>,
|
||||||
@ -78,7 +72,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
|
|||||||
let mut this = Self { inner: tim };
|
let mut this = Self { inner: tim };
|
||||||
|
|
||||||
this.inner.set_counting_mode(counting_mode);
|
this.inner.set_counting_mode(counting_mode);
|
||||||
this.set_frequency(freq);
|
this.set_freq(freq);
|
||||||
this.inner.start();
|
this.inner.start();
|
||||||
|
|
||||||
this.inner.enable_outputs();
|
this.inner.enable_outputs();
|
||||||
@ -94,23 +88,17 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable the given channel.
|
|
||||||
pub fn enable(&mut self, channel: Channel) {
|
pub fn enable(&mut self, channel: Channel) {
|
||||||
self.inner.enable_channel(channel, true);
|
self.inner.enable_channel(channel, true);
|
||||||
self.inner.enable_complementary_channel(channel, true);
|
self.inner.enable_complementary_channel(channel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable the given channel.
|
|
||||||
pub fn disable(&mut self, channel: Channel) {
|
pub fn disable(&mut self, channel: Channel) {
|
||||||
self.inner.enable_complementary_channel(channel, false);
|
self.inner.enable_complementary_channel(channel, false);
|
||||||
self.inner.enable_channel(channel, false);
|
self.inner.enable_channel(channel, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set PWM frequency.
|
pub fn set_freq(&mut self, freq: Hertz) {
|
||||||
///
|
|
||||||
/// Note: when you call this, the max duty value changes, so you will have to
|
|
||||||
/// call `set_duty` on all channels with the duty calculated based on the new max duty.
|
|
||||||
pub fn set_frequency(&mut self, freq: Hertz) {
|
|
||||||
let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
|
let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
|
||||||
2u8
|
2u8
|
||||||
} else {
|
} else {
|
||||||
@ -119,22 +107,15 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
|
|||||||
self.inner.set_frequency(freq * multiplier);
|
self.inner.set_frequency(freq * multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get max duty value.
|
|
||||||
///
|
|
||||||
/// This value depends on the configured frequency and the timer's clock rate from RCC.
|
|
||||||
pub fn get_max_duty(&self) -> u16 {
|
pub fn get_max_duty(&self) -> u16 {
|
||||||
self.inner.get_max_compare_value() + 1
|
self.inner.get_max_compare_value() + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the duty for a given channel.
|
|
||||||
///
|
|
||||||
/// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
|
|
||||||
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
|
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
|
||||||
assert!(duty <= self.get_max_duty());
|
assert!(duty <= self.get_max_duty());
|
||||||
self.inner.set_compare_value(channel, duty)
|
self.inner.set_compare_value(channel, duty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the output polarity for a given channel.
|
|
||||||
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
||||||
self.inner.set_output_polarity(channel, polarity);
|
self.inner.set_output_polarity(channel, polarity);
|
||||||
self.inner.set_complementary_output_polarity(channel, polarity);
|
self.inner.set_complementary_output_polarity(channel, polarity);
|
||||||
|
@ -17,27 +17,17 @@ pub mod low_level {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Basic 16-bit timer instance.
|
use super::*;
|
||||||
pub trait Basic16bitInstance: RccPeripheral {
|
pub trait Basic16bitInstance: RccPeripheral {
|
||||||
/// Interrupt for this timer.
|
|
||||||
type Interrupt: interrupt::typelevel::Interrupt;
|
type Interrupt: interrupt::typelevel::Interrupt;
|
||||||
|
|
||||||
/// Get access to the basic 16bit timer registers.
|
|
||||||
///
|
|
||||||
/// Note: This works even if the timer is more capable, because registers
|
|
||||||
/// for the less capable timers are a subset. This allows writing a driver
|
|
||||||
/// for a given set of capabilities, and having it transparently work with
|
|
||||||
/// more capable timers.
|
|
||||||
fn regs() -> crate::pac::timer::TimBasic;
|
fn regs() -> crate::pac::timer::TimBasic;
|
||||||
|
|
||||||
/// Start the timer.
|
|
||||||
fn start(&mut self) {
|
fn start(&mut self) {
|
||||||
Self::regs().cr1().modify(|r| r.set_cen(true));
|
Self::regs().cr1().modify(|r| r.set_cen(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stop the timer.
|
|
||||||
fn stop(&mut self) {
|
fn stop(&mut self) {
|
||||||
Self::regs().cr1().modify(|r| r.set_cen(false));
|
Self::regs().cr1().modify(|r| r.set_cen(false));
|
||||||
}
|
}
|
||||||
@ -73,9 +63,6 @@ pub(crate) mod sealed {
|
|||||||
regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
|
regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear update interrupt.
|
|
||||||
///
|
|
||||||
/// Returns whether the update interrupt flag was set.
|
|
||||||
fn clear_update_interrupt(&mut self) -> bool {
|
fn clear_update_interrupt(&mut self) -> bool {
|
||||||
let regs = Self::regs();
|
let regs = Self::regs();
|
||||||
let sr = regs.sr().read();
|
let sr = regs.sr().read();
|
||||||
@ -89,17 +76,14 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable/disable the update interrupt.
|
|
||||||
fn enable_update_interrupt(&mut self, enable: bool) {
|
fn enable_update_interrupt(&mut self, enable: bool) {
|
||||||
Self::regs().dier().write(|r| r.set_uie(enable));
|
Self::regs().dier().write(|r| r.set_uie(enable));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable/disable autoreload preload.
|
|
||||||
fn set_autoreload_preload(&mut self, enable: bool) {
|
fn set_autoreload_preload(&mut self, enable: bool) {
|
||||||
Self::regs().cr1().modify(|r| r.set_arpe(enable));
|
Self::regs().cr1().modify(|r| r.set_arpe(enable));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the timer frequency.
|
|
||||||
fn get_frequency(&self) -> Hertz {
|
fn get_frequency(&self) -> Hertz {
|
||||||
let timer_f = Self::frequency();
|
let timer_f = Self::frequency();
|
||||||
|
|
||||||
@ -111,17 +95,9 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gneral-purpose 16-bit timer instance.
|
|
||||||
pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
|
pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
|
||||||
/// Get access to the general purpose 16bit timer registers.
|
|
||||||
///
|
|
||||||
/// Note: This works even if the timer is more capable, because registers
|
|
||||||
/// for the less capable timers are a subset. This allows writing a driver
|
|
||||||
/// for a given set of capabilities, and having it transparently work with
|
|
||||||
/// more capable timers.
|
|
||||||
fn regs_gp16() -> crate::pac::timer::TimGp16;
|
fn regs_gp16() -> crate::pac::timer::TimGp16;
|
||||||
|
|
||||||
/// Set counting mode.
|
|
||||||
fn set_counting_mode(&mut self, mode: CountingMode) {
|
fn set_counting_mode(&mut self, mode: CountingMode) {
|
||||||
let (cms, dir) = mode.into();
|
let (cms, dir) = mode.into();
|
||||||
|
|
||||||
@ -134,29 +110,19 @@ pub(crate) mod sealed {
|
|||||||
Self::regs_gp16().cr1().modify(|r| r.set_cms(cms))
|
Self::regs_gp16().cr1().modify(|r| r.set_cms(cms))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get counting mode.
|
|
||||||
fn get_counting_mode(&self) -> CountingMode {
|
fn get_counting_mode(&self) -> CountingMode {
|
||||||
let cr1 = Self::regs_gp16().cr1().read();
|
let cr1 = Self::regs_gp16().cr1().read();
|
||||||
(cr1.cms(), cr1.dir()).into()
|
(cr1.cms(), cr1.dir()).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set clock divider.
|
|
||||||
fn set_clock_division(&mut self, ckd: vals::Ckd) {
|
fn set_clock_division(&mut self, ckd: vals::Ckd) {
|
||||||
Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
|
Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gneral-purpose 32-bit timer instance.
|
|
||||||
pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
|
pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
|
||||||
/// Get access to the general purpose 32bit timer registers.
|
|
||||||
///
|
|
||||||
/// Note: This works even if the timer is more capable, because registers
|
|
||||||
/// for the less capable timers are a subset. This allows writing a driver
|
|
||||||
/// for a given set of capabilities, and having it transparently work with
|
|
||||||
/// more capable timers.
|
|
||||||
fn regs_gp32() -> crate::pac::timer::TimGp32;
|
fn regs_gp32() -> crate::pac::timer::TimGp32;
|
||||||
|
|
||||||
/// Set timer frequency.
|
|
||||||
fn set_frequency(&mut self, frequency: Hertz) {
|
fn set_frequency(&mut self, frequency: Hertz) {
|
||||||
let f = frequency.0;
|
let f = frequency.0;
|
||||||
assert!(f > 0);
|
assert!(f > 0);
|
||||||
@ -174,7 +140,6 @@ pub(crate) mod sealed {
|
|||||||
regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
|
regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get timer frequency.
|
|
||||||
fn get_frequency(&self) -> Hertz {
|
fn get_frequency(&self) -> Hertz {
|
||||||
let timer_f = Self::frequency();
|
let timer_f = Self::frequency();
|
||||||
|
|
||||||
@ -186,177 +151,141 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advanced control timer instance.
|
|
||||||
pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
|
pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
|
||||||
/// Get access to the advanced timer registers.
|
|
||||||
fn regs_advanced() -> crate::pac::timer::TimAdv;
|
fn regs_advanced() -> crate::pac::timer::TimAdv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Capture/Compare 16-bit timer instance.
|
|
||||||
pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
|
pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
|
||||||
/// Set input capture filter.
|
|
||||||
fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
|
fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
|
||||||
let raw_channel = channel.index();
|
let raw_channel = channel.raw();
|
||||||
Self::regs_gp16()
|
Self::regs_gp16()
|
||||||
.ccmr_input(raw_channel / 2)
|
.ccmr_input(raw_channel / 2)
|
||||||
.modify(|r| r.set_icf(raw_channel % 2, icf));
|
.modify(|r| r.set_icf(raw_channel % 2, icf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear input interrupt.
|
|
||||||
fn clear_input_interrupt(&mut self, channel: Channel) {
|
fn clear_input_interrupt(&mut self, channel: Channel) {
|
||||||
Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
|
Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.raw(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable input interrupt.
|
|
||||||
fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
|
fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
|
||||||
Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
|
Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.raw(), enable));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set input capture prescaler.
|
|
||||||
fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
|
fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
|
||||||
let raw_channel = channel.index();
|
let raw_channel = channel.raw();
|
||||||
Self::regs_gp16()
|
Self::regs_gp16()
|
||||||
.ccmr_input(raw_channel / 2)
|
.ccmr_input(raw_channel / 2)
|
||||||
.modify(|r| r.set_icpsc(raw_channel % 2, factor));
|
.modify(|r| r.set_icpsc(raw_channel % 2, factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set input TI selection.
|
|
||||||
fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
|
fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
|
||||||
let raw_channel = channel.index();
|
let raw_channel = channel.raw();
|
||||||
Self::regs_gp16()
|
Self::regs_gp16()
|
||||||
.ccmr_input(raw_channel / 2)
|
.ccmr_input(raw_channel / 2)
|
||||||
.modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
|
.modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set input capture mode.
|
|
||||||
fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
|
fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
|
||||||
Self::regs_gp16().ccer().modify(|r| match mode {
|
Self::regs_gp16().ccer().modify(|r| match mode {
|
||||||
InputCaptureMode::Rising => {
|
InputCaptureMode::Rising => {
|
||||||
r.set_ccnp(channel.index(), false);
|
r.set_ccnp(channel.raw(), false);
|
||||||
r.set_ccp(channel.index(), false);
|
r.set_ccp(channel.raw(), false);
|
||||||
}
|
}
|
||||||
InputCaptureMode::Falling => {
|
InputCaptureMode::Falling => {
|
||||||
r.set_ccnp(channel.index(), false);
|
r.set_ccnp(channel.raw(), false);
|
||||||
r.set_ccp(channel.index(), true);
|
r.set_ccp(channel.raw(), true);
|
||||||
}
|
}
|
||||||
InputCaptureMode::BothEdges => {
|
InputCaptureMode::BothEdges => {
|
||||||
r.set_ccnp(channel.index(), true);
|
r.set_ccnp(channel.raw(), true);
|
||||||
r.set_ccp(channel.index(), true);
|
r.set_ccp(channel.raw(), true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable timer outputs.
|
|
||||||
fn enable_outputs(&mut self);
|
fn enable_outputs(&mut self);
|
||||||
|
|
||||||
/// Set output compare mode.
|
|
||||||
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
|
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
|
||||||
let r = Self::regs_gp16();
|
let r = Self::regs_gp16();
|
||||||
let raw_channel: usize = channel.index();
|
let raw_channel: usize = channel.raw();
|
||||||
r.ccmr_output(raw_channel / 2)
|
r.ccmr_output(raw_channel / 2)
|
||||||
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
|
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set output polarity.
|
|
||||||
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
||||||
Self::regs_gp16()
|
Self::regs_gp16()
|
||||||
.ccer()
|
.ccer()
|
||||||
.modify(|w| w.set_ccp(channel.index(), polarity.into()));
|
.modify(|w| w.set_ccp(channel.raw(), polarity.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable/disable a channel.
|
|
||||||
fn enable_channel(&mut self, channel: Channel, enable: bool) {
|
fn enable_channel(&mut self, channel: Channel, enable: bool) {
|
||||||
Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
|
Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.raw(), enable));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set compare value for a channel.
|
|
||||||
fn set_compare_value(&mut self, channel: Channel, value: u16) {
|
fn set_compare_value(&mut self, channel: Channel, value: u16) {
|
||||||
Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
|
Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get capture value for a channel.
|
|
||||||
fn get_capture_value(&mut self, channel: Channel) -> u16 {
|
fn get_capture_value(&mut self, channel: Channel) -> u16 {
|
||||||
Self::regs_gp16().ccr(channel.index()).read().ccr()
|
Self::regs_gp16().ccr(channel.raw()).read().ccr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
|
|
||||||
fn get_max_compare_value(&self) -> u16 {
|
fn get_max_compare_value(&self) -> u16 {
|
||||||
Self::regs_gp16().arr().read().arr()
|
Self::regs_gp16().arr().read().arr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get compare value for a channel.
|
|
||||||
fn get_compare_value(&self, channel: Channel) -> u16 {
|
fn get_compare_value(&self, channel: Channel) -> u16 {
|
||||||
Self::regs_gp16().ccr(channel.index()).read().ccr()
|
Self::regs_gp16().ccr(channel.raw()).read().ccr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Capture/Compare 16-bit timer instance with complementary pin support.
|
|
||||||
pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance {
|
pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance {
|
||||||
/// Set complementary output polarity.
|
|
||||||
fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
||||||
Self::regs_advanced()
|
Self::regs_advanced()
|
||||||
.ccer()
|
.ccer()
|
||||||
.modify(|w| w.set_ccnp(channel.index(), polarity.into()));
|
.modify(|w| w.set_ccnp(channel.raw(), polarity.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set clock divider for the dead time.
|
|
||||||
fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
|
fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
|
||||||
Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
|
Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set dead time, as a fraction of the max duty value.
|
|
||||||
fn set_dead_time_value(&mut self, value: u8) {
|
fn set_dead_time_value(&mut self, value: u8) {
|
||||||
Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
|
Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable/disable a complementary channel.
|
|
||||||
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
|
fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
|
||||||
Self::regs_advanced()
|
Self::regs_advanced()
|
||||||
.ccer()
|
.ccer()
|
||||||
.modify(|w| w.set_ccne(channel.index(), enable));
|
.modify(|w| w.set_ccne(channel.raw(), enable));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Capture/Compare 32-bit timer instance.
|
|
||||||
pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance {
|
pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance {
|
||||||
/// Set comapre value for a channel.
|
|
||||||
fn set_compare_value(&mut self, channel: Channel, value: u32) {
|
fn set_compare_value(&mut self, channel: Channel, value: u32) {
|
||||||
Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value));
|
Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get capture value for a channel.
|
|
||||||
fn get_capture_value(&mut self, channel: Channel) -> u32 {
|
fn get_capture_value(&mut self, channel: Channel) -> u32 {
|
||||||
Self::regs_gp32().ccr(channel.index()).read().ccr()
|
Self::regs_gp32().ccr(channel.raw()).read().ccr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
|
|
||||||
fn get_max_compare_value(&self) -> u32 {
|
fn get_max_compare_value(&self) -> u32 {
|
||||||
Self::regs_gp32().arr().read().arr()
|
Self::regs_gp32().arr().read().arr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get compare value for a channel.
|
|
||||||
fn get_compare_value(&self, channel: Channel) -> u32 {
|
fn get_compare_value(&self, channel: Channel) -> u32 {
|
||||||
Self::regs_gp32().ccr(channel.index()).read().ccr()
|
Self::regs_gp32().ccr(channel.raw()).read().ccr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Timer channel.
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Channel {
|
pub enum Channel {
|
||||||
/// Channel 1.
|
|
||||||
Ch1,
|
Ch1,
|
||||||
/// Channel 2.
|
|
||||||
Ch2,
|
Ch2,
|
||||||
/// Channel 3.
|
|
||||||
Ch3,
|
Ch3,
|
||||||
/// Channel 4.
|
|
||||||
Ch4,
|
Ch4,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
/// Get the channel index (0..3)
|
pub fn raw(&self) -> usize {
|
||||||
pub fn index(&self) -> usize {
|
|
||||||
match self {
|
match self {
|
||||||
Channel::Ch1 => 0,
|
Channel::Ch1 => 0,
|
||||||
Channel::Ch2 => 1,
|
Channel::Ch2 => 1,
|
||||||
@ -366,25 +295,17 @@ impl Channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Input capture mode.
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum InputCaptureMode {
|
pub enum InputCaptureMode {
|
||||||
/// Rising edge only.
|
|
||||||
Rising,
|
Rising,
|
||||||
/// Falling edge only.
|
|
||||||
Falling,
|
Falling,
|
||||||
/// Both rising or falling edges.
|
|
||||||
BothEdges,
|
BothEdges,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Input TI selection.
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum InputTISelection {
|
pub enum InputTISelection {
|
||||||
/// Normal
|
|
||||||
Normal,
|
Normal,
|
||||||
/// Alternate
|
|
||||||
Alternate,
|
Alternate,
|
||||||
/// TRC
|
|
||||||
TRC,
|
TRC,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +319,6 @@ impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Timer counting mode.
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub enum CountingMode {
|
pub enum CountingMode {
|
||||||
@ -425,7 +345,6 @@ pub enum CountingMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CountingMode {
|
impl CountingMode {
|
||||||
/// Return whether this mode is edge-aligned (up or down).
|
|
||||||
pub fn is_edge_aligned(&self) -> bool {
|
pub fn is_edge_aligned(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown => true,
|
CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown => true,
|
||||||
@ -433,7 +352,6 @@ impl CountingMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether this mode is center-aligned.
|
|
||||||
pub fn is_center_aligned(&self) -> bool {
|
pub fn is_center_aligned(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CountingMode::CenterAlignedDownInterrupts
|
CountingMode::CenterAlignedDownInterrupts
|
||||||
@ -468,34 +386,16 @@ impl From<(vals::Cms, vals::Dir)> for CountingMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Output compare mode.
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum OutputCompareMode {
|
pub enum OutputCompareMode {
|
||||||
/// The comparison between the output compare register TIMx_CCRx and
|
|
||||||
/// the counter TIMx_CNT has no effect on the outputs.
|
|
||||||
/// (this mode is used to generate a timing base).
|
|
||||||
Frozen,
|
Frozen,
|
||||||
/// Set channel to active level on match. OCxREF signal is forced high when the
|
|
||||||
/// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
|
|
||||||
ActiveOnMatch,
|
ActiveOnMatch,
|
||||||
/// Set channel to inactive level on match. OCxREF signal is forced low when the
|
|
||||||
/// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
|
|
||||||
InactiveOnMatch,
|
InactiveOnMatch,
|
||||||
/// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx.
|
|
||||||
Toggle,
|
Toggle,
|
||||||
/// Force inactive level - OCxREF is forced low.
|
|
||||||
ForceInactive,
|
ForceInactive,
|
||||||
/// Force active level - OCxREF is forced high.
|
|
||||||
ForceActive,
|
ForceActive,
|
||||||
/// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRx
|
|
||||||
/// else inactive. In downcounting, channel is inactive (OCxREF=0) as long as
|
|
||||||
/// TIMx_CNT>TIMx_CCRx else active (OCxREF=1).
|
|
||||||
PwmMode1,
|
PwmMode1,
|
||||||
/// PWM mode 2 - In upcounting, channel is inactive as long as
|
|
||||||
/// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as
|
|
||||||
/// TIMx_CNT>TIMx_CCRx else inactive.
|
|
||||||
PwmMode2,
|
PwmMode2,
|
||||||
// TODO: there's more modes here depending on the chip family.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
|
impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
|
||||||
@ -513,12 +413,9 @@ impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Timer output pin polarity.
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum OutputPolarity {
|
pub enum OutputPolarity {
|
||||||
/// Active high (higher duty value makes the pin spend more time high).
|
|
||||||
ActiveHigh,
|
ActiveHigh,
|
||||||
/// Active low (higher duty value makes the pin spend more time low).
|
|
||||||
ActiveLow,
|
ActiveLow,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,31 +428,24 @@ impl From<OutputPolarity> for bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Basic 16-bit timer instance.
|
|
||||||
pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
|
pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
|
||||||
|
|
||||||
/// Gneral-purpose 16-bit timer instance.
|
|
||||||
pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {}
|
pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {}
|
||||||
|
|
||||||
/// Gneral-purpose 32-bit timer instance.
|
|
||||||
pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {}
|
pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {}
|
||||||
|
|
||||||
/// Advanced control timer instance.
|
|
||||||
pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {}
|
pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {}
|
||||||
|
|
||||||
/// Capture/Compare 16-bit timer instance.
|
|
||||||
pub trait CaptureCompare16bitInstance:
|
pub trait CaptureCompare16bitInstance:
|
||||||
sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static
|
sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Capture/Compare 16-bit timer instance with complementary pin support.
|
|
||||||
pub trait ComplementaryCaptureCompare16bitInstance:
|
pub trait ComplementaryCaptureCompare16bitInstance:
|
||||||
sealed::ComplementaryCaptureCompare16bitInstance + AdvancedControlInstance + 'static
|
sealed::ComplementaryCaptureCompare16bitInstance + AdvancedControlInstance + 'static
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Capture/Compare 32-bit timer instance.
|
|
||||||
pub trait CaptureCompare32bitInstance:
|
pub trait CaptureCompare32bitInstance:
|
||||||
sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static
|
sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static
|
||||||
{
|
{
|
||||||
|
@ -9,30 +9,23 @@ use crate::gpio::sealed::AFType;
|
|||||||
use crate::gpio::AnyPin;
|
use crate::gpio::AnyPin;
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
|
||||||
/// Counting direction
|
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
/// Counting up.
|
|
||||||
Upcounting,
|
Upcounting,
|
||||||
/// Counting down.
|
|
||||||
Downcounting,
|
Downcounting,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel 1 marker type.
|
pub struct Ch1;
|
||||||
pub enum Ch1 {}
|
pub struct Ch2;
|
||||||
/// Channel 2 marker type.
|
|
||||||
pub enum Ch2 {}
|
|
||||||
|
|
||||||
/// Wrapper for using a pin with QEI.
|
pub struct QeiPin<'d, Perip, Channel> {
|
||||||
pub struct QeiPin<'d, T, Channel> {
|
|
||||||
_pin: PeripheralRef<'d, AnyPin>,
|
_pin: PeripheralRef<'d, AnyPin>,
|
||||||
phantom: PhantomData<(T, Channel)>,
|
phantom: PhantomData<(Perip, Channel)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! channel_impl {
|
macro_rules! channel_impl {
|
||||||
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
||||||
impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> {
|
impl<'d, Perip: CaptureCompare16bitInstance> QeiPin<'d, Perip, $channel> {
|
||||||
#[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
|
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
|
||||||
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self {
|
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
pin.set_low();
|
pin.set_low();
|
||||||
@ -52,13 +45,11 @@ macro_rules! channel_impl {
|
|||||||
channel_impl!(new_ch1, Ch1, Channel1Pin);
|
channel_impl!(new_ch1, Ch1, Channel1Pin);
|
||||||
channel_impl!(new_ch2, Ch2, Channel2Pin);
|
channel_impl!(new_ch2, Ch2, Channel2Pin);
|
||||||
|
|
||||||
/// Quadrature decoder driver.
|
|
||||||
pub struct Qei<'d, T> {
|
pub struct Qei<'d, T> {
|
||||||
_inner: PeripheralRef<'d, T>,
|
_inner: PeripheralRef<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
|
impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
|
||||||
/// Create a new quadrature decoder driver.
|
|
||||||
pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
|
pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
|
||||||
Self::new_inner(tim)
|
Self::new_inner(tim)
|
||||||
}
|
}
|
||||||
@ -93,7 +84,6 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
|
|||||||
Self { _inner: tim }
|
Self { _inner: tim }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get direction.
|
|
||||||
pub fn read_direction(&self) -> Direction {
|
pub fn read_direction(&self) -> Direction {
|
||||||
match T::regs_gp16().cr1().read().dir() {
|
match T::regs_gp16().cr1().read().dir() {
|
||||||
vals::Dir::DOWN => Direction::Downcounting,
|
vals::Dir::DOWN => Direction::Downcounting,
|
||||||
@ -101,7 +91,6 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get count.
|
|
||||||
pub fn count(&self) -> u16 {
|
pub fn count(&self) -> u16 {
|
||||||
T::regs_gp16().cnt().read().cnt()
|
T::regs_gp16().cnt().read().cnt()
|
||||||
}
|
}
|
||||||
|
@ -11,28 +11,20 @@ use crate::gpio::{AnyPin, OutputType};
|
|||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
|
||||||
/// Channel 1 marker type.
|
pub struct Ch1;
|
||||||
pub enum Ch1 {}
|
pub struct Ch2;
|
||||||
/// Channel 2 marker type.
|
pub struct Ch3;
|
||||||
pub enum Ch2 {}
|
pub struct Ch4;
|
||||||
/// Channel 3 marker type.
|
|
||||||
pub enum Ch3 {}
|
|
||||||
/// Channel 4 marker type.
|
|
||||||
pub enum Ch4 {}
|
|
||||||
|
|
||||||
/// PWM pin wrapper.
|
pub struct PwmPin<'d, Perip, Channel> {
|
||||||
///
|
|
||||||
/// This wraps a pin to make it usable with PWM.
|
|
||||||
pub struct PwmPin<'d, T, C> {
|
|
||||||
_pin: PeripheralRef<'d, AnyPin>,
|
_pin: PeripheralRef<'d, AnyPin>,
|
||||||
phantom: PhantomData<(T, C)>,
|
phantom: PhantomData<(Perip, Channel)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! channel_impl {
|
macro_rules! channel_impl {
|
||||||
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
||||||
impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> {
|
impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> {
|
||||||
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
|
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self {
|
||||||
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
|
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
pin.set_low();
|
pin.set_low();
|
||||||
@ -54,13 +46,11 @@ channel_impl!(new_ch2, Ch2, Channel2Pin);
|
|||||||
channel_impl!(new_ch3, Ch3, Channel3Pin);
|
channel_impl!(new_ch3, Ch3, Channel3Pin);
|
||||||
channel_impl!(new_ch4, Ch4, Channel4Pin);
|
channel_impl!(new_ch4, Ch4, Channel4Pin);
|
||||||
|
|
||||||
/// Simple PWM driver.
|
|
||||||
pub struct SimplePwm<'d, T> {
|
pub struct SimplePwm<'d, T> {
|
||||||
inner: PeripheralRef<'d, T>,
|
inner: PeripheralRef<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
||||||
/// Create a new simple PWM driver.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tim: impl Peripheral<P = T> + 'd,
|
tim: impl Peripheral<P = T> + 'd,
|
||||||
_ch1: Option<PwmPin<'d, T, Ch1>>,
|
_ch1: Option<PwmPin<'d, T, Ch1>>,
|
||||||
@ -81,7 +71,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
|||||||
let mut this = Self { inner: tim };
|
let mut this = Self { inner: tim };
|
||||||
|
|
||||||
this.inner.set_counting_mode(counting_mode);
|
this.inner.set_counting_mode(counting_mode);
|
||||||
this.set_frequency(freq);
|
this.set_freq(freq);
|
||||||
this.inner.start();
|
this.inner.start();
|
||||||
|
|
||||||
this.inner.enable_outputs();
|
this.inner.enable_outputs();
|
||||||
@ -97,21 +87,15 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable the given channel.
|
|
||||||
pub fn enable(&mut self, channel: Channel) {
|
pub fn enable(&mut self, channel: Channel) {
|
||||||
self.inner.enable_channel(channel, true);
|
self.inner.enable_channel(channel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable the given channel.
|
|
||||||
pub fn disable(&mut self, channel: Channel) {
|
pub fn disable(&mut self, channel: Channel) {
|
||||||
self.inner.enable_channel(channel, false);
|
self.inner.enable_channel(channel, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set PWM frequency.
|
pub fn set_freq(&mut self, freq: Hertz) {
|
||||||
///
|
|
||||||
/// Note: when you call this, the max duty value changes, so you will have to
|
|
||||||
/// call `set_duty` on all channels with the duty calculated based on the new max duty.
|
|
||||||
pub fn set_frequency(&mut self, freq: Hertz) {
|
|
||||||
let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
|
let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
|
||||||
2u8
|
2u8
|
||||||
} else {
|
} else {
|
||||||
@ -120,22 +104,15 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
|||||||
self.inner.set_frequency(freq * multiplier);
|
self.inner.set_frequency(freq * multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get max duty value.
|
|
||||||
///
|
|
||||||
/// This value depends on the configured frequency and the timer's clock rate from RCC.
|
|
||||||
pub fn get_max_duty(&self) -> u16 {
|
pub fn get_max_duty(&self) -> u16 {
|
||||||
self.inner.get_max_compare_value() + 1
|
self.inner.get_max_compare_value() + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the duty for a given channel.
|
|
||||||
///
|
|
||||||
/// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
|
|
||||||
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
|
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
|
||||||
assert!(duty <= self.get_max_duty());
|
assert!(duty <= self.get_max_duty());
|
||||||
self.inner.set_compare_value(channel, duty)
|
self.inner.set_compare_value(channel, duty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the output polarity for a given channel.
|
|
||||||
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
|
||||||
self.inner.set_output_polarity(channel, polarity);
|
self.inner.set_output_polarity(channel, polarity);
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,6 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Buffered UART State
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
rx_waker: AtomicWaker,
|
rx_waker: AtomicWaker,
|
||||||
rx_buf: RingBuffer,
|
rx_buf: RingBuffer,
|
||||||
@ -92,7 +91,6 @@ pub struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
/// Create new state
|
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
rx_buf: RingBuffer::new(),
|
rx_buf: RingBuffer::new(),
|
||||||
@ -103,18 +101,15 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bidirectional buffered UART
|
|
||||||
pub struct BufferedUart<'d, T: BasicInstance> {
|
pub struct BufferedUart<'d, T: BasicInstance> {
|
||||||
rx: BufferedUartRx<'d, T>,
|
rx: BufferedUartRx<'d, T>,
|
||||||
tx: BufferedUartTx<'d, T>,
|
tx: BufferedUartTx<'d, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tx-only buffered UART
|
|
||||||
pub struct BufferedUartTx<'d, T: BasicInstance> {
|
pub struct BufferedUartTx<'d, T: BasicInstance> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rx-only buffered UART
|
|
||||||
pub struct BufferedUartRx<'d, T: BasicInstance> {
|
pub struct BufferedUartRx<'d, T: BasicInstance> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
@ -147,7 +142,6 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||||
/// Create a new bidirectional buffered UART driver
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -164,7 +158,6 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins
|
|
||||||
pub fn new_with_rtscts(
|
pub fn new_with_rtscts(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -192,7 +185,6 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new bidirectional buffered UART driver with a driver-enable pin
|
|
||||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||||
pub fn new_with_de(
|
pub fn new_with_de(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
@ -254,12 +246,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split the driver into a Tx and Rx part (useful for sending to separate tasks)
|
|
||||||
pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
|
pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
|
||||||
(self.tx, self.rx)
|
(self.tx, self.rx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconfigure the driver
|
|
||||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
reconfigure::<T>(config)?;
|
reconfigure::<T>(config)?;
|
||||||
|
|
||||||
@ -347,7 +337,6 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconfigure the driver
|
|
||||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
reconfigure::<T>(config)?;
|
reconfigure::<T>(config)?;
|
||||||
|
|
||||||
@ -429,7 +418,6 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconfigure the driver
|
|
||||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
reconfigure::<T>(config)?;
|
reconfigure::<T>(config)?;
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
//! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART)
|
//! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART)
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
@ -78,29 +77,21 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
|
|||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
/// Number of data bits
|
|
||||||
pub enum DataBits {
|
pub enum DataBits {
|
||||||
/// 8 Data Bits
|
|
||||||
DataBits8,
|
DataBits8,
|
||||||
/// 9 Data Bits
|
|
||||||
DataBits9,
|
DataBits9,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
/// Parity
|
|
||||||
pub enum Parity {
|
pub enum Parity {
|
||||||
/// No parity
|
|
||||||
ParityNone,
|
ParityNone,
|
||||||
/// Even Parity
|
|
||||||
ParityEven,
|
ParityEven,
|
||||||
/// Odd Parity
|
|
||||||
ParityOdd,
|
ParityOdd,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
/// Number of stop bits
|
|
||||||
pub enum StopBits {
|
pub enum StopBits {
|
||||||
#[doc = "1 stop bit"]
|
#[doc = "1 stop bit"]
|
||||||
STOP1,
|
STOP1,
|
||||||
@ -115,37 +106,26 @@ pub enum StopBits {
|
|||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
/// Config Error
|
|
||||||
pub enum ConfigError {
|
pub enum ConfigError {
|
||||||
/// Baudrate too low
|
|
||||||
BaudrateTooLow,
|
BaudrateTooLow,
|
||||||
/// Baudrate too high
|
|
||||||
BaudrateTooHigh,
|
BaudrateTooHigh,
|
||||||
/// Rx or Tx not enabled
|
|
||||||
RxOrTxNotEnabled,
|
RxOrTxNotEnabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
/// Config
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Baud rate
|
|
||||||
pub baudrate: u32,
|
pub baudrate: u32,
|
||||||
/// Number of data bits
|
|
||||||
pub data_bits: DataBits,
|
pub data_bits: DataBits,
|
||||||
/// Number of stop bits
|
|
||||||
pub stop_bits: StopBits,
|
pub stop_bits: StopBits,
|
||||||
/// Parity type
|
|
||||||
pub parity: Parity,
|
pub parity: Parity,
|
||||||
|
/// if true, on read-like method, if there is a latent error pending,
|
||||||
/// If true: on a read-like method, if there is a latent error pending,
|
/// read will abort, the error reported and cleared
|
||||||
/// the read will abort and the error will be reported and cleared
|
/// if false, the error is ignored and cleared
|
||||||
///
|
|
||||||
/// If false: the error is ignored and cleared
|
|
||||||
pub detect_previous_overrun: bool,
|
pub detect_previous_overrun: bool,
|
||||||
|
|
||||||
/// Set this to true if the line is considered noise free.
|
/// Set this to true if the line is considered noise free.
|
||||||
/// This will increase the receiver’s tolerance to clock deviations,
|
/// This will increase the receivers tolerance to clock deviations,
|
||||||
/// but will effectively disable noise detection.
|
/// but will effectively disable noise detection.
|
||||||
#[cfg(not(usart_v1))]
|
#[cfg(not(usart_v1))]
|
||||||
pub assume_noise_free: bool,
|
pub assume_noise_free: bool,
|
||||||
@ -161,10 +141,6 @@ pub struct Config {
|
|||||||
/// Set this to true to invert RX pin signal values (V<sub>DD</sub> =0/mark, Gnd = 1/idle).
|
/// Set this to true to invert RX pin signal values (V<sub>DD</sub> =0/mark, Gnd = 1/idle).
|
||||||
#[cfg(any(usart_v3, usart_v4))]
|
#[cfg(any(usart_v3, usart_v4))]
|
||||||
pub invert_rx: bool,
|
pub invert_rx: bool,
|
||||||
|
|
||||||
/// enable single wire half duplex communication. Only the tx pin is used. Needs an external
|
|
||||||
/// pull up
|
|
||||||
pub half_duplex: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -184,7 +160,6 @@ impl Default for Config {
|
|||||||
invert_tx: false,
|
invert_tx: false,
|
||||||
#[cfg(any(usart_v3, usart_v4))]
|
#[cfg(any(usart_v3, usart_v4))]
|
||||||
invert_rx: false,
|
invert_rx: false,
|
||||||
half_duplex: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,7 +188,6 @@ enum ReadCompletionEvent {
|
|||||||
Idle(usize),
|
Idle(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bidirectional UART Driver
|
|
||||||
pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
|
pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
|
||||||
tx: UartTx<'d, T, TxDma>,
|
tx: UartTx<'d, T, TxDma>,
|
||||||
rx: UartRx<'d, T, RxDma>,
|
rx: UartRx<'d, T, RxDma>,
|
||||||
@ -229,7 +203,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tx-only UART Driver
|
|
||||||
pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
|
pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
tx_dma: PeripheralRef<'d, TxDma>,
|
tx_dma: PeripheralRef<'d, TxDma>,
|
||||||
@ -244,7 +217,6 @@ impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rx-only UART Driver
|
|
||||||
pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
|
pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
rx_dma: PeripheralRef<'d, RxDma>,
|
rx_dma: PeripheralRef<'d, RxDma>,
|
||||||
@ -275,7 +247,6 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
|||||||
Self::new_inner(peri, tx, tx_dma, config)
|
Self::new_inner(peri, tx, tx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new tx-only UART with a clear-to-send pin
|
|
||||||
pub fn new_with_cts(
|
pub fn new_with_cts(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
@ -317,12 +288,10 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconfigure the driver
|
|
||||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
reconfigure::<T>(config)
|
reconfigure::<T>(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initiate an asynchronous UART write
|
|
||||||
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
|
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
TxDma: crate::usart::TxDma<T>,
|
TxDma: crate::usart::TxDma<T>,
|
||||||
@ -339,7 +308,6 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform a blocking UART write
|
|
||||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
for &b in buffer {
|
for &b in buffer {
|
||||||
@ -349,7 +317,6 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Block until transmission complete
|
|
||||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
while !sr(r).read().tc() {}
|
while !sr(r).read().tc() {}
|
||||||
@ -371,7 +338,6 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
Self::new_inner(peri, rx, rx_dma, config)
|
Self::new_inner(peri, rx, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new rx-only UART with a request-to-send pin
|
|
||||||
pub fn new_with_rts(
|
pub fn new_with_rts(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -421,7 +387,6 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconfigure the driver
|
|
||||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
reconfigure::<T>(config)
|
reconfigure::<T>(config)
|
||||||
}
|
}
|
||||||
@ -479,7 +444,6 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
Ok(sr.rxne())
|
Ok(sr.rxne())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initiate an asynchronous UART read
|
|
||||||
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
RxDma: crate::usart::RxDma<T>,
|
RxDma: crate::usart::RxDma<T>,
|
||||||
@ -489,7 +453,6 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a single u8 if there is one available, otherwise return WouldBlock
|
|
||||||
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
|
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
if self.check_rx_flags()? {
|
if self.check_rx_flags()? {
|
||||||
@ -499,7 +462,6 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform a blocking read into `buffer`
|
|
||||||
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
for b in buffer {
|
for b in buffer {
|
||||||
@ -509,7 +471,6 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initiate an asynchronous read with idle line detection enabled
|
|
||||||
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
|
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
RxDma: crate::usart::RxDma<T>,
|
RxDma: crate::usart::RxDma<T>,
|
||||||
@ -734,7 +695,6 @@ impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||||
/// Create a new bidirectional UART
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
@ -751,7 +711,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
|
Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new bidirectional UART with request-to-send and clear-to-send pins
|
|
||||||
pub fn new_with_rtscts(
|
pub fn new_with_rtscts(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
@ -779,7 +738,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||||
/// Create a new bidirectional UART with a driver-enable pin
|
|
||||||
pub fn new_with_de(
|
pub fn new_with_de(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
@ -816,13 +774,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
// Some chips do not have swap_rx_tx bit
|
// Some chips do not have swap_rx_tx bit
|
||||||
if config.half_duplex {
|
|
||||||
if config.swap_rx_tx {
|
|
||||||
rx.set_as_af(rx.af_num(), AFType::OutputOpenDrain);
|
|
||||||
} else {
|
|
||||||
tx.set_as_af(tx.af_num(), AFType::OutputOpenDrain);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(any(usart_v3, usart_v4))] {
|
if #[cfg(any(usart_v3, usart_v4))] {
|
||||||
if config.swap_rx_tx {
|
if config.swap_rx_tx {
|
||||||
@ -838,7 +789,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
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, true, true)?;
|
configure(r, &config, T::frequency(), T::KIND, true, true)?;
|
||||||
|
|
||||||
@ -863,7 +813,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initiate an asynchronous write
|
|
||||||
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
|
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
TxDma: crate::usart::TxDma<T>,
|
TxDma: crate::usart::TxDma<T>,
|
||||||
@ -871,17 +820,14 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
self.tx.write(buffer).await
|
self.tx.write(buffer).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform a blocking write
|
|
||||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||||
self.tx.blocking_write(buffer)
|
self.tx.blocking_write(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Block until transmission complete
|
|
||||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||||
self.tx.blocking_flush()
|
self.tx.blocking_flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initiate an asynchronous read into `buffer`
|
|
||||||
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
RxDma: crate::usart::RxDma<T>,
|
RxDma: crate::usart::RxDma<T>,
|
||||||
@ -889,17 +835,14 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
self.rx.read(buffer).await
|
self.rx.read(buffer).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a single `u8` or return `WouldBlock`
|
|
||||||
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
|
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
|
||||||
self.rx.nb_read()
|
self.rx.nb_read()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform a blocking read into `buffer`
|
|
||||||
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
self.rx.blocking_read(buffer)
|
self.rx.blocking_read(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initiate an an asynchronous read with idle line detection enabled
|
|
||||||
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
|
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
RxDma: crate::usart::RxDma<T>,
|
RxDma: crate::usart::RxDma<T>,
|
||||||
@ -1052,7 +995,6 @@ fn configure(
|
|||||||
#[cfg(not(usart_v1))]
|
#[cfg(not(usart_v1))]
|
||||||
r.cr3().modify(|w| {
|
r.cr3().modify(|w| {
|
||||||
w.set_onebit(config.assume_noise_free);
|
w.set_onebit(config.assume_noise_free);
|
||||||
w.set_hdsel(config.half_duplex);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
r.cr1().write(|w| {
|
r.cr1().write(|w| {
|
||||||
@ -1350,10 +1292,8 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Basic UART driver instance
|
|
||||||
pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {}
|
pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {}
|
||||||
|
|
||||||
/// Full UART driver instance
|
|
||||||
pub trait FullInstance: sealed::FullInstance {}
|
pub trait FullInstance: sealed::FullInstance {}
|
||||||
|
|
||||||
pin_trait!(RxPin, BasicInstance);
|
pin_trait!(RxPin, BasicInstance);
|
||||||
|
@ -11,7 +11,6 @@ use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config,
|
|||||||
use crate::dma::ReadableRingBuffer;
|
use crate::dma::ReadableRingBuffer;
|
||||||
use crate::usart::{Regs, Sr};
|
use crate::usart::{Regs, Sr};
|
||||||
|
|
||||||
/// Rx-only Ring-buffered UART Driver
|
|
||||||
pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> {
|
pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
ring_buf: ReadableRingBuffer<'d, RxDma, u8>,
|
ring_buf: ReadableRingBuffer<'d, RxDma, u8>,
|
||||||
@ -28,8 +27,8 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> SetConfig for RingBufferedUar
|
|||||||
|
|
||||||
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
|
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
|
||||||
/// Turn the `UartRx` into a buffered uart which can continously receive in the background
|
/// Turn the `UartRx` into a buffered uart which can continously receive in the background
|
||||||
/// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the
|
/// without the possibility of loosing bytes. The `dma_buf` is a buffer registered to the
|
||||||
/// DMA controller, and must be large enough to prevent overflows.
|
/// DMA controller, and must be sufficiently large, such that it will not overflow.
|
||||||
pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T, RxDma> {
|
pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T, RxDma> {
|
||||||
assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
|
assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
|
||||||
|
|
||||||
@ -50,7 +49,6 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> {
|
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> {
|
||||||
/// Clear the ring buffer and start receiving in the background
|
|
||||||
pub fn start(&mut self) -> Result<(), Error> {
|
pub fn start(&mut self) -> Result<(), Error> {
|
||||||
// Clear the ring buffer so that it is ready to receive data
|
// Clear the ring buffer so that it is ready to receive data
|
||||||
self.ring_buf.clear();
|
self.ring_buf.clear();
|
||||||
@ -66,7 +64,6 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
|
|||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cleanly stop and reconfigure the driver
|
|
||||||
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
self.teardown_uart();
|
self.teardown_uart();
|
||||||
reconfigure::<T>(config)
|
reconfigure::<T>(config)
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//! Universal Serial Bus (USB)
|
|
||||||
|
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
use crate::rcc::RccPeripheral;
|
use crate::rcc::RccPeripheral;
|
||||||
|
|
||||||
@ -12,9 +10,7 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB instance trait.
|
|
||||||
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
|
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
|
||||||
/// Interrupt for this USB instance.
|
|
||||||
type Interrupt: interrupt::typelevel::Interrupt;
|
type Interrupt: interrupt::typelevel::Interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,6 @@ struct EndpointData {
|
|||||||
used_out: bool,
|
used_out: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB driver.
|
|
||||||
pub struct Driver<'d, T: Instance> {
|
pub struct Driver<'d, T: Instance> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
alloc: [EndpointData; EP_COUNT],
|
alloc: [EndpointData; EP_COUNT],
|
||||||
@ -252,7 +251,6 @@ pub struct Driver<'d, T: Instance> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Driver<'d, T> {
|
impl<'d, T: Instance> Driver<'d, T> {
|
||||||
/// Create a new USB driver.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
_usb: impl Peripheral<P = T> + 'd,
|
_usb: impl Peripheral<P = T> + 'd,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
@ -467,7 +465,6 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB bus.
|
|
||||||
pub struct Bus<'d, T: Instance> {
|
pub struct Bus<'d, T: Instance> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
ep_types: [EpType; EP_COUNT - 1],
|
ep_types: [EpType; EP_COUNT - 1],
|
||||||
@ -643,7 +640,6 @@ trait Dir {
|
|||||||
fn waker(i: usize) -> &'static AtomicWaker;
|
fn waker(i: usize) -> &'static AtomicWaker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marker type for the "IN" direction.
|
|
||||||
pub enum In {}
|
pub enum In {}
|
||||||
impl Dir for In {
|
impl Dir for In {
|
||||||
fn dir() -> Direction {
|
fn dir() -> Direction {
|
||||||
@ -656,7 +652,6 @@ impl Dir for In {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marker type for the "OUT" direction.
|
|
||||||
pub enum Out {}
|
pub enum Out {}
|
||||||
impl Dir for Out {
|
impl Dir for Out {
|
||||||
fn dir() -> Direction {
|
fn dir() -> Direction {
|
||||||
@ -669,7 +664,6 @@ impl Dir for Out {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB endpoint.
|
|
||||||
pub struct Endpoint<'d, T: Instance, D> {
|
pub struct Endpoint<'d, T: Instance, D> {
|
||||||
_phantom: PhantomData<(&'d mut T, D)>,
|
_phantom: PhantomData<(&'d mut T, D)>,
|
||||||
info: EndpointInfo,
|
info: EndpointInfo,
|
||||||
@ -819,7 +813,6 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB control pipe.
|
|
||||||
pub struct ControlPipe<'d, T: Instance> {
|
pub struct ControlPipe<'d, T: Instance> {
|
||||||
_phantom: PhantomData<&'d mut T>,
|
_phantom: PhantomData<&'d mut T>,
|
||||||
max_packet_size: u16,
|
max_packet_size: u16,
|
||||||
|
@ -20,9 +20,7 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB OTG instance.
|
|
||||||
pub trait Instance: sealed::Instance + RccPeripheral {
|
pub trait Instance: sealed::Instance + RccPeripheral {
|
||||||
/// Interrupt for this USB OTG instance.
|
|
||||||
type Interrupt: interrupt::typelevel::Interrupt;
|
type Interrupt: interrupt::typelevel::Interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,6 @@ pub enum PhyType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PhyType {
|
impl PhyType {
|
||||||
/// Get whether this PHY is any of the internal types.
|
|
||||||
pub fn internal(&self) -> bool {
|
pub fn internal(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
|
PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
|
||||||
@ -212,7 +211,6 @@ impl PhyType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get whether this PHY is any of the high-speed types.
|
|
||||||
pub fn high_speed(&self) -> bool {
|
pub fn high_speed(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
PhyType::InternalFullSpeed => false,
|
PhyType::InternalFullSpeed => false,
|
||||||
@ -220,7 +218,7 @@ impl PhyType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_dspd(&self) -> vals::Dspd {
|
pub fn to_dspd(&self) -> vals::Dspd {
|
||||||
match self {
|
match self {
|
||||||
PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
|
PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
|
||||||
PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
|
PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
|
||||||
@ -232,7 +230,6 @@ impl PhyType {
|
|||||||
/// Indicates that [State::ep_out_buffers] is empty.
|
/// Indicates that [State::ep_out_buffers] is empty.
|
||||||
const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
|
const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
|
||||||
|
|
||||||
/// USB OTG driver state.
|
|
||||||
pub struct State<const EP_COUNT: usize> {
|
pub struct State<const EP_COUNT: usize> {
|
||||||
/// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true.
|
/// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true.
|
||||||
ep0_setup_data: UnsafeCell<[u8; 8]>,
|
ep0_setup_data: UnsafeCell<[u8; 8]>,
|
||||||
@ -250,7 +247,6 @@ unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
|
|||||||
unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
|
unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
|
||||||
|
|
||||||
impl<const EP_COUNT: usize> State<EP_COUNT> {
|
impl<const EP_COUNT: usize> State<EP_COUNT> {
|
||||||
/// Create a new State.
|
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
const NEW_AW: AtomicWaker = AtomicWaker::new();
|
const NEW_AW: AtomicWaker = AtomicWaker::new();
|
||||||
const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
|
const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
|
||||||
@ -275,7 +271,6 @@ struct EndpointData {
|
|||||||
fifo_size_words: u16,
|
fifo_size_words: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB driver config.
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
@ -302,7 +297,6 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB driver.
|
|
||||||
pub struct Driver<'d, T: Instance> {
|
pub struct Driver<'d, T: Instance> {
|
||||||
config: Config,
|
config: Config,
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
@ -533,7 +527,6 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB bus.
|
|
||||||
pub struct Bus<'d, T: Instance> {
|
pub struct Bus<'d, T: Instance> {
|
||||||
config: Config,
|
config: Config,
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
@ -1099,7 +1092,6 @@ trait Dir {
|
|||||||
fn dir() -> Direction;
|
fn dir() -> Direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marker type for the "IN" direction.
|
|
||||||
pub enum In {}
|
pub enum In {}
|
||||||
impl Dir for In {
|
impl Dir for In {
|
||||||
fn dir() -> Direction {
|
fn dir() -> Direction {
|
||||||
@ -1107,7 +1099,6 @@ impl Dir for In {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marker type for the "OUT" direction.
|
|
||||||
pub enum Out {}
|
pub enum Out {}
|
||||||
impl Dir for Out {
|
impl Dir for Out {
|
||||||
fn dir() -> Direction {
|
fn dir() -> Direction {
|
||||||
@ -1115,7 +1106,6 @@ impl Dir for Out {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB endpoint.
|
|
||||||
pub struct Endpoint<'d, T: Instance, D> {
|
pub struct Endpoint<'d, T: Instance, D> {
|
||||||
_phantom: PhantomData<(&'d mut T, D)>,
|
_phantom: PhantomData<(&'d mut T, D)>,
|
||||||
info: EndpointInfo,
|
info: EndpointInfo,
|
||||||
@ -1309,7 +1299,6 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB control pipe.
|
|
||||||
pub struct ControlPipe<'d, T: Instance> {
|
pub struct ControlPipe<'d, T: Instance> {
|
||||||
_phantom: PhantomData<&'d mut T>,
|
_phantom: PhantomData<&'d mut T>,
|
||||||
max_packet_size: u16,
|
max_packet_size: u16,
|
||||||
|
@ -6,7 +6,6 @@ use stm32_metapac::iwdg::vals::{Key, Pr};
|
|||||||
|
|
||||||
use crate::rcc::LSI_FREQ;
|
use crate::rcc::LSI_FREQ;
|
||||||
|
|
||||||
/// Independent watchdog (IWDG) driver.
|
|
||||||
pub struct IndependentWatchdog<'d, T: Instance> {
|
pub struct IndependentWatchdog<'d, T: Instance> {
|
||||||
wdg: PhantomData<&'d mut T>,
|
wdg: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
@ -65,12 +64,10 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
|
|||||||
IndependentWatchdog { wdg: PhantomData }
|
IndependentWatchdog { wdg: PhantomData }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unleash (start) the watchdog.
|
|
||||||
pub fn unleash(&mut self) {
|
pub fn unleash(&mut self) {
|
||||||
T::regs().kr().write(|w| w.set_key(Key::START));
|
T::regs().kr().write(|w| w.set_key(Key::START));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pet (reload, refresh) the watchdog.
|
|
||||||
pub fn pet(&mut self) {
|
pub fn pet(&mut self) {
|
||||||
T::regs().kr().write(|w| w.set_key(Key::RESET));
|
T::regs().kr().write(|w| w.set_key(Key::RESET));
|
||||||
}
|
}
|
||||||
@ -82,7 +79,6 @@ mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// IWDG instance trait.
|
|
||||||
pub trait Instance: sealed::Instance {}
|
pub trait Instance: sealed::Instance {}
|
||||||
|
|
||||||
foreach_peripheral!(
|
foreach_peripheral!(
|
||||||
|
@ -111,20 +111,6 @@ where
|
|||||||
poll_fn(move |cx| self.poll_wait(cx))
|
poll_fn(move |cx| self.poll_wait(cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// non-blocking method to try and take the signal value.
|
|
||||||
pub fn try_take(&self) -> Option<T> {
|
|
||||||
self.state.lock(|cell| {
|
|
||||||
let state = cell.replace(State::None);
|
|
||||||
match state {
|
|
||||||
State::Signaled(res) => Some(res),
|
|
||||||
state => {
|
|
||||||
cell.set(state);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// non-blocking method to check whether this signal has been signaled.
|
/// non-blocking method to check whether this signal has been signaled.
|
||||||
pub fn signaled(&self) -> bool {
|
pub fn signaled(&self) -> bool {
|
||||||
self.state.lock(|cell| {
|
self.state.lock(|cell| {
|
||||||
|
@ -47,6 +47,9 @@ impl Timer {
|
|||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ``` no_run
|
/// ``` no_run
|
||||||
|
/// # #![feature(type_alias_impl_trait)]
|
||||||
|
/// #
|
||||||
|
/// # fn foo() {}
|
||||||
/// use embassy_time::{Duration, Timer};
|
/// use embassy_time::{Duration, Timer};
|
||||||
///
|
///
|
||||||
/// #[embassy_executor::task]
|
/// #[embassy_executor::task]
|
||||||
@ -129,6 +132,8 @@ impl Future for Timer {
|
|||||||
///
|
///
|
||||||
/// For instance, consider the following code fragment.
|
/// For instance, consider the following code fragment.
|
||||||
/// ``` no_run
|
/// ``` no_run
|
||||||
|
/// # #![feature(type_alias_impl_trait)]
|
||||||
|
/// #
|
||||||
/// use embassy_time::{Duration, Timer};
|
/// use embassy_time::{Duration, Timer};
|
||||||
/// # fn foo() {}
|
/// # fn foo() {}
|
||||||
///
|
///
|
||||||
@ -147,6 +152,8 @@ impl Future for Timer {
|
|||||||
/// Example using ticker, which will consistently call `foo` once a second.
|
/// Example using ticker, which will consistently call `foo` once a second.
|
||||||
///
|
///
|
||||||
/// ``` no_run
|
/// ``` no_run
|
||||||
|
/// # #![feature(type_alias_impl_trait)]
|
||||||
|
/// #
|
||||||
/// use embassy_time::{Duration, Ticker};
|
/// use embassy_time::{Duration, Ticker};
|
||||||
/// # fn foo(){}
|
/// # fn foo(){}
|
||||||
///
|
///
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
# embassy-usb-dfu
|
|
||||||
|
|
||||||
An implementation of the USB DFU 1.1 protocol using embassy-boot. It has 2 components depending on which feature is enabled by the user.
|
|
||||||
|
|
||||||
* DFU protocol mode, enabled by the `dfu` feature. This mode corresponds to the transfer phase DFU protocol described by the USB IF. It supports DFU_DNLOAD requests if marked by the user, and will automatically reset the chip once a DFU transaction has been completed. It also responds to DFU_GETSTATUS, DFU_GETSTATE, DFU_ABORT, and DFU_CLRSTATUS with no user intervention.
|
|
||||||
* DFU runtime mode, enabled by the `application feature`. This mode allows users to expose a DFU interface on their USB device, informing the host of the capability to DFU over USB, and allowing the host to reset the device into its bootloader to complete a DFU operation. Supports DFU_GETSTATUS and DFU_DETACH. When detach/reset is seen by the device as described by the standard, will write a new DFU magic number into the bootloader state in flash, and reset the system.
|
|
||||||
|
|
||||||
## Minimum supported Rust version (MSRV)
|
|
||||||
|
|
||||||
Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This work is licensed under either of
|
|
||||||
|
|
||||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
||||||
<http://www.apache.org/licenses/LICENSE-2.0>)
|
|
||||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
|
|
||||||
|
|
||||||
at your option.
|
|
@ -24,7 +24,6 @@ pub struct Control<'d, STATE: NorFlash, RST: Reset> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, STATE: NorFlash, RST: Reset> Control<'d, STATE, RST> {
|
impl<'d, STATE: NorFlash, RST: Reset> Control<'d, STATE, RST> {
|
||||||
/// Create a new DFU instance to expose a DFU interface.
|
|
||||||
pub fn new(firmware_state: BlockingFirmwareState<'d, STATE>, attrs: DfuAttributes) -> Self {
|
pub fn new(firmware_state: BlockingFirmwareState<'d, STATE>, attrs: DfuAttributes) -> Self {
|
||||||
Control {
|
Control {
|
||||||
firmware_state,
|
firmware_state,
|
||||||
@ -73,8 +72,6 @@ impl<'d, STATE: NorFlash, RST: Reset> Handler for Control<'d, STATE, RST> {
|
|||||||
self.detach_start = Some(Instant::now());
|
self.detach_start = Some(Instant::now());
|
||||||
self.timeout = Some(Duration::from_millis(req.value as u64));
|
self.timeout = Some(Duration::from_millis(req.value as u64));
|
||||||
self.state = State::AppDetach;
|
self.state = State::AppDetach;
|
||||||
// hack to make it work together with usb serial logging
|
|
||||||
self.reset();
|
|
||||||
Some(OutResponse::Accepted)
|
Some(OutResponse::Accepted)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -23,7 +23,6 @@ pub struct Control<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_S
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Control<'d, DFU, STATE, RST, BLOCK_SIZE> {
|
impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Control<'d, DFU, STATE, RST, BLOCK_SIZE> {
|
||||||
/// Create a new DFU instance to handle DFU transfers.
|
|
||||||
pub fn new(updater: BlockingFirmwareUpdater<'d, DFU, STATE>, attrs: DfuAttributes) -> Self {
|
pub fn new(updater: BlockingFirmwareUpdater<'d, DFU, STATE>, attrs: DfuAttributes) -> Self {
|
||||||
Self {
|
Self {
|
||||||
updater,
|
updater,
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user