diff --git a/ci.sh b/ci.sh index 8ac9e1ccd..4c9397cee 100755 --- a/ci.sh +++ b/ci.sh @@ -2,11 +2,13 @@ set -eo pipefail -# check-cfg is stable on rustc 1.79 but not cargo 1.79. -# however, our cargo-batch is currently based on cargo 1.80, which does support check-cfg. -# so, force build.rs scripts to emit check-cfg commands. -# when 1.80 hits stable we can make build.rs unconditionally emit check-cfg and remove all this. -export EMBASSY_FORCE_CHECK_CFG=1 +if ! command -v cargo-batch &> /dev/null; then + echo "cargo-batch could not be found. Install it with the following command:" + echo "" + echo " cargo install --git https://github.com/embassy-rs/cargo-batch cargo --bin cargo-batch --locked" + echo "" + exit 1 +fi export RUSTFLAGS=-Dwarnings export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info @@ -175,6 +177,7 @@ cargo batch \ --- build --release --manifest-path cyw43-pio/Cargo.toml --target thumbv6m-none-eabi --features 'overclock' \ --- 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-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-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 docs/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ @@ -186,6 +189,8 @@ cargo batch \ --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840 \ --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf5340 \ --- build --release --manifest-path examples/nrf9160/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9160 \ + --- build --release --manifest-path examples/nrf9151/s/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9151/s \ + --- build --release --manifest-path examples/nrf9151/ns/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf9151/ns \ --- build --release --manifest-path examples/nrf51/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/nrf51 \ --- 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 \ @@ -214,6 +219,7 @@ cargo batch \ --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32wl \ --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840,skip-include --out-dir out/examples/boot/nrf52840 \ --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns,skip-include --out-dir out/examples/boot/nrf9160 \ + --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns,skip-include --out-dir out/examples/boot/nrf9120 \ --- build --release --manifest-path examples/boot/application/rp/Cargo.toml --target thumbv6m-none-eabi --features skip-include --out-dir out/examples/boot/rp \ --- build --release --manifest-path examples/boot/application/stm32f3/Cargo.toml --target thumbv7em-none-eabi --features skip-include --out-dir out/examples/boot/stm32f3 \ --- build --release --manifest-path examples/boot/application/stm32f7/Cargo.toml --target thumbv7em-none-eabi --features skip-include --out-dir out/examples/boot/stm32f7 \ @@ -225,6 +231,7 @@ cargo batch \ --- build --release --manifest-path examples/boot/application/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/boot/stm32wb-dfu \ --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ + --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns \ --- build --release --manifest-path examples/boot/bootloader/rp/Cargo.toml --target thumbv6m-none-eabi \ --- build --release --manifest-path examples/boot/bootloader/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4 \ --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg \ diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 157046b18..9c7acd779 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -16,7 +16,7 @@ overclock = [] [dependencies] cyw43 = { version = "0.1.0", path = "../cyw43" } -embassy-rp = { version = "0.1.0", path = "../embassy-rp" } +embassy-rp = { version = "0.2.0", path = "../embassy-rp" } pio-proc = "0.2" pio = "0.2.1" fixed = "1.23.1" diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index c613698c1..3c90873de 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -17,10 +17,10 @@ log = ["dep:log"] firmware-logs = [] [dependencies] -embassy-time = { version = "0.3.1", path = "../embassy-time"} +embassy-time = { version = "0.3.2", path = "../embassy-time"} embassy-sync = { version = "0.6.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} -embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel"} +embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel"} defmt = { version = "0.3", optional = true } log = { version = "0.4.17", optional = true } diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index 8944865c1..f0f179e2e 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -42,9 +42,11 @@ pub enum ScanType { Passive, } +/// Scan options. #[derive(Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ScanOptions { + /// SSID to scan for. pub ssid: Option>, /// If set to `None`, all APs will be returned. If set to `Some`, only APs /// with the specified BSSID will be returned. diff --git a/cyw43/src/fmt.rs b/cyw43/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/cyw43/src/fmt.rs +++ b/cyw43/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/cyw43/src/lib.rs b/cyw43/src/lib.rs index 19b0cb194..7c8f35da7 100644 --- a/cyw43/src/lib.rs +++ b/cyw43/src/lib.rs @@ -28,7 +28,7 @@ use ioctl::IoctlState; use crate::bus::Bus; pub use crate::bus::SpiBusCyw43; -pub use crate::control::{AddMulticastAddressError, Control, Error as ControlError, Scanner}; +pub use crate::control::{AddMulticastAddressError, Control, Error as ControlError, ScanOptions, Scanner}; pub use crate::runner::Runner; pub use crate::structs::BssInfo; diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index e82165032..5d391adf3 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -6,9 +6,9 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.5.0", path = "../../../embassy-executor", features = ["defmt", "integrated-timers", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.3.1", path = "../../../embassy-time", features = ["defmt"] } -embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } +embassy-executor = { version = "0.6.0", path = "../../../embassy-executor", features = ["defmt", "integrated-timers", "arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.3.2", path = "../../../embassy-time", features = ["defmt"] } +embassy-nrf = { version = "0.2.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } defmt = "0.3" defmt-rtt = "0.3" diff --git a/docs/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/examples/layer-by-layer/blinky-async/Cargo.toml index 64f7e8403..7f8d8af3e 100644 --- a/docs/examples/layer-by-layer/blinky-async/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-async/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" cortex-m = "0.7" cortex-m-rt = "0.7" embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] } -embassy-executor = { version = "0.5.0", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", "executor-thread"] } defmt = "0.3.0" defmt-rtt = "0.3.0" diff --git a/docs/pages/basic_application.adoc b/docs/pages/basic_application.adoc index 7b4ebda4f..5c4e3e8b3 100644 --- a/docs/pages/basic_application.adoc +++ b/docs/pages/basic_application.adoc @@ -4,7 +4,7 @@ So you've got one of the examples running, but what now? Let's go through a simp == Main -The full example can be found link:https://github.com/embassy-rs/embassy/tree/master/docs/examples/basic[here]. +The full example can be found link:https://github.com/embassy-rs/embassy/tree/main/docs/examples/basic[here]. NOTE: If you’re using VS Code and rust-analyzer to view and edit the examples, you may need to make some changes to `.vscode/settings.json` to tell it which project we’re working on. Follow the instructions commented in that file to get rust-analyzer working correctly. diff --git a/docs/pages/faq.adoc b/docs/pages/faq.adoc index a2f56a539..4ab04e2a1 100644 --- a/docs/pages/faq.adoc +++ b/docs/pages/faq.adoc @@ -352,8 +352,13 @@ There are two main ways to handle concurrency in Embassy: In general, either of these approaches will work. The main differences of these approaches are: -When using **separate tasks**, each task needs its own RAM allocation, so there's a little overhead for each task, so one task that does three things will likely be a little bit smaller than three tasks that do one thing (not a lot, probably a couple dozen bytes). In contrast, with **multiple futures in one task**, you don't need multiple task allocations, and it will generally be easier to share data, or use borrowed resources, inside of a single task. +When using **separate tasks**, each task needs its own RAM allocation, so there's a little overhead for each task, so one task that does three things will likely be a little bit smaller than three tasks that do one thing (not a lot, probably a couple dozen bytes). In contrast, with **multiple futures in one task**, you don't need multiple task allocations, and it will generally be easier to share data, or use borrowed resources, inside of a single task. +An example showcasing some methods for sharing things between tasks link:https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/sharing.rs[can be found here]. But when it comes to "waking" tasks, for example when a data transfer is complete or a button is pressed, it's faster to wake a dedicated task, because that task does not need to check which future is actually ready. `join` and `select` must check ALL of the futures they are managing to see which one (or which ones) are ready to do more work. This is because all Rust executors (like Embassy or Tokio) only have the ability to wake tasks, not specific futures. This means you will use slightly less CPU time juggling futures when using dedicated tasks. Practically, there's not a LOT of difference either way - so go with what makes it easier for you and your code first, but there will be some details that are slightly different in each case. + +== splitting peripherals resources between tasks + +There are two ways to split resources between tasks, either manually assigned or by a convenient macro. See link:https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/assign_resources.rs[this example] \ No newline at end of file diff --git a/docs/pages/new_project.adoc b/docs/pages/new_project.adoc index 346d9f0f8..821bcbd27 100644 --- a/docs/pages/new_project.adoc +++ b/docs/pages/new_project.adoc @@ -1,6 +1,6 @@ = Starting a new project -Once you’ve successfully xref:getting_started.adoc[run some example projects], the next step is to make a standalone Embassy project. +Once you’ve successfully xref:#_getting_started[run some example projects], the next step is to make a standalone Embassy project. == Tools for generating Embassy projects diff --git a/docs/pages/nrf.adoc b/docs/pages/nrf.adoc index 1706087ae..de052b63f 100644 --- a/docs/pages/nrf.adoc +++ b/docs/pages/nrf.adoc @@ -1,6 +1,6 @@ = Embassy nRF HAL -The link:https://github.com/embassy-rs/embassy/tree/master/embassy-nrf[Embassy nRF HAL] is based on the PACs (Peripheral Access Crate) from link:https://github.com/nrf-rs/[nrf-rs]. +The link:https://github.com/embassy-rs/embassy/tree/main/embassy-nrf[Embassy nRF HAL] is based on the PACs (Peripheral Access Crate) from link:https://github.com/nrf-rs/[nrf-rs]. == Timer driver diff --git a/docs/pages/overview.adoc b/docs/pages/overview.adoc index 1b9381bfe..7d59d5521 100644 --- a/docs/pages/overview.adoc +++ b/docs/pages/overview.adoc @@ -48,7 +48,7 @@ link:https://github.com/lora-rs/lora-rs[lora-rs] supports LoRa networking on a w link:https://docs.embassy.dev/embassy-usb/[embassy-usb] implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own. === Bootloader and DFU -link:https://github.com/embassy-rs/embassy/tree/master/embassy-boot[embassy-boot] is a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks. +link:https://github.com/embassy-rs/embassy/tree/main/embassy-boot[embassy-boot] is a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks. == What is DMA? diff --git a/docs/pages/sharing_peripherals.adoc b/docs/pages/sharing_peripherals.adoc index 6bcd56b01..dfb8c1ffe 100644 --- a/docs/pages/sharing_peripherals.adoc +++ b/docs/pages/sharing_peripherals.adoc @@ -8,7 +8,7 @@ The following examples shows different ways to use the on-board LED on a Raspber Using mutual exclusion is the simplest way to share a peripheral. -TIP: Dependencies needed to run this example link:/book/dev/basic_application.html#_the_cargo_toml[can be found here]. +TIP: Dependencies needed to run this example link:#_the_cargo_toml[can be found here]. [,rust] ---- use defmt::*; @@ -78,7 +78,7 @@ To indicate that the pin will be set to an Output. The `AnyPin` could have been A channel is another way to ensure exclusive access to a resource. Using a channel is great in the cases where the access can happen at a later point in time, allowing you to enqueue operations and do other things. -TIP: Dependencies needed to run this example link:/book/dev/basic_application.html#_the_cargo_toml[can be found here]. +TIP: Dependencies needed to run this example link:#_the_cargo_toml[can be found here]. [,rust] ---- use defmt::*; @@ -126,3 +126,9 @@ async fn toggle_led(control: Sender<'static, ThreadModeRawMutex, LedState, 64>, This example replaces the Mutex with a Channel, and uses another task (the main loop) to drive the LED. The advantage of this approach is that only a single task references the peripheral, separating concerns. However, using a Mutex has a lower overhead and might be necessary if you need to ensure that the operation is completed before continuing to do other work in your task. + +An example showcasing more methods for sharing link:https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/sharing.rs[can be found here]. + +== Sharing an I2C or SPI bus between multiple devices + +An example of how to deal with multiple devices sharing a common I2C or SPI bus link:https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/shared_bus.rs[can be found here]. diff --git a/docs/pages/stm32.adoc b/docs/pages/stm32.adoc index 7bfc0592b..df139a420 100644 --- a/docs/pages/stm32.adoc +++ b/docs/pages/stm32.adoc @@ -1,6 +1,6 @@ = Embassy STM32 HAL -The link:https://github.com/embassy-rs/embassy/tree/master/embassy-stm32[Embassy STM32 HAL] is based on the `stm32-metapac` project. +The link:https://github.com/embassy-rs/embassy/tree/main/embassy-stm32[Embassy STM32 HAL] is based on the `stm32-metapac` project. == The infinite variant problem diff --git a/docs/pages/time_keeping.adoc b/docs/pages/time_keeping.adoc index 17492a884..11ddb2b2b 100644 --- a/docs/pages/time_keeping.adoc +++ b/docs/pages/time_keeping.adoc @@ -16,7 +16,7 @@ The `embassy::time::Timer` type provides two timing methods. An example of a delay is provided as follows: -TIP: Dependencies needed to run this example link:/book/dev/basic_application.html#_the_cargo_toml[can be found here]. +TIP: Dependencies needed to run this example link:#_the_cargo_toml[can be found here]. [,rust] ---- use embassy::executor::{task, Executor}; @@ -41,7 +41,7 @@ that expect a generic delay implementation to be provided. An example of how this can be used: -TIP: Dependencies needed to run this example link:/book/dev/basic_application.html#_the_cargo_toml[can be found here]. +TIP: Dependencies needed to run this example link:#_the_cargo_toml[can be found here]. [,rust] ---- use embassy::executor::{task, Executor}; diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 86bfc21f4..27407ae92 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-nrf" -version = "0.2.0" +version = "0.3.0" description = "Bootloader lib for nRF chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -25,8 +25,8 @@ defmt = { version = "0.3", optional = true } log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } -embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", default-features = false } -embassy-boot = { version = "0.2.0", path = "../embassy-boot" } +embassy-nrf = { version = "0.2.0", path = "../embassy-nrf", default-features = false } +embassy-boot = { version = "0.3.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" diff --git a/embassy-boot-nrf/src/fmt.rs b/embassy-boot-nrf/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-boot-nrf/src/fmt.rs +++ b/embassy-boot-nrf/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 23a8bb549..5b173638e 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-rp" -version = "0.2.0" +version = "0.3.0" description = "Bootloader lib for RP2040 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -24,9 +24,9 @@ defmt = { version = "0.3", optional = true } log = { version = "0.4", optional = true } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } -embassy-rp = { version = "0.1.0", path = "../embassy-rp", default-features = false } -embassy-boot = { version = "0.2.0", path = "../embassy-boot" } -embassy-time = { version = "0.3.1", path = "../embassy-time" } +embassy-rp = { version = "0.2.0", path = "../embassy-rp", default-features = false } +embassy-boot = { version = "0.3.0", path = "../embassy-boot" } +embassy-time = { version = "0.3.2", path = "../embassy-time" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } diff --git a/embassy-boot-rp/src/fmt.rs b/embassy-boot-rp/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-boot-rp/src/fmt.rs +++ b/embassy-boot-rp/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index 52ad1b463..e4ef9a612 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -26,7 +26,7 @@ log = { version = "0.4", optional = true } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false } -embassy-boot = { version = "0.2.0", path = "../embassy-boot" } +embassy-boot = { version = "0.3.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" diff --git a/embassy-boot-stm32/src/fmt.rs b/embassy-boot-stm32/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-boot-stm32/src/fmt.rs +++ b/embassy-boot-stm32/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index 16dc52bcc..85b3695a1 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot" -version = "0.2.0" +version = "0.3.0" description = "A lightweight bootloader supporting firmware updates in a power-fail-safe way, with trial boots and rollbacks." license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -28,7 +28,7 @@ defmt = { version = "0.3", optional = true } digest = "0.10" log = { version = "0.4", optional = true } ed25519-dalek = { version = "2", default_features = false, features = ["digest"], optional = true } -embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.2.0", path = "../embassy-embedded-hal" } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } diff --git a/embassy-boot/src/boot_loader.rs b/embassy-boot/src/boot_loader.rs index 789fa34c1..61d61b96e 100644 --- a/embassy-boot/src/boot_loader.rs +++ b/embassy-boot/src/boot_loader.rs @@ -236,10 +236,10 @@ impl BootLoader Result { const { - assert!(Self::PAGE_SIZE % ACTIVE::WRITE_SIZE as u32 == 0); - assert!(Self::PAGE_SIZE % ACTIVE::ERASE_SIZE as u32 == 0); - assert!(Self::PAGE_SIZE % DFU::WRITE_SIZE as u32 == 0); - assert!(Self::PAGE_SIZE % DFU::ERASE_SIZE as u32 == 0); + core::assert!(Self::PAGE_SIZE % ACTIVE::WRITE_SIZE as u32 == 0); + core::assert!(Self::PAGE_SIZE % ACTIVE::ERASE_SIZE as u32 == 0); + core::assert!(Self::PAGE_SIZE % DFU::WRITE_SIZE as u32 == 0); + core::assert!(Self::PAGE_SIZE % DFU::ERASE_SIZE as u32 == 0); } // Ensure we have enough progress pages to store copy progress diff --git a/embassy-boot/src/fmt.rs b/embassy-boot/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-boot/src/fmt.rs +++ b/embassy-boot/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-embedded-hal/CHANGELOG.md b/embassy-embedded-hal/CHANGELOG.md new file mode 100644 index 000000000..f8e272160 --- /dev/null +++ b/embassy-embedded-hal/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog for embassy-embedded-hal + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## 0.2.0 - 2024-08-05 + +- Add Clone derive to flash Partition in embassy-embedded-hal +- Add support for all word sizes to async shared spi +- Add Copy and 'static constraint to Word type in SPI structs +- Improve flexibility by introducing SPI word size as a generic parameter +- Allow changing Spi/I2cDeviceWithConfig's config at runtime +- Impl `MultiwriteNorFlash` for `BlockingAsync` + +## 0.1.0 - 2024-01-10 + +- First release diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index 905439fe7..345dc3420 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-embedded-hal" -version = "0.1.0" +version = "0.2.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Collection of utilities to use `embedded-hal` and `embedded-storage` traits with Embassy." @@ -29,7 +29,7 @@ default = ["time"] [dependencies] embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } -embassy-time = { version = "0.3.1", path = "../embassy-time", optional = true } +embassy-time = { version = "0.3.2", path = "../embassy-time", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ "unproven", ] } diff --git a/embassy-embedded-hal/src/flash/partition/asynch.rs b/embassy-embedded-hal/src/flash/partition/asynch.rs index 5920436dd..1b0c91232 100644 --- a/embassy-embedded-hal/src/flash/partition/asynch.rs +++ b/embassy-embedded-hal/src/flash/partition/asynch.rs @@ -18,6 +18,16 @@ pub struct Partition<'a, M: RawMutex, T: NorFlash> { size: u32, } +impl<'a, M: RawMutex, T: NorFlash> Clone for Partition<'a, M, T> { + fn clone(&self) -> Self { + Self { + flash: self.flash, + offset: self.offset, + size: self.size, + } + } +} + impl<'a, M: RawMutex, T: NorFlash> Partition<'a, M, T> { /// Create a new partition pub const fn new(flash: &'a Mutex, offset: u32, size: u32) -> Self { diff --git a/embassy-embedded-hal/src/flash/partition/blocking.rs b/embassy-embedded-hal/src/flash/partition/blocking.rs index 2ddbe3de0..a68df7812 100644 --- a/embassy-embedded-hal/src/flash/partition/blocking.rs +++ b/embassy-embedded-hal/src/flash/partition/blocking.rs @@ -19,6 +19,16 @@ pub struct BlockingPartition<'a, M: RawMutex, T: NorFlash> { size: u32, } +impl<'a, M: RawMutex, T: NorFlash> Clone for BlockingPartition<'a, M, T> { + fn clone(&self) -> Self { + Self { + flash: self.flash, + offset: self.offset, + size: self.size, + } + } +} + impl<'a, M: RawMutex, T: NorFlash> BlockingPartition<'a, M, T> { /// Create a new partition pub const fn new(flash: &'a Mutex>, offset: u32, size: u32) -> Self { diff --git a/embassy-executor-macros/Cargo.toml b/embassy-executor-macros/Cargo.toml index 2953e7ccc..218e820ce 100644 --- a/embassy-executor-macros/Cargo.toml +++ b/embassy-executor-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-executor-macros" -version = "0.4.1" +version = "0.5.0" edition = "2021" license = "MIT OR Apache-2.0" description = "macros for creating the entry point and tasks for embassy-executor" diff --git a/embassy-executor-macros/src/macros/main.rs b/embassy-executor-macros/src/macros/main.rs index 088e64d1c..26dfa2397 100644 --- a/embassy-executor-macros/src/macros/main.rs +++ b/embassy-executor-macros/src/macros/main.rs @@ -70,7 +70,7 @@ pub fn wasm() -> TokenStream { let executor = ::std::boxed::Box::leak(::std::boxed::Box::new(::embassy_executor::Executor::new())); executor.start(|spawner| { - spawner.spawn(__embassy_main(spawner)).unwrap(); + spawner.must_spawn(__embassy_main(spawner)); }); Ok(()) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 77c64fd8e..5582b56ec 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## 0.6.0 - 2024-08-05 + +- Add collapse_debuginfo to fmt.rs macros. +- initial support for avr +- use nightly waker_getters APIs + ## 0.5.0 - 2024-01-11 - Updated to `embassy-time-driver 0.1`, `embassy-time-queue-driver 0.1`, compatible with `embassy-time v0.3` and higher. diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 431165cee..5984cc49c 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-executor" -version = "0.5.0" +version = "0.6.0" edition = "2021" license = "MIT OR Apache-2.0" description = "async/await executor designed for embedded usage" @@ -33,7 +33,7 @@ defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } rtos-trace = { version = "0.1.2", optional = true } -embassy-executor-macros = { version = "0.4.0", path = "../embassy-executor-macros" } +embassy-executor-macros = { version = "0.5.0", path = "../embassy-executor-macros" } embassy-time-driver = { version = "0.1.0", path = "../embassy-time-driver", optional = true } embassy-time-queue-driver = { version = "0.1.0", path = "../embassy-time-queue-driver", optional = true } critical-section = "1.1" diff --git a/embassy-executor/build_common.rs b/embassy-executor/build_common.rs index 0487eb3c5..4f24e6d37 100644 --- a/embassy-executor/build_common.rs +++ b/embassy-executor/build_common.rs @@ -8,8 +8,6 @@ use std::collections::HashSet; use std::env; -use std::ffi::OsString; -use std::process::Command; /// Helper for emitting cargo instruction for enabling configs (`cargo:rustc-cfg=X`) and declaring /// them (`cargo:rust-check-cfg=cfg(X)`). @@ -17,7 +15,6 @@ use std::process::Command; pub struct CfgSet { enabled: HashSet, declared: HashSet, - emit_declared: bool, } impl CfgSet { @@ -25,7 +22,6 @@ impl CfgSet { Self { enabled: HashSet::new(), declared: HashSet::new(), - emit_declared: is_rustc_nightly(), } } @@ -49,7 +45,7 @@ impl CfgSet { /// /// This enables rustc to check that the configs in `#[cfg(...)]` attributes are valid. pub fn declare(&mut self, cfg: impl AsRef) { - if self.declared.insert(cfg.as_ref().to_owned()) && self.emit_declared { + if self.declared.insert(cfg.as_ref().to_owned()) { println!("cargo:rustc-check-cfg=cfg({})", cfg.as_ref()); } } @@ -69,21 +65,6 @@ impl CfgSet { } } -fn is_rustc_nightly() -> bool { - if env::var_os("EMBASSY_FORCE_CHECK_CFG").is_some() { - return true; - } - - let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc")); - - let output = Command::new(rustc) - .arg("--version") - .output() - .expect("failed to run `rustc --version`"); - - String::from_utf8_lossy(&output.stdout).contains("nightly") -} - /// Sets configs that describe the target platform. pub fn set_target_cfgs(cfgs: &mut CfgSet) { let target = env::var("TARGET").unwrap(); diff --git a/embassy-executor/src/fmt.rs b/embassy-executor/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-executor/src/fmt.rs +++ b/embassy-executor/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-futures/src/fmt.rs b/embassy-futures/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-futures/src/fmt.rs +++ b/embassy-futures/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-hal-internal/Cargo.toml b/embassy-hal-internal/Cargo.toml index c5013f365..d5ca95ac2 100644 --- a/embassy-hal-internal/Cargo.toml +++ b/embassy-hal-internal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-hal-internal" -version = "0.1.0" +version = "0.2.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Internal implementation details for Embassy HALs. DO NOT USE DIRECTLY." diff --git a/embassy-hal-internal/build_common.rs b/embassy-hal-internal/build_common.rs index 0487eb3c5..4f24e6d37 100644 --- a/embassy-hal-internal/build_common.rs +++ b/embassy-hal-internal/build_common.rs @@ -8,8 +8,6 @@ use std::collections::HashSet; use std::env; -use std::ffi::OsString; -use std::process::Command; /// Helper for emitting cargo instruction for enabling configs (`cargo:rustc-cfg=X`) and declaring /// them (`cargo:rust-check-cfg=cfg(X)`). @@ -17,7 +15,6 @@ use std::process::Command; pub struct CfgSet { enabled: HashSet, declared: HashSet, - emit_declared: bool, } impl CfgSet { @@ -25,7 +22,6 @@ impl CfgSet { Self { enabled: HashSet::new(), declared: HashSet::new(), - emit_declared: is_rustc_nightly(), } } @@ -49,7 +45,7 @@ impl CfgSet { /// /// This enables rustc to check that the configs in `#[cfg(...)]` attributes are valid. pub fn declare(&mut self, cfg: impl AsRef) { - if self.declared.insert(cfg.as_ref().to_owned()) && self.emit_declared { + if self.declared.insert(cfg.as_ref().to_owned()) { println!("cargo:rustc-check-cfg=cfg({})", cfg.as_ref()); } } @@ -69,21 +65,6 @@ impl CfgSet { } } -fn is_rustc_nightly() -> bool { - if env::var_os("EMBASSY_FORCE_CHECK_CFG").is_some() { - return true; - } - - let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc")); - - let output = Command::new(rustc) - .arg("--version") - .output() - .expect("failed to run `rustc --version`"); - - String::from_utf8_lossy(&output.stdout).contains("nightly") -} - /// Sets configs that describe the target platform. pub fn set_target_cfgs(cfgs: &mut CfgSet) { let target = env::var("TARGET").unwrap(); diff --git a/embassy-hal-internal/src/fmt.rs b/embassy-hal-internal/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-hal-internal/src/fmt.rs +++ b/embassy-hal-internal/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-net-adin1110/Cargo.toml b/embassy-net-adin1110/Cargo.toml index e75f76b16..0b2a6744d 100644 --- a/embassy-net-adin1110/Cargo.toml +++ b/embassy-net-adin1110/Cargo.toml @@ -16,8 +16,8 @@ log = { version = "0.4", default-features = false, optional = true } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-hal-bus = { version = "0.1", features = ["async"] } -embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" } -embassy-time = { version = "0.3.1", path = "../embassy-time" } +embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } +embassy-time = { version = "0.3.2", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } bitfield = "0.14.0" diff --git a/embassy-net-adin1110/README.md b/embassy-net-adin1110/README.md index 39a38960d..0514274b4 100644 --- a/embassy-net-adin1110/README.md +++ b/embassy-net-adin1110/README.md @@ -21,7 +21,7 @@ APL can be used in [`intrinsic safety applications/explosion hazardous areas`](h ## Supported SPI modes -`ADIN1110` supports two SPI modes. `Generic` and [`OPEN Alliance 10BASE-T1x MAC-PHY serial interface`](https://opensig.org/download/document/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf) +`ADIN1110` supports two SPI modes. `Generic` and [`OPEN Alliance 10BASE-T1x MAC-PHY serial interface`](https://opensig.org/wp-content/uploads/2023/12/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf) Both modes support with and without additional CRC. Currently only `Generic` SPI with or without CRC is supported. diff --git a/embassy-net-adin1110/src/crc8.rs b/embassy-net-adin1110/src/crc8.rs index 7d20a7401..321983e64 100644 --- a/embassy-net-adin1110/src/crc8.rs +++ b/embassy-net-adin1110/src/crc8.rs @@ -16,7 +16,7 @@ const CRC8X_TABLE: [u8; 256] = [ 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3, ]; -/// Calculate the crc of a pease of data. +/// Calculate the crc of a piece of data. pub fn crc8(data: &[u8]) -> u8 { data.iter().fold(0, |crc, &byte| CRC8X_TABLE[usize::from(byte ^ crc)]) } diff --git a/embassy-net-adin1110/src/fmt.rs b/embassy-net-adin1110/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-net-adin1110/src/fmt.rs +++ b/embassy-net-adin1110/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-net-driver-channel/CHANGELOG.md b/embassy-net-driver-channel/CHANGELOG.md index b04d0a86b..d7af7e55d 100644 --- a/embassy-net-driver-channel/CHANGELOG.md +++ b/embassy-net-driver-channel/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +## 0.3.0 - 2024-08-05 + +- Add collapse_debuginfo to fmt.rs macros. +- Update embassy-sync version + ## 0.2.0 - 2023-10-18 - Update `embassy-net-driver` to v0.2 diff --git a/embassy-net-driver-channel/Cargo.toml b/embassy-net-driver-channel/Cargo.toml index 3bd7d288a..abce9315b 100644 --- a/embassy-net-driver-channel/Cargo.toml +++ b/embassy-net-driver-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-driver-channel" -version = "0.2.0" +version = "0.3.0" edition = "2021" license = "MIT OR Apache-2.0" description = "High-level channel-based driver for the `embassy-net` async TCP/IP network stack." diff --git a/embassy-net-driver-channel/src/fmt.rs b/embassy-net-driver-channel/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-net-driver-channel/src/fmt.rs +++ b/embassy-net-driver-channel/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-net-enc28j60/Cargo.toml b/embassy-net-enc28j60/Cargo.toml index dd7aa031d..cafced4b2 100644 --- a/embassy-net-enc28j60/Cargo.toml +++ b/embassy-net-enc28j60/Cargo.toml @@ -13,7 +13,7 @@ documentation = "https://docs.embassy.dev/embassy-net-enc28j60" embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } -embassy-time = { version = "0.3.1", path = "../embassy-time" } +embassy-time = { version = "0.3.2", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } defmt = { version = "0.3", optional = true } diff --git a/embassy-net-enc28j60/src/fmt.rs b/embassy-net-enc28j60/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-net-enc28j60/src/fmt.rs +++ b/embassy-net-enc28j60/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index 24b7d0806..915eba7a0 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -17,10 +17,10 @@ log = [ "dep:log" ] defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } -embassy-time = { version = "0.3.1", path = "../embassy-time" } +embassy-time = { version = "0.3.2", path = "../embassy-time" } embassy-sync = { version = "0.6.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} -embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel"} +embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel"} embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } diff --git a/embassy-net-esp-hosted/src/fmt.rs b/embassy-net-esp-hosted/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-net-esp-hosted/src/fmt.rs +++ b/embassy-net-esp-hosted/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml index cdfafaae1..f6371f955 100644 --- a/embassy-net-ppp/Cargo.toml +++ b/embassy-net-ppp/Cargo.toml @@ -18,7 +18,7 @@ defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } embedded-io-async = { version = "0.6.1" } -embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" } +embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } ppproto = { version = "0.1.2"} embassy-sync = { version = "0.6.0", path = "../embassy-sync" } diff --git a/embassy-net-ppp/src/fmt.rs b/embassy-net-ppp/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-net-ppp/src/fmt.rs +++ b/embassy-net-ppp/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-net-wiznet/Cargo.toml b/embassy-net-wiznet/Cargo.toml index b6ce20325..e7fb3f455 100644 --- a/embassy-net-wiznet/Cargo.toml +++ b/embassy-net-wiznet/Cargo.toml @@ -12,8 +12,8 @@ documentation = "https://docs.embassy.dev/embassy-net-wiznet" [dependencies] embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } -embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" } -embassy-time = { version = "0.3.1", path = "../embassy-time" } +embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } +embassy-time = { version = "0.3.2", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } defmt = { version = "0.3", optional = true } diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 15b97af47..d86a30755 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -72,7 +72,7 @@ smoltcp = { version = "0.11.0", default-features = false, features = [ ] } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } -embassy-time = { version = "0.3.1", path = "../embassy-time" } +embassy-time = { version = "0.3.2", path = "../embassy-time" } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } embedded-io-async = { version = "0.6.1" } diff --git a/embassy-net/src/fmt.rs b/embassy-net/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-net/src/fmt.rs +++ b/embassy-net/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 12f5f30b4..bd3de1f8c 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -34,6 +34,8 @@ use embassy_sync::waitqueue::WakerRegistration; use embassy_time::{Instant, Timer}; #[allow(unused_imports)] use heapless::Vec; +#[cfg(feature = "dns")] +pub use smoltcp::config::DNS_MAX_SERVER_COUNT; #[cfg(feature = "igmp")] pub use smoltcp::iface::MulticastError; #[allow(unused_imports)] @@ -414,7 +416,7 @@ impl Stack { /// ```ignore /// let config = embassy_net::Config::dhcpv4(Default::default()); ///// Init network stack - /// static RESOURCES: StaticCell = StaticCell::new(); + /// static RESOURCES: StaticCell> = StaticCell::new(); /// static STACK: StaticCell = StaticCell::new(); /// let stack = &*STACK.init(embassy_net::Stack::new( /// device, @@ -823,9 +825,17 @@ impl Inner { // Apply DNS servers #[cfg(feature = "dns")] - s.sockets - .get_mut::(self.dns_socket) - .update_servers(&dns_servers[..]); + if !dns_servers.is_empty() { + let count = if dns_servers.len() > DNS_MAX_SERVER_COUNT { + warn!("Number of DNS servers exceeds DNS_MAX_SERVER_COUNT, truncating list."); + DNS_MAX_SERVER_COUNT + } else { + dns_servers.len() + }; + s.sockets + .get_mut::(self.dns_socket) + .update_servers(&dns_servers[..count]); + } self.config_waker.wake(); } diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index 74eff9dae..be0e1a129 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs @@ -660,12 +660,25 @@ pub mod client { pub struct TcpClient<'d, D: Driver, const N: usize, const TX_SZ: usize = 1024, const RX_SZ: usize = 1024> { stack: &'d Stack, state: &'d TcpClientState, + socket_timeout: Option, } impl<'d, D: Driver, const N: usize, const TX_SZ: usize, const RX_SZ: usize> TcpClient<'d, D, N, TX_SZ, RX_SZ> { /// Create a new `TcpClient`. pub fn new(stack: &'d Stack, state: &'d TcpClientState) -> Self { - Self { stack, state } + Self { + stack, + state, + socket_timeout: None, + } + } + + /// Set the timeout for each socket created by this `TcpClient`. + /// + /// If the timeout is set, the socket will be closed if no data is received for the + /// specified duration. + pub fn set_timeout(&mut self, timeout: Option) { + self.socket_timeout = timeout; } } @@ -691,6 +704,7 @@ pub mod client { }; let remote_endpoint = (addr, remote.port()); let mut socket = TcpConnection::new(&self.stack, self.state)?; + socket.socket.set_timeout(self.socket_timeout.clone()); socket .socket .connect(remote_endpoint) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 6f07a8c6d..f8d6ab753 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -7,24 +7,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -- Drop `sealed` mod -- nrf52840: Add dcdc voltage parameter to configure REG0 regulator -- radio: Add support for IEEE 802.15.4 and BLE via radio peripheral -- spim: Reduce trace-level messages ("Copying SPIM tx buffer..") -- uart: Add support for rx- or tx-only BufferedUart -- uart: Implement splitting Rx/Tx -- spi: Allow specifying OutputDrive for SPI spins -- pdm: Fix gain register value derivation -- spim: Implement chunked DMA transfers -- spi: Add bounds checks for EasyDMA buffer size -- uarte: Add support for handling RX errors -- nrf51: Implement support for nrf51 chip -- pwm: Expose `duty` method -- pwm: Fix infinite loop -- spi: Add support for configuring bit order for bus -- pwm: Expose `pwm::PWM_CLK_HZ` and add `is_enabled` method -- gpio: Drop GPIO Pin generics (API break) -- pwm: Allow specifying OutputDrive for PWM channels +## 0.2.0 - 2024-08-05 + +- Support for NRF chips: + - nrf51 + - nrf9151 +- Support for new peripherals: + - EGU + - radio - low-level support for IEEE 802.15.4 and BLE via radio peripheral +- Peripheral changes: + - gpio: Drop GPIO Pin generics (API break) + - pdm: Fix gain register value derivation + - pwm: + - Expose `duty` method + - Expose `pwm::PWM_CLK_HZ` and add `is_enabled` method + - Allow specifying OutputDrive for PWM channels + - Fix infinite loop + - spim: + - Reduce trace-level messages ("Copying SPIM tx buffer..") + - Support configuring bit order for bus + - Allow specifying OutputDrive for SPI pins + - Add bounds checks for EasyDMA buffer size + - Implement chunked DMA transfers + - uart: + - Add support for rx- or tx-only BufferedUart + - Implement splitting Rx/Tx + - Add support for handling RX errors +- Miscellaneous changes: + - Add `collapse_debuginfo` to fmt.rs macros. + - Drop `sealed` mod + - nrf52840: Add dcdc voltage parameter to configure REG0 regulator ## 0.1.0 - 2024-01-12 diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 02c3bfbbe..bc0a9d199 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-nrf" -version = "0.1.0" +version = "0.2.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for nRF series microcontrollers" @@ -40,6 +40,7 @@ rt = [ "nrf5340-app-pac?/rt", "nrf5340-net-pac?/rt", "nrf9160-pac?/rt", + "nrf9120-pac?/rt", ] ## Enable features requiring `embassy-time` @@ -96,9 +97,18 @@ nrf5340-app-ns = ["_nrf5340-app", "_ns"] ## nRF5340 network core nrf5340-net = ["_nrf5340-net"] ## nRF9160 in Secure mode -nrf9160-s = ["_nrf9160", "_s"] +nrf9160-s = ["_nrf9160", "_s", "_nrf91"] ## nRF9160 in Non-Secure mode -nrf9160-ns = ["_nrf9160", "_ns"] +nrf9160-ns = ["_nrf9160", "_ns", "_nrf91"] +## The nRF9120 is the internal part number for the nRF9161 and nRF9151. +## nRF9120 in Secure mode +nrf9120-s = ["_nrf9120", "_s", "_nrf91"] +nrf9151-s = ["_nrf9120", "_s", "_nrf91"] +nrf9161-s = ["_nrf9120", "_s", "_nrf91"] +## nRF9120 in Non-Secure mode +nrf9120-ns = ["_nrf9120", "_ns", "_nrf91"] +nrf9151-ns = ["_nrf9120", "_ns", "_nrf91"] +nrf9161-ns = ["_nrf9120", "_ns", "_nrf91"] # Features starting with `_` are for internal use only. They're not intended # to be enabled by other crates, and are not covered by semver guarantees. @@ -107,8 +117,10 @@ _nrf5340-app = ["_nrf5340", "nrf5340-app-pac"] _nrf5340-net = ["_nrf5340", "nrf5340-net-pac"] _nrf5340 = ["_gpio-p1", "_dppi"] _nrf9160 = ["nrf9160-pac", "_dppi"] +_nrf9120 = ["nrf9120-pac", "_dppi"] _nrf52 = ["_ppi"] _nrf51 = ["_ppi"] +_nrf91 = [] _time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-32_768"] @@ -125,10 +137,10 @@ _nrf52832_anomaly_109 = [] [dependencies] embassy-time-driver = { version = "0.1", path = "../embassy-time-driver", optional = true } -embassy-time = { version = "0.3.1", path = "../embassy-time", optional = true } +embassy-time = { version = "0.3.2", path = "../embassy-time", optional = true } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } -embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } +embassy-hal-internal = {version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } +embassy-embedded-hal = {version = "0.2.0", path = "../embassy-embedded-hal" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } @@ -161,3 +173,4 @@ nrf52840-pac = { version = "0.12.0", optional = true } nrf5340-app-pac = { version = "0.12.0", optional = true } nrf5340-net-pac = { version = "0.12.0", optional = true } nrf9160-pac = { version = "0.12.0", optional = true } +nrf9120-pac = { version = "0.12.0", optional = true } diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 8e4064aaa..b368a3d33 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -766,6 +766,12 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { rx.pop_done(amt); U::regs().intenset.write(|w| w.rxstarted().set()); } + + /// we are ready to read if there is data in the buffer + fn read_ready() -> Result { + let state = U::buffered_state(); + Ok(!state.rx_buf.is_empty()) + } } impl<'a, U: UarteInstance, T: TimerInstance> Drop for BufferedUarteRx<'a, U, T> { @@ -827,6 +833,18 @@ mod _embedded_io { } } + impl<'d, U: UarteInstance, T: TimerInstance + 'd> embedded_io_async::ReadReady for BufferedUarte<'d, U, T> { + fn read_ready(&mut self) -> Result { + BufferedUarteRx::<'d, U, T>::read_ready() + } + } + + impl<'d, U: UarteInstance, T: TimerInstance + 'd> embedded_io_async::ReadReady for BufferedUarteRx<'d, U, T> { + fn read_ready(&mut self) -> Result { + Self::read_ready() + } + } + impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::BufRead for BufferedUarte<'d, U, T> { async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { self.fill_buf().await diff --git a/embassy-nrf/src/chips/nrf9120.rs b/embassy-nrf/src/chips/nrf9120.rs new file mode 100644 index 000000000..b53510118 --- /dev/null +++ b/embassy-nrf/src/chips/nrf9120.rs @@ -0,0 +1,430 @@ +/// Peripheral Access Crate +#[allow(unused_imports)] +#[rustfmt::skip] +pub mod pac { + // The nRF9120 has a secure and non-secure (NS) mode. + // To avoid cfg spam, we remove _ns or _s suffixes here. + + pub use nrf9120_pac::NVIC_PRIO_BITS; + + #[cfg(feature="rt")] + #[doc(no_inline)] + pub use nrf9120_pac::interrupt; + + #[doc(no_inline)] + pub use nrf9120_pac::{ + Interrupt, + + cc_host_rgf_s as cc_host_rgf, + clock_ns as clock, + cryptocell_s as cryptocell, + ctrl_ap_peri_s as ctrl_ap_peri, + dppic_ns as dppic, + egu0_ns as egu0, + ficr_s as ficr, + fpu_ns as fpu, + gpiote0_s as gpiote, + i2s_ns as i2s, + ipc_ns as ipc, + kmu_ns as kmu, + nvmc_ns as nvmc, + p0_ns as p0, + pdm_ns as pdm, + power_ns as power, + pwm0_ns as pwm0, + regulators_ns as regulators, + rtc0_ns as rtc0, + saadc_ns as saadc, + spim0_ns as spim0, + spis0_ns as spis0, + spu_s as spu, + tad_s as tad, + timer0_ns as timer0, + twim0_ns as twim0, + twis0_ns as twis0, + uarte0_ns as uarte0, + uicr_s as uicr, + vmc_ns as vmc, + wdt_ns as wdt, + }; + + /// Non-Secure mode (NS) peripherals + pub mod ns { + #[doc(no_inline)] + pub use nrf9120_pac::{ + CLOCK_NS as CLOCK, + DPPIC_NS as DPPIC, + EGU0_NS as EGU0, + EGU1_NS as EGU1, + EGU2_NS as EGU2, + EGU3_NS as EGU3, + EGU4_NS as EGU4, + EGU5_NS as EGU5, + FPU_NS as FPU, + GPIOTE1_NS as GPIOTE1, + I2S_NS as I2S, + IPC_NS as IPC, + KMU_NS as KMU, + NVMC_NS as NVMC, + P0_NS as P0, + PDM_NS as PDM, + POWER_NS as POWER, + PWM0_NS as PWM0, + PWM1_NS as PWM1, + PWM2_NS as PWM2, + PWM3_NS as PWM3, + REGULATORS_NS as REGULATORS, + RTC0_NS as RTC0, + RTC1_NS as RTC1, + SAADC_NS as SAADC, + SPIM0_NS as SPIM0, + SPIM1_NS as SPIM1, + SPIM2_NS as SPIM2, + SPIM3_NS as SPIM3, + SPIS0_NS as SPIS0, + SPIS1_NS as SPIS1, + SPIS2_NS as SPIS2, + SPIS3_NS as SPIS3, + TIMER0_NS as TIMER0, + TIMER1_NS as TIMER1, + TIMER2_NS as TIMER2, + TWIM0_NS as TWIM0, + TWIM1_NS as TWIM1, + TWIM2_NS as TWIM2, + TWIM3_NS as TWIM3, + TWIS0_NS as TWIS0, + TWIS1_NS as TWIS1, + TWIS2_NS as TWIS2, + TWIS3_NS as TWIS3, + UARTE0_NS as UARTE0, + UARTE1_NS as UARTE1, + UARTE2_NS as UARTE2, + UARTE3_NS as UARTE3, + VMC_NS as VMC, + WDT_NS as WDT, + }; + } + + /// Secure mode (S) peripherals + pub mod s { + #[doc(no_inline)] + pub use nrf9120_pac::{ + CC_HOST_RGF_S as CC_HOST_RGF, + CLOCK_S as CLOCK, + CRYPTOCELL_S as CRYPTOCELL, + CTRL_AP_PERI_S as CTRL_AP_PERI, + DPPIC_S as DPPIC, + EGU0_S as EGU0, + EGU1_S as EGU1, + EGU2_S as EGU2, + EGU3_S as EGU3, + EGU4_S as EGU4, + EGU5_S as EGU5, + FICR_S as FICR, + FPU as FPU, + GPIOTE0_S as GPIOTE0, + I2S_S as I2S, + IPC_S as IPC, + KMU_S as KMU, + NVMC_S as NVMC, + P0_S as P0, + PDM_S as PDM, + POWER_S as POWER, + PWM0_S as PWM0, + PWM1_S as PWM1, + PWM2_S as PWM2, + PWM3_S as PWM3, + REGULATORS_S as REGULATORS, + RTC0_S as RTC0, + RTC1_S as RTC1, + SAADC_S as SAADC, + SPIM0_S as SPIM0, + SPIM1_S as SPIM1, + SPIM2_S as SPIM2, + SPIM3_S as SPIM3, + SPIS0_S as SPIS0, + SPIS1_S as SPIS1, + SPIS2_S as SPIS2, + SPIS3_S as SPIS3, + SPU_S as SPU, + TAD_S as TAD, + TIMER0_S as TIMER0, + TIMER1_S as TIMER1, + TIMER2_S as TIMER2, + TWIM0_S as TWIM0, + TWIM1_S as TWIM1, + TWIM2_S as TWIM2, + TWIM3_S as TWIM3, + TWIS0_S as TWIS0, + TWIS1_S as TWIS1, + TWIS2_S as TWIS2, + TWIS3_S as TWIS3, + UARTE0_S as UARTE0, + UARTE1_S as UARTE1, + UARTE2_S as UARTE2, + UARTE3_S as UARTE3, + UICR_S as UICR, + VMC_S as VMC, + WDT_S as WDT, + }; + } + + #[cfg(feature = "_ns")] + pub use ns::*; + #[cfg(feature = "_s")] + pub use s::*; +} + +/// The maximum buffer size that the EasyDMA can send/recv in one operation. +pub const EASY_DMA_SIZE: usize = (1 << 13) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; + +pub const FLASH_SIZE: usize = 1024 * 1024; + +embassy_hal_internal::peripherals! { + // RTC + RTC0, + RTC1, + + // WDT + WDT, + + // NVMC + NVMC, + + // UARTE, TWI & SPI + SERIAL0, + SERIAL1, + SERIAL2, + SERIAL3, + + // SAADC + SAADC, + + // PWM + PWM0, + PWM1, + PWM2, + PWM3, + + // TIMER + TIMER0, + TIMER1, + TIMER2, + + // GPIOTE + GPIOTE_CH0, + GPIOTE_CH1, + GPIOTE_CH2, + GPIOTE_CH3, + GPIOTE_CH4, + GPIOTE_CH5, + GPIOTE_CH6, + GPIOTE_CH7, + + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + PPI_GROUP4, + PPI_GROUP5, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + P0_07, + P0_08, + P0_09, + P0_10, + P0_11, + P0_12, + P0_13, + P0_14, + P0_15, + P0_16, + P0_17, + P0_18, + P0_19, + P0_20, + P0_21, + P0_22, + P0_23, + P0_24, + P0_25, + P0_26, + P0_27, + P0_28, + P0_29, + P0_30, + P0_31, + + // PDM + PDM, + + // EGU + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, +} + +impl_uarte!(SERIAL0, UARTE0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0); +impl_uarte!(SERIAL1, UARTE1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1); +impl_uarte!(SERIAL2, UARTE2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2); +impl_uarte!(SERIAL3, UARTE3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3); + +impl_spim!(SERIAL0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0); +impl_spim!(SERIAL1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1); +impl_spim!(SERIAL2, SPIM2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2); +impl_spim!(SERIAL3, SPIM3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3); + +impl_spis!(SERIAL0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0); +impl_spis!(SERIAL1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1); +impl_spis!(SERIAL2, SPIS2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2); +impl_spis!(SERIAL3, SPIS3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3); + +impl_twim!(SERIAL0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0); +impl_twim!(SERIAL1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1); +impl_twim!(SERIAL2, TWIM2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2); +impl_twim!(SERIAL3, TWIM3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3); + +impl_twis!(SERIAL0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0); +impl_twis!(SERIAL1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1); +impl_twis!(SERIAL2, TWIS2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2); +impl_twis!(SERIAL3, TWIS3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3); + +impl_pwm!(PWM0, PWM0, PWM0); +impl_pwm!(PWM1, PWM1, PWM1); +impl_pwm!(PWM2, PWM2, PWM2); +impl_pwm!(PWM3, PWM3, PWM3); + +impl_pdm!(PDM, PDM, PDM); + +impl_timer!(TIMER0, TIMER0, TIMER0); +impl_timer!(TIMER1, TIMER1, TIMER1); +impl_timer!(TIMER2, TIMER2, TIMER2); + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); +impl_pin!(P0_07, 0, 7); +impl_pin!(P0_08, 0, 8); +impl_pin!(P0_09, 0, 9); +impl_pin!(P0_10, 0, 10); +impl_pin!(P0_11, 0, 11); +impl_pin!(P0_12, 0, 12); +impl_pin!(P0_13, 0, 13); +impl_pin!(P0_14, 0, 14); +impl_pin!(P0_15, 0, 15); +impl_pin!(P0_16, 0, 16); +impl_pin!(P0_17, 0, 17); +impl_pin!(P0_18, 0, 18); +impl_pin!(P0_19, 0, 19); +impl_pin!(P0_20, 0, 20); +impl_pin!(P0_21, 0, 21); +impl_pin!(P0_22, 0, 22); +impl_pin!(P0_23, 0, 23); +impl_pin!(P0_24, 0, 24); +impl_pin!(P0_25, 0, 25); +impl_pin!(P0_26, 0, 26); +impl_pin!(P0_27, 0, 27); +impl_pin!(P0_28, 0, 28); +impl_pin!(P0_29, 0, 29); +impl_pin!(P0_30, 0, 30); +impl_pin!(P0_31, 0, 31); + +impl_ppi_channel!(PPI_CH0, 0 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH10, 10 => configurable); +impl_ppi_channel!(PPI_CH11, 11 => configurable); +impl_ppi_channel!(PPI_CH12, 12 => configurable); +impl_ppi_channel!(PPI_CH13, 13 => configurable); +impl_ppi_channel!(PPI_CH14, 14 => configurable); +impl_ppi_channel!(PPI_CH15, 15 => configurable); + +impl_saadc_input!(P0_13, ANALOG_INPUT0); +impl_saadc_input!(P0_14, ANALOG_INPUT1); +impl_saadc_input!(P0_15, ANALOG_INPUT2); +impl_saadc_input!(P0_16, ANALOG_INPUT3); +impl_saadc_input!(P0_17, ANALOG_INPUT4); +impl_saadc_input!(P0_18, ANALOG_INPUT5); +impl_saadc_input!(P0_19, ANALOG_INPUT6); +impl_saadc_input!(P0_20, ANALOG_INPUT7); + +impl_egu!(EGU0, EGU0, EGU0); +impl_egu!(EGU1, EGU1, EGU1); +impl_egu!(EGU2, EGU2, EGU2); +impl_egu!(EGU3, EGU3, EGU3); +impl_egu!(EGU4, EGU4, EGU4); +impl_egu!(EGU5, EGU5, EGU5); + +embassy_hal_internal::interrupt_mod!( + SPU, + CLOCK_POWER, + SPIM0_SPIS0_TWIM0_TWIS0_UARTE0, + SPIM1_SPIS1_TWIM1_TWIS1_UARTE1, + SPIM2_SPIS2_TWIM2_TWIS2_UARTE2, + SPIM3_SPIS3_TWIM3_TWIS3_UARTE3, + GPIOTE0, + SAADC, + TIMER0, + TIMER1, + TIMER2, + RTC0, + RTC1, + WDT, + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, + PWM0, + PWM1, + PWM2, + PDM, + PWM3, + I2S, + IPC, + FPU, + GPIOTE1, + KMU, + CRYPTOCELL, +); diff --git a/embassy-nrf/src/fmt.rs b/embassy-nrf/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-nrf/src/fmt.rs +++ b/embassy-nrf/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index a74b3157b..9d97c7be9 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -53,9 +53,9 @@ pub enum OutputChannelPolarity { fn regs() -> &'static pac::gpiote::RegisterBlock { cfg_if::cfg_if! { - if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s"))] { + if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s", feature="nrf9120-s"))] { unsafe { &*pac::GPIOTE0::ptr() } - } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns"))] { + } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns", feature="nrf9120-ns"))] { unsafe { &*pac::GPIOTE1::ptr() } } else { unsafe { &*pac::GPIOTE::ptr() } @@ -81,9 +81,9 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) { } // Enable interrupts - #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))] + #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))] let irq = interrupt::GPIOTE0; - #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))] + #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))] let irq = interrupt::GPIOTE1; #[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))] let irq = interrupt::GPIOTE; @@ -96,14 +96,14 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) { g.intenset.write(|w| w.port().set()); } -#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))] +#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))] #[cfg(feature = "rt")] #[interrupt] fn GPIOTE0() { unsafe { handle_gpiote_interrupt() }; } -#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))] +#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))] #[cfg(feature = "rt")] #[interrupt] fn GPIOTE1() { diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 05b52f687..13623dd1c 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -24,8 +24,36 @@ feature = "nrf5340-net", feature = "nrf9160-s", feature = "nrf9160-ns", + feature = "nrf9120-s", + feature = "nrf9120-ns", + feature = "nrf9151-s", + feature = "nrf9151-ns", + feature = "nrf9161-s", + feature = "nrf9161-ns", )))] -compile_error!("No chip feature activated. You must activate exactly one of the following features: nrf52810, nrf52811, nrf52832, nrf52833, nrf52840"); +compile_error!( + "No chip feature activated. You must activate exactly one of the following features: + nrf51, + nrf52805, + nrf52810, + nrf52811, + nrf52820, + nrf52832, + nrf52833, + nrf52840, + nrf5340-app-s, + nrf5340-app-ns, + nrf5340-net, + nrf9160-s, + nrf9160-ns, + nrf9120-s, + nrf9120-ns, + nrf9151-s, + nrf9151-ns, + nrf9161-s, + nrf9161-ns, + " +); #[cfg(all(feature = "reset-pin-as-gpio", not(feature = "_nrf52")))] compile_error!("feature `reset-pin-as-gpio` is only valid for nRF52 series chips."); @@ -47,7 +75,7 @@ pub mod gpio; pub mod gpiote; // TODO: tested on other chips -#[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340-app")))] +#[cfg(not(any(feature = "_nrf91", feature = "_nrf5340-app")))] pub mod radio; #[cfg(not(feature = "nrf51"))] @@ -62,7 +90,7 @@ pub mod nvmc; feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340-app", - feature = "_nrf9160" + feature = "_nrf91", ))] pub mod pdm; pub mod ppi; @@ -73,11 +101,11 @@ pub mod ppi; feature = "_nrf5340-net" )))] pub mod pwm; -#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))] +#[cfg(not(any(feature = "nrf51", feature = "_nrf91", feature = "_nrf5340-net")))] pub mod qdec; #[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))] pub mod qspi; -#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))] +#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] pub mod rng; #[cfg(not(any(feature = "nrf51", feature = "nrf52820", feature = "_nrf5340-net")))] pub mod saadc; @@ -85,7 +113,7 @@ pub mod saadc; pub mod spim; #[cfg(not(feature = "nrf51"))] pub mod spis; -#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] +#[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] pub mod temp; pub mod timer; #[cfg(not(feature = "nrf51"))] @@ -116,6 +144,7 @@ pub mod wdt; #[cfg_attr(feature = "_nrf5340-app", path = "chips/nrf5340_app.rs")] #[cfg_attr(feature = "_nrf5340-net", path = "chips/nrf5340_net.rs")] #[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")] +#[cfg_attr(feature = "_nrf9120", path = "chips/nrf9120.rs")] mod chip; /// Macro to bind interrupts to handlers. @@ -196,15 +225,15 @@ pub mod config { /// Internal RC oscillator InternalRC, /// Synthesized from the high frequency clock source. - #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] + #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] Synthesized, /// External source from xtal. ExternalXtal, /// External source from xtal with low swing applied. - #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] + #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] ExternalLowSwing, /// External source from xtal with full swing applied. - #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] + #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] ExternalFullSwing, } @@ -222,7 +251,7 @@ pub mod config { } /// Settings for enabling the built in DCDC converters. - #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] + #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] pub struct DcdcConfig { /// Config for the first stage DCDC (VDDH -> VDD), if disabled LDO will be used. #[cfg(feature = "nrf52840")] @@ -264,7 +293,7 @@ pub mod config { } /// Settings for enabling the built in DCDC converter. - #[cfg(feature = "_nrf9160")] + #[cfg(feature = "_nrf91")] pub struct DcdcConfig { /// Config for the main rail, if disabled LDO will be used. pub regmain: bool, @@ -298,7 +327,7 @@ pub mod config { // xtals if they know they have them. hfclk_source: HfclkSource::Internal, lfclk_source: LfclkSource::InternalRC, - #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] + #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] dcdc: DcdcConfig { #[cfg(feature = "nrf52840")] reg0: false, @@ -312,7 +341,7 @@ pub mod config { regmain: false, regradio: false, }, - #[cfg(feature = "_nrf9160")] + #[cfg(feature = "_nrf91")] dcdc: DcdcConfig { regmain: false }, #[cfg(feature = "gpiote")] gpiote_interrupt_priority: crate::interrupt::Priority::P0, @@ -329,7 +358,7 @@ pub mod config { } } -#[cfg(feature = "_nrf9160")] +#[cfg(feature = "_nrf91")] #[allow(unused)] mod consts { pub const UICR_APPROTECT: *mut u32 = 0x00FF8000 as *mut u32; @@ -468,7 +497,7 @@ pub fn init(config: config::Config) -> Peripherals { // UICR.APPROTECT = Enabled let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_ENABLED); needs_reset |= res == WriteResult::Written; - #[cfg(any(feature = "_nrf5340-app", feature = "_nrf9160"))] + #[cfg(any(feature = "_nrf5340-app", feature = "_nrf91"))] { let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_ENABLED); needs_reset |= res == WriteResult::Written; @@ -552,7 +581,7 @@ pub fn init(config: config::Config) -> Peripherals { } // Configure LFCLK. - #[cfg(not(any(feature = "nrf51", feature = "_nrf5340", feature = "_nrf9160")))] + #[cfg(not(any(feature = "nrf51", feature = "_nrf5340", feature = "_nrf91")))] match config.lfclk_source { config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()), config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()), @@ -572,7 +601,7 @@ pub fn init(config: config::Config) -> Peripherals { w }), } - #[cfg(feature = "_nrf9160")] + #[cfg(feature = "_nrf91")] match config.lfclk_source { config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().lfrc()), config::LfclkSource::ExternalXtal => r.lfclksrc.write(|w| w.src().lfxo()), @@ -585,7 +614,7 @@ pub fn init(config: config::Config) -> Peripherals { r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); while r.events_lfclkstarted.read().bits() == 0 {} - #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] + #[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] { // Setup DCDCs. let pwr = unsafe { &*pac::POWER::ptr() }; @@ -597,7 +626,7 @@ pub fn init(config: config::Config) -> Peripherals { pwr.dcdcen.write(|w| w.dcdcen().set_bit()); } } - #[cfg(feature = "_nrf9160")] + #[cfg(feature = "_nrf91")] { // Setup DCDC. let reg = unsafe { &*pac::REGULATORS::ptr() }; @@ -629,7 +658,7 @@ pub fn init(config: config::Config) -> Peripherals { time_driver::init(config.time_interrupt_priority); // Disable UARTE (enabled by default for some reason) - #[cfg(feature = "_nrf9160")] + #[cfg(feature = "_nrf91")] unsafe { (*pac::UARTE0::ptr()).enable.write(|w| w.enable().disabled()); (*pac::UARTE1::ptr()).enable.write(|w| w.enable().disabled()); diff --git a/embassy-nrf/src/nvmc.rs b/embassy-nrf/src/nvmc.rs index 4f9eda167..9b17e7da0 100644 --- a/embassy-nrf/src/nvmc.rs +++ b/embassy-nrf/src/nvmc.rs @@ -60,23 +60,23 @@ impl<'d> Nvmc<'d> { while p.ready.read().ready().is_busy() {} } - #[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340")))] + #[cfg(not(any(feature = "_nrf91", feature = "_nrf5340")))] fn wait_ready_write(&mut self) { self.wait_ready(); } - #[cfg(any(feature = "_nrf9160", feature = "_nrf5340"))] + #[cfg(any(feature = "_nrf91", feature = "_nrf5340"))] fn wait_ready_write(&mut self) { let p = Self::regs(); while p.readynext.read().readynext().is_busy() {} } - #[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340")))] + #[cfg(not(any(feature = "_nrf91", feature = "_nrf5340")))] fn erase_page(&mut self, page_addr: u32) { Self::regs().erasepage().write(|w| unsafe { w.bits(page_addr) }); } - #[cfg(any(feature = "_nrf9160", feature = "_nrf5340"))] + #[cfg(any(feature = "_nrf91", feature = "_nrf5340"))] fn erase_page(&mut self, page_addr: u32) { let first_page_word = page_addr as *mut u32; unsafe { diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index c1501e02e..5160fe3c4 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -21,7 +21,7 @@ pub use crate::pac::pdm::pdmclkctrl::FREQ_A as Frequency; feature = "nrf52840", feature = "nrf52833", feature = "_nrf5340-app", - feature = "_nrf9160", + feature = "_nrf91", ))] pub use crate::pac::pdm::ratio::RATIO_A as Ratio; use crate::{interrupt, Peripheral}; @@ -121,7 +121,7 @@ impl<'d, T: Instance> Pdm<'d, T> { feature = "nrf52840", feature = "nrf52833", feature = "_nrf5340-app", - feature = "_nrf9160", + feature = "_nrf91", ))] r.ratio.write(|w| w.ratio().variant(config.ratio)); r.mode.write(|w| { @@ -374,7 +374,7 @@ pub struct Config { feature = "nrf52840", feature = "nrf52833", feature = "_nrf5340-app", - feature = "_nrf9160", + feature = "_nrf91", ))] pub ratio: Ratio, /// Gain left in dB @@ -393,7 +393,7 @@ impl Default for Config { feature = "nrf52840", feature = "nrf52833", feature = "_nrf5340-app", - feature = "_nrf9160", + feature = "_nrf91", ))] ratio: Ratio::RATIO80, gain_left: I7F1::ZERO, diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index 17c65fa3e..a3a5b9cfe 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -722,9 +722,9 @@ macro_rules! impl_saadc_input { pub struct VddInput; impl_peripheral!(VddInput); -#[cfg(not(feature = "_nrf9160"))] +#[cfg(not(feature = "_nrf91"))] impl_saadc_input!(@local, VddInput, VDD); -#[cfg(feature = "_nrf9160")] +#[cfg(feature = "_nrf91")] impl_saadc_input!(@local, VddInput, VDDGPIO); /// A dummy `Input` pin implementation for SAADC peripheral sampling from the diff --git a/embassy-nrf/src/wdt.rs b/embassy-nrf/src/wdt.rs index 40a674424..5a261ce8f 100644 --- a/embassy-nrf/src/wdt.rs +++ b/embassy-nrf/src/wdt.rs @@ -30,9 +30,9 @@ impl Config { pub fn try_new(_wdt: &peripherals::WDT) -> Option { let r = unsafe { &*WDT::ptr() }; - #[cfg(not(feature = "_nrf9160"))] + #[cfg(not(feature = "_nrf91"))] let runstatus = r.runstatus.read().runstatus().bit(); - #[cfg(feature = "_nrf9160")] + #[cfg(feature = "_nrf91")] let runstatus = r.runstatus.read().runstatuswdt().bit(); if runstatus { @@ -83,9 +83,9 @@ impl Watchdog { let crv = config.timeout_ticks.max(MIN_TICKS); let rren = (1u32 << N) - 1; - #[cfg(not(feature = "_nrf9160"))] + #[cfg(not(feature = "_nrf91"))] let runstatus = r.runstatus.read().runstatus().bit(); - #[cfg(feature = "_nrf9160")] + #[cfg(feature = "_nrf91")] let runstatus = r.runstatus.read().runstatuswdt().bit(); if runstatus { diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md new file mode 100644 index 000000000..7eef64292 --- /dev/null +++ b/embassy-rp/CHANGELOG.md @@ -0,0 +1,32 @@ +# Changelog for embassy-rp + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## 0.2.0 - 2024-08-05 + +- Add read_to_break_with_count +- add option to provide your own boot2 +- Add multichannel ADC +- Add collapse_debuginfo to fmt.rs macros. +- Use raw slices .len() method instead of unsafe hacks. +- Add missing word "pin" in rp pwm documentation +- Add Clone and Copy to Error types +- fix spinlocks staying locked after reset. +- wait until read matches for PSM accesses. +- Remove generics +- fix drop implementation of BufferedUartRx and BufferedUartTx +- implement `embedded_storage_async::nor_flash::MultiwriteNorFlash` +- rp usb: wake ep-wakers after stalling +- rp usb: add stall implementation +- Add parameter for enabling pull-up and pull-down in RP PWM input mode +- rp: remove mod sealed. +- rename pins data type and the macro +- rename pwm channels to pwm slices, including in documentation +- rename the Channel trait to Slice and the PwmPin to PwmChannel +- i2c: Fix race condition that appears on fast repeated transfers. +- Add a basic "read to break" function diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 447c96b4d..f6c0fba2d 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-rp" -version = "0.1.0" +version = "0.2.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for the Raspberry Pi RP2040 microcontroller" @@ -91,10 +91,10 @@ boot2-none = [] [dependencies] embassy-sync = { version = "0.6.0", path = "../embassy-sync" } embassy-time-driver = { version = "0.1", path = "../embassy-time-driver", optional = true } -embassy-time = { version = "0.3.1", path = "../embassy-time" } +embassy-time = { version = "0.3.2", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } +embassy-hal-internal = {version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } +embassy-embedded-hal = {version = "0.2.0", path = "../embassy-embedded-hal" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" defmt = { version = "0.3", optional = true } @@ -125,5 +125,5 @@ rp2040-boot2 = "0.3" document-features = "0.2.7" [dev-dependencies] -embassy-executor = { version = "0.5.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] } +embassy-executor = { version = "0.6.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] } static_cell = { version = "2" } diff --git a/embassy-rp/README.md b/embassy-rp/README.md index 8cf7da994..16b189344 100644 --- a/embassy-rp/README.md +++ b/embassy-rp/README.md @@ -23,5 +23,5 @@ The `embassy-rp` HAL implements the traits from [embedded-hal](https://crates.io This crate can run on any executor. -Optionally, some features requiring [`embassy-time`](https://crates.io/crates/embassy-time) can be activated with the `time` feature. If you enable it, +Optionally, some features requiring [`embassy-time`](https://crates.io/crates/embassy-time) can be activated with the `time-driver` feature. If you enable it, you must link an `embassy-time` driver in your project. diff --git a/embassy-rp/src/bootsel.rs b/embassy-rp/src/bootsel.rs index 540255ae3..d24ce7bd8 100644 --- a/embassy-rp/src/bootsel.rs +++ b/embassy-rp/src/bootsel.rs @@ -57,9 +57,9 @@ mod ram_helpers { "str {val}, [{cs_gpio}, $GPIO_CTRL]", // ...then wait for the state to settle... - "1:", // ~4000 cycle delay loop + "2:", // ~4000 cycle delay loop "subs {val}, #8", - "bne 1b", + "bne 2b", // ...we can read the current state of bootsel "ldr {val}, [{cs_gpio}, $GPIO_STATUS]", diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 6e2a823d8..9e4542b2f 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -625,18 +625,18 @@ mod ram_helpers { "movs r3, #0", // r3 = 0 "ldr r4, [{ptrs}, #8]", "cmp r4, #0", - "beq 1f", + "beq 2f", "blx r4", // flash_range_erase(addr, len, 1 << 31, 0) - "1:", + "2:", "mov r0, r8", // r0 = addr "mov r1, r9", // r0 = data "mov r2, r10", // r2 = len "ldr r4, [{ptrs}, #12]", "cmp r4, #0", - "beq 1f", + "beq 2f", "blx r4", // flash_range_program(addr, data, len); - "1:", + "2:", "ldr r4, [{ptrs}, #16]", "blx r4", // flash_flush_cache(); @@ -802,12 +802,12 @@ mod ram_helpers { "adds r2, 0x60", // &DR "ldr r0, [r3, #0]", // cmd_addr "ldr r1, [r3, #4]", // cmd_addr_len - "10:", + "3:", "ldrb r3, [r0]", "strb r3, [r2]", // DR "adds r0, #1", "subs r1, #1", - "bne 10b", + "bne 3b", // Skip any dummy cycles "mov r3, r10", // cmd diff --git a/embassy-rp/src/fmt.rs b/embassy-rp/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-rp/src/fmt.rs +++ b/embassy-rp/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 10d3c86b3..ac2b1bc5a 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -312,13 +312,13 @@ impl<'d, T: Instance> I2c<'d, T, Async> { } } - /// Read from address into buffer using DMA. + /// Read from address into buffer asynchronously. pub async fn read_async(&mut self, addr: impl Into, buffer: &mut [u8]) -> Result<(), Error> { Self::setup(addr.into())?; self.read_async_internal(buffer, true, true).await } - /// Write to address from buffer using DMA. + /// Write to address from buffer asynchronously. pub async fn write_async( &mut self, addr: impl Into, @@ -328,7 +328,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { self.write_async_internal(bytes, true).await } - /// Write to address from bytes and read from address into buffer using DMA. + /// Write to address from bytes and read from address into buffer asynchronously. pub async fn write_read_async( &mut self, addr: impl Into, @@ -779,9 +779,6 @@ pub fn i2c_reserved_addr(addr: u16) -> bool { } pub(crate) trait SealedInstance { - const TX_DREQ: u8; - const RX_DREQ: u8; - fn regs() -> crate::pac::i2c::I2c; fn reset() -> crate::pac::resets::regs::Peripherals; fn waker() -> &'static AtomicWaker; @@ -816,11 +813,8 @@ pub trait Instance: SealedInstance { } macro_rules! impl_instance { - ($type:ident, $irq:ident, $reset:ident, $tx_dreq:expr, $rx_dreq:expr) => { + ($type:ident, $irq:ident, $reset:ident) => { impl SealedInstance for peripherals::$type { - const TX_DREQ: u8 = $tx_dreq; - const RX_DREQ: u8 = $rx_dreq; - #[inline] fn regs() -> pac::i2c::I2c { pac::$type @@ -846,8 +840,8 @@ macro_rules! impl_instance { }; } -impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33); -impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35); +impl_instance!(I2C0, I2C0_IRQ, set_i2c0); +impl_instance!(I2C1, I2C1_IRQ, set_i2c1); /// SDA pin. pub trait SdaPin: crate::gpio::Pin {} diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index c94164040..152a432c9 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs @@ -163,9 +163,21 @@ impl<'d, T: Instance> BufferedUart<'d, T> { self.tx.send_break(bits).await } + /// sets baudrate on runtime + pub fn set_baudrate(&mut self, baudrate: u32) { + super::Uart::<'d, T, Async>::set_baudrate_inner(baudrate); + } + /// Split into separate RX and TX handles. - pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) { - (self.rx, self.tx) + pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) { + (self.tx, self.rx) + } + + /// Split the Uart into a transmitter and receiver by mutable reference, + /// which is particularly useful when having two tasks correlating to + /// transmitting and receiving. + pub fn split_ref(&mut self) -> (&mut BufferedUartTx<'d, T>, &mut BufferedUartRx<'d, T>) { + (&mut self.tx, &mut self.rx) } } @@ -315,6 +327,12 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> { w.set_rtim(true); }); } + + /// we are ready to read if there is data in the buffer + fn read_ready() -> Result { + let state = T::buffered_state(); + Ok(!state.rx_buf.is_empty()) + } } impl<'d, T: Instance> BufferedUartTx<'d, T> { @@ -621,6 +639,18 @@ impl<'d, T: Instance + 'd> embedded_io_async::Read for BufferedUartRx<'d, T> { } } +impl<'d, T: Instance + 'd> embedded_io_async::ReadReady for BufferedUart<'d, T> { + fn read_ready(&mut self) -> Result { + BufferedUartRx::<'d, T>::read_ready() + } +} + +impl<'d, T: Instance + 'd> embedded_io_async::ReadReady for BufferedUartRx<'d, T> { + fn read_ready(&mut self) -> Result { + Self::read_ready() + } +} + impl<'d, T: Instance + 'd> embedded_io_async::BufRead for BufferedUart<'d, T> { async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { BufferedUartRx::<'d, T>::fill_buf().await diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 30ece15bd..d50f5b4d5 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -7,7 +7,7 @@ use atomic_polyfill::{AtomicU16, Ordering}; use embassy_futures::select::{select, Either}; use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; -use embassy_time::Timer; +use embassy_time::{Delay, Timer}; use pac::uart::regs::Uartris; use crate::clocks::clk_peri_freq; @@ -490,6 +490,36 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { /// * The first call to `read_to_break()` will return `Ok(20)`. /// * The next call to `read_to_break()` will work as expected pub async fn read_to_break(&mut self, buffer: &mut [u8]) -> Result { + self.read_to_break_with_count(buffer, 0).await + } + + /// Read from the UART, waiting for a line break as soon as at least `min_count` bytes have been read. + /// + /// We read until one of the following occurs: + /// + /// * We read `buffer.len()` bytes without a line break + /// * returns `Err(ReadToBreakError::MissingBreak(buffer.len()))` + /// * We read `n > min_count` bytes then a line break occurs + /// * returns `Ok(n)` + /// * We encounter some error OTHER than a line break + /// * returns `Err(ReadToBreakError::Other(error))` + /// + /// If a line break occurs before `min_count` bytes have been read, the break will be ignored and the read will continue + /// + /// **NOTE**: you MUST provide a buffer one byte larger than your largest expected + /// message to reliably detect the framing on one single call to `read_to_break()`. + /// + /// * If you expect a message of 20 bytes + line break, and provide a 20-byte buffer: + /// * The first call to `read_to_break()` will return `Err(ReadToBreakError::MissingBreak(20))` + /// * The next call to `read_to_break()` will immediately return `Ok(0)`, from the "stale" line break + /// * If you expect a message of 20 bytes + line break, and provide a 21-byte buffer: + /// * The first call to `read_to_break()` will return `Ok(20)`. + /// * The next call to `read_to_break()` will work as expected + pub async fn read_to_break_with_count( + &mut self, + buffer: &mut [u8], + min_count: usize, + ) -> Result { // clear error flags before we drain the fifo. errors that have accumulated // in the flags will also be present in the fifo. T::dma_state().rx_errs.store(0, Ordering::Relaxed); @@ -502,7 +532,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { // then drain the fifo. we need to read at most 32 bytes. errors that apply // to fifo bytes will be reported directly. - let sbuffer = match { + let mut sbuffer = match { let limit = buffer.len().min(32); self.drain_fifo(&mut buffer[0..limit]) } { @@ -511,7 +541,13 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { // Drained (some/all of the fifo), no room left Ok(len) => return Err(ReadToBreakError::MissingBreak(len)), // We got a break WHILE draining the FIFO, return what we did get before the break - Err((i, Error::Break)) => return Ok(i), + Err((len, Error::Break)) => { + if len < min_count && len < buffer.len() { + &mut buffer[len..] + } else { + return Ok(len); + } + } // Some other error, just return the error Err((_i, e)) => return Err(ReadToBreakError::Other(e)), }; @@ -530,110 +566,118 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { reg.set_rxdmae(true); reg.set_dmaonerr(true); }); - let transfer = unsafe { - // If we don't assign future to a variable, the data register pointer - // is held across an await and makes the future non-Send. - crate::dma::read(&mut ch, T::regs().uartdr().as_ptr() as *const _, sbuffer, T::RX_DREQ) - }; - // wait for either the transfer to complete or an error to happen. - let transfer_result = select( - transfer, - poll_fn(|cx| { - T::dma_state().rx_err_waker.register(cx.waker()); - match T::dma_state().rx_errs.swap(0, Ordering::Relaxed) { - 0 => Poll::Pending, - e => Poll::Ready(Uartris(e as u32)), + loop { + let transfer = unsafe { + // If we don't assign future to a variable, the data register pointer + // is held across an await and makes the future non-Send. + crate::dma::read(&mut ch, T::regs().uartdr().as_ptr() as *const _, sbuffer, T::RX_DREQ) + }; + + // wait for either the transfer to complete or an error to happen. + let transfer_result = select( + transfer, + poll_fn(|cx| { + T::dma_state().rx_err_waker.register(cx.waker()); + match T::dma_state().rx_errs.swap(0, Ordering::Relaxed) { + 0 => Poll::Pending, + e => Poll::Ready(Uartris(e as u32)), + } + }), + ) + .await; + + // Figure out our error state + let errors = match transfer_result { + Either::First(()) => { + // We're here because the DMA finished, BUT if an error occurred on the LAST + // byte, then we may still need to grab the error state! + Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32) } - }), - ) - .await; - - // Figure out our error state - let errors = match transfer_result { - Either::First(()) => { - // We're here because the DMA finished, BUT if an error occurred on the LAST - // byte, then we may still need to grab the error state! - Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32) - } - Either::Second(e) => { - // We're here because we errored, which means this is the error that - // was problematic. - e - } - }; - - if errors.0 == 0 { - // No errors? That means we filled the buffer without a line break. - // For THIS function, that's a problem. - return Err(ReadToBreakError::MissingBreak(buffer.len())); - } else if errors.beris() { - // We got a Line Break! By this point, we've finished/aborted the DMA - // transaction, which means that we need to figure out where it left off - // by looking at the write_addr. - // - // First, we do a sanity check to make sure the write value is within the - // range of DMA we just did. - let sval = buffer.as_ptr() as usize; - let eval = sval + buffer.len(); - - // This is the address where the DMA would write to next - let next_addr = ch.regs().write_addr().read() as usize; - - // If we DON'T end up inside the range, something has gone really wrong. - // Note that it's okay that `eval` is one past the end of the slice, as - // this is where the write pointer will end up at the end of a full - // transfer. - if (next_addr < sval) || (next_addr > eval) { - unreachable!("UART DMA reported invalid `write_addr`"); - } - - let regs = T::regs(); - let all_full = next_addr == eval; - - // NOTE: This is off label usage of RSR! See the issue below for - // why I am not checking if there is an "extra" FIFO byte, and why - // I am checking RSR directly (it seems to report the status of the LAST - // POPPED value, rather than the NEXT TO POP value like the datasheet - // suggests!) - // - // issue: https://github.com/raspberrypi/pico-feedback/issues/367 - let last_was_break = regs.uartrsr().read().be(); - - return match (all_full, last_was_break) { - (true, true) | (false, _) => { - // We got less than the full amount + a break, or the full amount - // and the last byte was a break. Subtract the break off by adding one to sval. - Ok(next_addr.saturating_sub(1 + sval)) - } - (true, false) => { - // We finished the whole DMA, and the last DMA'd byte was NOT a break - // character. This is an error. - // - // NOTE: we COULD potentially return Ok(buffer.len()) here, since we - // know a line break occured at SOME POINT after the DMA completed. - // - // However, we have no way of knowing if there was extra data BEFORE - // that line break, so instead return an Err to signal to the caller - // that there are "leftovers", and they'll catch the actual line break - // on the next call. - // - // Doing it like this also avoids racyness: now whether you finished - // the full read BEFORE the line break occurred or AFTER the line break - // occurs, you still get `MissingBreak(buffer.len())` instead of sometimes - // getting `Ok(buffer.len())` if you were "late enough" to observe the - // line break. - Err(ReadToBreakError::MissingBreak(buffer.len())) + Either::Second(e) => { + // We're here because we errored, which means this is the error that + // was problematic. + e } }; - } else if errors.oeris() { - return Err(ReadToBreakError::Other(Error::Overrun)); - } else if errors.peris() { - return Err(ReadToBreakError::Other(Error::Parity)); - } else if errors.feris() { - return Err(ReadToBreakError::Other(Error::Framing)); + + if errors.0 == 0 { + // No errors? That means we filled the buffer without a line break. + // For THIS function, that's a problem. + return Err(ReadToBreakError::MissingBreak(buffer.len())); + } else if errors.beris() { + // We got a Line Break! By this point, we've finished/aborted the DMA + // transaction, which means that we need to figure out where it left off + // by looking at the write_addr. + // + // First, we do a sanity check to make sure the write value is within the + // range of DMA we just did. + let sval = buffer.as_ptr() as usize; + let eval = sval + buffer.len(); + + // This is the address where the DMA would write to next + let next_addr = ch.regs().write_addr().read() as usize; + + // If we DON'T end up inside the range, something has gone really wrong. + // Note that it's okay that `eval` is one past the end of the slice, as + // this is where the write pointer will end up at the end of a full + // transfer. + if (next_addr < sval) || (next_addr > eval) { + unreachable!("UART DMA reported invalid `write_addr`"); + } + + if (next_addr - sval) < min_count { + sbuffer = &mut buffer[(next_addr - sval)..]; + continue; + } + + let regs = T::regs(); + let all_full = next_addr == eval; + + // NOTE: This is off label usage of RSR! See the issue below for + // why I am not checking if there is an "extra" FIFO byte, and why + // I am checking RSR directly (it seems to report the status of the LAST + // POPPED value, rather than the NEXT TO POP value like the datasheet + // suggests!) + // + // issue: https://github.com/raspberrypi/pico-feedback/issues/367 + let last_was_break = regs.uartrsr().read().be(); + + return match (all_full, last_was_break) { + (true, true) | (false, _) => { + // We got less than the full amount + a break, or the full amount + // and the last byte was a break. Subtract the break off by adding one to sval. + Ok(next_addr.saturating_sub(1 + sval)) + } + (true, false) => { + // We finished the whole DMA, and the last DMA'd byte was NOT a break + // character. This is an error. + // + // NOTE: we COULD potentially return Ok(buffer.len()) here, since we + // know a line break occured at SOME POINT after the DMA completed. + // + // However, we have no way of knowing if there was extra data BEFORE + // that line break, so instead return an Err to signal to the caller + // that there are "leftovers", and they'll catch the actual line break + // on the next call. + // + // Doing it like this also avoids racyness: now whether you finished + // the full read BEFORE the line break occurred or AFTER the line break + // occurs, you still get `MissingBreak(buffer.len())` instead of sometimes + // getting `Ok(buffer.len())` if you were "late enough" to observe the + // line break. + Err(ReadToBreakError::MissingBreak(buffer.len())) + } + }; + } else if errors.oeris() { + return Err(ReadToBreakError::Other(Error::Overrun)); + } else if errors.peris() { + return Err(ReadToBreakError::Other(Error::Parity)); + } else if errors.feris() { + return Err(ReadToBreakError::Other(Error::Framing)); + } + unreachable!("unrecognized rx error"); } - unreachable!("unrecognized rx error"); } } @@ -860,6 +904,56 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> { }); } + fn lcr_modify(f: impl FnOnce(&mut rp_pac::uart::regs::UartlcrH) -> R) -> R { + let r = T::regs(); + + // Notes from PL011 reference manual: + // + // - Before writing the LCR, if the UART is enabled it needs to be + // disabled and any current TX + RX activity has to be completed + // + // - There is a BUSY flag which waits for the current TX char, but this is + // OR'd with TX FIFO !FULL, so not usable when FIFOs are enabled and + // potentially nonempty + // + // - FIFOs can't be set to disabled whilst a character is in progress + // (else "FIFO integrity is not guaranteed") + // + // Combination of these means there is no general way to halt and poll for + // end of TX character, if FIFOs may be enabled. Either way, there is no + // way to poll for end of RX character. + // + // So, insert a 15 Baud period delay before changing the settings. + // 15 Baud is comfortably higher than start + max data + parity + stop. + // Anything else would require API changes to permit a non-enabled UART + // state after init() where settings can be changed safely. + let clk_base = crate::clocks::clk_peri_freq(); + + let cr = r.uartcr().read(); + if cr.uarten() { + r.uartcr().modify(|w| { + w.set_uarten(false); + w.set_txe(false); + w.set_rxe(false); + }); + + // Note: Maximise precision here. Show working, the compiler will mop this up. + // Create a 16.6 fixed-point fractional division ratio; then scale to 32-bits. + let mut brdiv_ratio = 64 * r.uartibrd().read().0 + r.uartfbrd().read().0; + brdiv_ratio <<= 10; + // 3662 is ~(15 * 244.14) where 244.14 is 16e6 / 2^16 + let scaled_freq = clk_base / 3662; + let wait_time_us = brdiv_ratio / scaled_freq; + embedded_hal_1::delay::DelayNs::delay_us(&mut Delay, wait_time_us); + } + + let res = r.uartlcr_h().modify(f); + + r.uartcr().write_value(cr); + + res + } + /// sets baudrate on runtime pub fn set_baudrate(&mut self, baudrate: u32) { Self::set_baudrate_inner(baudrate); @@ -886,9 +980,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> { r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd)); r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd)); - // PL011 needs a (dummy) line control register write to latch in the - // divisors. We don't want to actually change LCR contents here. - r.uartlcr_h().modify(|_| {}); + Self::lcr_modify(|_| {}); } } @@ -923,6 +1015,13 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> { pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) { (self.tx, self.rx) } + + /// Split the Uart into a transmitter and receiver by mutable reference, + /// which is particularly useful when having two tasks correlating to + /// transmitting and receiving. + pub fn split_ref(&mut self) -> (&mut UartTx<'d, T, M>, &mut UartRx<'d, T, M>) { + (&mut self.tx, &mut self.rx) + } } impl<'d, T: Instance> Uart<'d, T, Async> { @@ -942,6 +1041,17 @@ impl<'d, T: Instance> Uart<'d, T, Async> { pub async fn read_to_break<'a>(&mut self, buf: &'a mut [u8]) -> Result { self.rx.read_to_break(buf).await } + + /// Read until the buffer is full or a line break occurs after at least `min_count` bytes have been read. + /// + /// See [`UartRx::read_to_break_with_count()`] for more details + pub async fn read_to_break_with_count<'a>( + &mut self, + buf: &'a mut [u8], + min_count: usize, + ) -> Result { + self.rx.read_to_break_with_count(buf, min_count).await + } } impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read for UartRx<'d, T, M> { diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 307b948c1..54dfd39a6 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -21,10 +21,10 @@ features = ["stm32wb55rg"] [dependencies] embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } -embassy-time = { version = "0.3.1", path = "../embassy-time", optional = true } +embassy-time = { version = "0.3.2", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-internal = { version = "0.1.0", path = "../embassy-hal-internal" } -embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } +embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal" } +embassy-embedded-hal = { version = "0.2.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } defmt = { version = "0.3", optional = true } diff --git a/embassy-stm32-wpan/src/fmt.rs b/embassy-stm32-wpan/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-stm32-wpan/src/fmt.rs +++ b/embassy-stm32-wpan/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 30f486ccc..ac9e9644c 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -43,15 +43,15 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] embassy-sync = { version = "0.6.0", path = "../embassy-sync" } -embassy-time = { version = "0.3.1", path = "../embassy-time", optional = true } +embassy-time = { version = "0.3.2", path = "../embassy-time", optional = true } embassy-time-driver = { version = "0.1", path = "../embassy-time-driver", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } -embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } +embassy-hal-internal = {version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } +embassy-embedded-hal = {version = "0.2.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver" } embassy-usb-synopsys-otg = {version = "0.1.0", path = "../embassy-usb-synopsys-otg" } -embassy-executor = { version = "0.5.0", path = "../embassy-executor", optional = true } +embassy-executor = { version = "0.6.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } diff --git a/embassy-stm32/build_common.rs b/embassy-stm32/build_common.rs index 0487eb3c5..4f24e6d37 100644 --- a/embassy-stm32/build_common.rs +++ b/embassy-stm32/build_common.rs @@ -8,8 +8,6 @@ use std::collections::HashSet; use std::env; -use std::ffi::OsString; -use std::process::Command; /// Helper for emitting cargo instruction for enabling configs (`cargo:rustc-cfg=X`) and declaring /// them (`cargo:rust-check-cfg=cfg(X)`). @@ -17,7 +15,6 @@ use std::process::Command; pub struct CfgSet { enabled: HashSet, declared: HashSet, - emit_declared: bool, } impl CfgSet { @@ -25,7 +22,6 @@ impl CfgSet { Self { enabled: HashSet::new(), declared: HashSet::new(), - emit_declared: is_rustc_nightly(), } } @@ -49,7 +45,7 @@ impl CfgSet { /// /// This enables rustc to check that the configs in `#[cfg(...)]` attributes are valid. pub fn declare(&mut self, cfg: impl AsRef) { - if self.declared.insert(cfg.as_ref().to_owned()) && self.emit_declared { + if self.declared.insert(cfg.as_ref().to_owned()) { println!("cargo:rustc-check-cfg=cfg({})", cfg.as_ref()); } } @@ -69,21 +65,6 @@ impl CfgSet { } } -fn is_rustc_nightly() -> bool { - if env::var_os("EMBASSY_FORCE_CHECK_CFG").is_some() { - return true; - } - - let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc")); - - let output = Command::new(rustc) - .arg("--version") - .output() - .expect("failed to run `rustc --version`"); - - String::from_utf8_lossy(&output.stdout).contains("nightly") -} - /// Sets configs that describe the target platform. pub fn set_target_cfgs(cfgs: &mut CfgSet) { let target = env::var("TARGET").unwrap(); diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index f20585ec3..2f36df240 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -2,6 +2,7 @@ #![macro_use] #![allow(missing_docs)] // TODO +#![cfg_attr(adc_f3_v2, allow(unused))] #[cfg(not(adc_f3_v2))] #[cfg_attr(adc_f1, path = "f1.rs")] diff --git a/embassy-stm32/src/flash/f1f3.rs b/embassy-stm32/src/flash/f1f3.rs index e66842e31..ff7f810ea 100644 --- a/embassy-stm32/src/flash/f1f3.rs +++ b/embassy-stm32/src/flash/f1f3.rs @@ -42,9 +42,11 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) // prevents parallelism errors fence(Ordering::SeqCst); + + wait_ready_blocking()?; } - wait_ready_blocking() + Ok(()) } pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index 7aea466e8..83b49a3dd 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -160,6 +160,26 @@ impl<'d, T: Instance> Fmc<'d, T> { ] )); + fmc_sdram_constructor!(sdram_a13bits_d32bits_4banks_bank1: ( + bank: stm32_fmc::SdramTargetBank::Bank1, + addr: [ + (a0: A0Pin), (a1: A1Pin), (a2: A2Pin), (a3: A3Pin), (a4: A4Pin), (a5: A5Pin), (a6: A6Pin), (a7: A7Pin), (a8: A8Pin), (a9: A9Pin), (a10: A10Pin), (a11: A11Pin), (a12: A12Pin) + ], + ba: [(ba0: BA0Pin), (ba1: BA1Pin)], + d: [ + (d0: D0Pin), (d1: D1Pin), (d2: D2Pin), (d3: D3Pin), (d4: D4Pin), (d5: D5Pin), (d6: D6Pin), (d7: D7Pin), + (d8: D8Pin), (d9: D9Pin), (d10: D10Pin), (d11: D11Pin), (d12: D12Pin), (d13: D13Pin), (d14: D14Pin), (d15: D15Pin), + (d16: D16Pin), (d17: D17Pin), (d18: D18Pin), (d19: D19Pin), (d20: D20Pin), (d21: D21Pin), (d22: D22Pin), (d23: D23Pin), + (d24: D24Pin), (d25: D25Pin), (d26: D26Pin), (d27: D27Pin), (d28: D28Pin), (d29: D29Pin), (d30: D30Pin), (d31: D31Pin) + ], + nbl: [ + (nbl0: NBL0Pin), (nbl1: NBL1Pin), (nbl2: NBL2Pin), (nbl3: NBL3Pin) + ], + ctrl: [ + (sdcke: SDCKE0Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE0Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin) + ] + )); + fmc_sdram_constructor!(sdram_a12bits_d16bits_4banks_bank2: ( bank: stm32_fmc::SdramTargetBank::Bank2, addr: [ @@ -197,6 +217,26 @@ impl<'d, T: Instance> Fmc<'d, T> { (sdcke: SDCKE1Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE1Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin) ] )); + + fmc_sdram_constructor!(sdram_a13bits_d32bits_4banks_bank2: ( + bank: stm32_fmc::SdramTargetBank::Bank2, + addr: [ + (a0: A0Pin), (a1: A1Pin), (a2: A2Pin), (a3: A3Pin), (a4: A4Pin), (a5: A5Pin), (a6: A6Pin), (a7: A7Pin), (a8: A8Pin), (a9: A9Pin), (a10: A10Pin), (a11: A11Pin), (a12: A12Pin) + ], + ba: [(ba0: BA0Pin), (ba1: BA1Pin)], + d: [ + (d0: D0Pin), (d1: D1Pin), (d2: D2Pin), (d3: D3Pin), (d4: D4Pin), (d5: D5Pin), (d6: D6Pin), (d7: D7Pin), + (d8: D8Pin), (d9: D9Pin), (d10: D10Pin), (d11: D11Pin), (d12: D12Pin), (d13: D13Pin), (d14: D14Pin), (d15: D15Pin), + (d16: D16Pin), (d17: D17Pin), (d18: D18Pin), (d19: D19Pin), (d20: D20Pin), (d21: D21Pin), (d22: D22Pin), (d23: D23Pin), + (d24: D24Pin), (d25: D25Pin), (d26: D26Pin), (d27: D27Pin), (d28: D28Pin), (d29: D29Pin), (d30: D30Pin), (d31: D31Pin) + ], + nbl: [ + (nbl0: NBL0Pin), (nbl1: NBL1Pin), (nbl2: NBL2Pin), (nbl3: NBL3Pin) + ], + ctrl: [ + (sdcke: SDCKE1Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE1Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin) + ] + )); } trait SealedInstance: crate::rcc::RccPeripheral { diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-stm32/src/fmt.rs +++ b/embassy-stm32/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-stm32/src/hsem/mod.rs b/embassy-stm32/src/hsem/mod.rs index b77a3415b..06ab7a9bc 100644 --- a/embassy-stm32/src/hsem/mod.rs +++ b/embassy-stm32/src/hsem/mod.rs @@ -158,6 +158,11 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> { .modify(|w| w.set_ise(sem_x, enable)); } + /// Gets the interrupt flag for the semaphore. + pub fn is_interrupt_active(&mut self, core_id: CoreId, sem_x: usize) -> bool { + T::regs().isr(core_id_to_index(core_id)).read().isf(sem_x) + } + /// Clears the interrupt flag for the semaphore. pub fn clear_interrupt(&mut self, core_id: CoreId, sem_x: usize) { T::regs() diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index ca94a573d..c86c18e22 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -45,6 +45,7 @@ pub struct OpAmpOutput<'d, T: Instance> { /// OpAmp internal outputs, wired directly to ADC inputs. /// /// This struct can be used as an ADC input. +#[cfg(opamp_g4)] pub struct OpAmpInternalOutput<'d, T: Instance> { _inner: &'d OpAmp<'d, T>, } @@ -80,11 +81,11 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// directly used as an ADC input. The opamp will be disabled when the /// [`OpAmpOutput`] is dropped. pub fn buffer_ext( - &'d mut self, + &mut self, in_pin: impl Peripheral

+ crate::gpio::Pin>, - out_pin: impl Peripheral

+ crate::gpio::Pin> + 'd, + out_pin: impl Peripheral

+ crate::gpio::Pin>, gain: OpAmpGain, - ) -> OpAmpOutput<'d, T> { + ) -> OpAmpOutput<'_, T> { into_ref!(in_pin); into_ref!(out_pin); in_pin.set_as_analog(); @@ -119,9 +120,9 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// [`OpAmpOutput`] is dropped. #[cfg(opamp_g4)] pub fn buffer_dac( - &'d mut self, - out_pin: impl Peripheral

+ crate::gpio::Pin> + 'd, - ) -> OpAmpOutput<'d, T> { + &mut self, + out_pin: impl Peripheral

+ crate::gpio::Pin>, + ) -> OpAmpOutput<'_, T> { into_ref!(out_pin); out_pin.set_as_analog(); @@ -147,10 +148,10 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// The opamp output will be disabled when it is dropped. #[cfg(opamp_g4)] pub fn buffer_int( - &'d mut self, + &mut self, pin: impl Peripheral

+ crate::gpio::Pin>, gain: OpAmpGain, - ) -> OpAmpInternalOutput<'d, T> { + ) -> OpAmpInternalOutput<'_, T> { into_ref!(pin); pin.set_as_analog(); @@ -184,6 +185,7 @@ impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> { } } +#[cfg(opamp_g4)] impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { fn drop(&mut self) { T::regs().csr().modify(|w| { diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index f6eb0d17c..289bfa672 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs @@ -1060,10 +1060,6 @@ pub(crate) trait SealedInstance { const REGS: Regs; } -trait SealedWord { - const CONFIG: u8; -} - /// OSPI instance trait. #[allow(private_bounds)] pub trait Instance: Peripheral

+ SealedInstance + RccPeripheral {} @@ -1110,17 +1106,14 @@ impl<'d, T: Instance, M: PeriMode> GetConfig for Ospi<'d, T, M> { /// Word sizes usable for OSPI. #[allow(private_bounds)] -pub trait Word: word::Word + SealedWord {} +pub trait Word: word::Word {} macro_rules! impl_word { - ($T:ty, $config:expr) => { - impl SealedWord for $T { - const CONFIG: u8 = $config; - } + ($T:ty) => { impl Word for $T {} }; } -impl_word!(u8, 8); -impl_word!(u16, 16); -impl_word!(u32, 32); +impl_word!(u8); +impl_word!(u16); +impl_word!(u32); diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index ee5539518..44ff9fcd5 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -94,6 +94,34 @@ impl DerefMut for DataBlock { } } +/// Command Block buffer for SDMMC command transfers. +/// +/// This is a 16-word array, exposed so that DMA commpatible memory can be used if required. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct CmdBlock(pub [u32; 16]); + +impl CmdBlock { + /// Creates a new instance of CmdBlock + pub const fn new() -> Self { + Self([0u32; 16]) + } +} + +impl Deref for CmdBlock { + type Target = [u32; 16]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for CmdBlock { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + /// Errors #[non_exhaustive] #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -292,6 +320,10 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma = NoDma> { signalling: Signalling, /// Card card: Option, + + /// An optional buffer to be used for commands + /// This should be used if there are special memory location requirements for dma + cmd_block: Option<&'d mut CmdBlock>, } const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh); @@ -495,6 +527,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { clock: SD_INIT_FREQ, signalling: Default::default(), card: None, + cmd_block: None, } } @@ -531,8 +564,10 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { /// # Safety /// /// `buffer` must be valid for the whole transfer and word aligned + #[allow(unused_variables)] fn prepare_datapath_read<'a>( - &'a mut self, + config: &Config, + dma: &'a mut PeripheralRef<'d, Dma>, buffer: &'a mut [u32], length_bytes: u32, block_size: u8, @@ -544,15 +579,14 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::wait_idle(); Self::clear_interrupt_flags(); - regs.dtimer() - .write(|w| w.set_datatime(self.config.data_transfer_timeout)); + regs.dtimer().write(|w| w.set_datatime(config.data_transfer_timeout)); regs.dlenr().write(|w| w.set_datalength(length_bytes)); #[cfg(sdmmc_v1)] let transfer = unsafe { - let request = self.dma.request(); + let request = dma.request(); Transfer::new_read( - &mut self.dma, + dma, request, regs.fifor().as_ptr() as *mut u32, buffer, @@ -692,13 +726,16 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Signalling::SDR12 => 0xFF_FF00, }; - let mut status = [0u32; 16]; + let status = match self.cmd_block.as_deref_mut() { + Some(x) => x, + None => &mut CmdBlock::new(), + }; // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); let on_drop = OnDrop::new(|| Self::on_drop()); - let transfer = self.prepare_datapath_read(&mut status, 64, 6); + let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); InterruptHandler::::data_interrupts(true); Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6 @@ -770,16 +807,21 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let card = self.card.as_mut().ok_or(Error::NoCard)?; let rca = card.rca; + let cmd_block = match self.cmd_block.as_deref_mut() { + Some(x) => x, + None => &mut CmdBlock::new(), + }; + Self::cmd(Cmd::set_block_length(64), false)?; // CMD16 Self::cmd(Cmd::app_cmd(rca << 16), false)?; // APP - let mut status = [0u32; 16]; + let status = cmd_block; // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); let on_drop = OnDrop::new(|| Self::on_drop()); - let transfer = self.prepare_datapath_read(&mut status, 64, 6); + let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); InterruptHandler::::data_interrupts(true); Self::cmd(Cmd::card_status(0), true)?; @@ -813,7 +855,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { for byte in status.iter_mut() { *byte = u32::from_be(*byte); } - self.card.as_mut().unwrap().status = status.into(); + self.card.as_mut().unwrap().status = status.0.into(); } res } @@ -872,13 +914,17 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::cmd(Cmd::set_block_length(8), false)?; // CMD16 Self::cmd(Cmd::app_cmd(card.rca << 16), false)?; - let mut scr = [0u32; 2]; + let cmd_block = match self.cmd_block.as_deref_mut() { + Some(x) => x, + None => &mut CmdBlock::new(), + }; + let scr = &mut cmd_block.0[..2]; // Arm `OnDrop` after the buffer, so it will be dropped first let regs = T::regs(); let on_drop = OnDrop::new(|| Self::on_drop()); - let transfer = self.prepare_datapath_read(&mut scr[..], 8, 3); + let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, scr, 8, 3); InterruptHandler::::data_interrupts(true); Self::cmd(Cmd::cmd51(), true)?; @@ -910,7 +956,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { drop(transfer); unsafe { - let scr_bytes = &*(&scr as *const [u32; 2] as *const [u8; 8]); + let scr_bytes = &*(&scr as *const _ as *const [u8; 8]); card.scr = SCR(u64::from_be_bytes(*scr_bytes)); } } @@ -1002,8 +1048,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { Self::stop_datapath(); } - /// Initializes card (if present) and sets the bus at the - /// specified frequency. + /// Initializes card (if present) and sets the bus at the specified frequency. pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> { let regs = T::regs(); let ker_ck = T::frequency(); @@ -1143,6 +1188,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { } } } + // Read status after signalling change self.read_sd_status().await?; @@ -1168,7 +1214,7 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { let regs = T::regs(); let on_drop = OnDrop::new(|| Self::on_drop()); - let transfer = self.prepare_datapath_read(buffer, 512, 9); + let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, buffer, 512, 9); InterruptHandler::::data_interrupts(true); Self::cmd(Cmd::read_single_block(address), true)?; @@ -1291,6 +1337,14 @@ impl<'d, T: Instance, Dma: SdmmcDma + 'd> Sdmmc<'d, T, Dma> { pub fn clock(&self) -> Hertz { self.clock } + + /// Set a specific cmd buffer rather than using the default stack allocated one. + /// This is required if stack RAM cannot be used with DMA and usually manifests + /// itself as an indefinite wait on a dma transfer because the dma peripheral + /// cannot access the memory. + pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) { + self.cmd_block = Some(cmd_block) + } } impl<'d, T: Instance, Dma: SdmmcDma + 'd> Drop for Sdmmc<'d, T, Dma> { diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 656676d9f..20718147a 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -1282,6 +1282,7 @@ pub(crate) struct Info { struct State {} impl State { + #[allow(unused)] const fn new() -> Self { Self {} } diff --git a/embassy-stm32/src/tsc/mod.rs b/embassy-stm32/src/tsc/mod.rs index 5cb58e918..17240e6bc 100644 --- a/embassy-stm32/src/tsc/mod.rs +++ b/embassy-stm32/src/tsc/mod.rs @@ -40,7 +40,7 @@ //! g7.set_io2(context.PE3, PinType::Sample); //! g7.set_io3(context.PE4, PinType::Channel); //! -//! let mut touch_controller = tsc::Tsc::new( +//! let mut touch_controller = tsc::Tsc::new_blocking( //! context.TSC, //! Some(g1), //! Some(g2), @@ -188,7 +188,7 @@ pub struct Config { pub spread_spectrum_prescaler: bool, /// Selects AHB clock divider used to generate pulse generator clk pub pulse_generator_prescaler: PGPrescalerDivider, - /// Maximum number of charge tranfer pulses that can be generated before error + /// Maximum number of charge transfer pulses that can be generated before error pub max_count_value: MaxCount, /// Defines config of all IOs when no ongoing acquisition pub io_default_mode: bool, diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 33bc009a8..06cc0e41d 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -436,6 +436,12 @@ impl<'d> BufferedUartRx<'d> { } } + /// we are ready to read if there is data in the buffer + fn read_ready(&mut self) -> Result { + let state = self.state; + Ok(!state.rx_buf.is_empty()) + } + /// Reconfigure the driver pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { reconfigure(self.info, self.kernel_clock, config)?; @@ -610,6 +616,18 @@ impl<'d> embedded_io_async::Read for BufferedUartRx<'d> { } } +impl<'d> embedded_io_async::ReadReady for BufferedUart<'d> { + fn read_ready(&mut self) -> Result { + BufferedUartRx::<'d>::read_ready(&mut self.rx) + } +} + +impl<'d> embedded_io_async::ReadReady for BufferedUartRx<'d> { + fn read_ready(&mut self) -> Result { + Self::read_ready(self) + } +} + impl<'d> embedded_io_async::BufRead for BufferedUart<'d> { async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { self.rx.fill_buf().await diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index a283adc0c..8f2d26fe0 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Add LazyLock sync primitive. + ## 0.6.0 - 2024-05-29 - Add `capacity`, `free_capacity`, `clear`, `len`, `is_empty` and `is_full` functions to `Channel`. diff --git a/embassy-sync/README.md b/embassy-sync/README.md index 2c1c0cf68..dec1fbc32 100644 --- a/embassy-sync/README.md +++ b/embassy-sync/README.md @@ -13,6 +13,7 @@ Synchronization primitives and data structures with async support: - [`WakerRegistration`](waitqueue::WakerRegistration) - Utility to register and wake a `Waker`. - [`AtomicWaker`](waitqueue::AtomicWaker) - A variant of `WakerRegistration` accessible using a non-mut API. - [`MultiWakerRegistration`](waitqueue::MultiWakerRegistration) - Utility registering and waking multiple `Waker`'s. +- [`LazyLock`](lazy_lock::LazyLock) - A value which is initialized on the first access ## Interoperability diff --git a/embassy-sync/build_common.rs b/embassy-sync/build_common.rs index 0487eb3c5..4f24e6d37 100644 --- a/embassy-sync/build_common.rs +++ b/embassy-sync/build_common.rs @@ -8,8 +8,6 @@ use std::collections::HashSet; use std::env; -use std::ffi::OsString; -use std::process::Command; /// Helper for emitting cargo instruction for enabling configs (`cargo:rustc-cfg=X`) and declaring /// them (`cargo:rust-check-cfg=cfg(X)`). @@ -17,7 +15,6 @@ use std::process::Command; pub struct CfgSet { enabled: HashSet, declared: HashSet, - emit_declared: bool, } impl CfgSet { @@ -25,7 +22,6 @@ impl CfgSet { Self { enabled: HashSet::new(), declared: HashSet::new(), - emit_declared: is_rustc_nightly(), } } @@ -49,7 +45,7 @@ impl CfgSet { /// /// This enables rustc to check that the configs in `#[cfg(...)]` attributes are valid. pub fn declare(&mut self, cfg: impl AsRef) { - if self.declared.insert(cfg.as_ref().to_owned()) && self.emit_declared { + if self.declared.insert(cfg.as_ref().to_owned()) { println!("cargo:rustc-check-cfg=cfg({})", cfg.as_ref()); } } @@ -69,21 +65,6 @@ impl CfgSet { } } -fn is_rustc_nightly() -> bool { - if env::var_os("EMBASSY_FORCE_CHECK_CFG").is_some() { - return true; - } - - let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc")); - - let output = Command::new(rustc) - .arg("--version") - .output() - .expect("failed to run `rustc --version`"); - - String::from_utf8_lossy(&output.stdout).contains("nightly") -} - /// Sets configs that describe the target platform. pub fn set_target_cfgs(cfgs: &mut CfgSet) { let target = env::var("TARGET").unwrap(); diff --git a/embassy-sync/src/fmt.rs b/embassy-sync/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-sync/src/fmt.rs +++ b/embassy-sync/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-sync/src/lazy_lock.rs b/embassy-sync/src/lazy_lock.rs new file mode 100644 index 000000000..18e3c2019 --- /dev/null +++ b/embassy-sync/src/lazy_lock.rs @@ -0,0 +1,152 @@ +//! Synchronization primitive for initializing a value once, allowing others to get a reference to the value. + +use core::cell::UnsafeCell; +use core::mem::ManuallyDrop; +use core::sync::atomic::{AtomicBool, Ordering}; + +/// The `LazyLock` is a synchronization primitive that allows for +/// initializing a value once, and allowing others to obtain a +/// reference to the value. This is useful for lazy initialization of +/// a static value. +/// +/// # Example +/// ``` +/// use futures_executor::block_on; +/// use embassy_sync::lazy_lock::LazyLock; +/// +/// // Define a static value that will be lazily initialized +/// // at runtime at the first access. +/// static VALUE: LazyLock = LazyLock::new(|| 20); +/// +/// let reference = VALUE.get(); +/// assert_eq!(reference, &20); +/// ``` +pub struct LazyLock T> { + init: AtomicBool, + data: UnsafeCell>, +} + +union Data { + value: ManuallyDrop, + f: ManuallyDrop, +} + +unsafe impl Sync for LazyLock {} + +impl T> LazyLock { + /// Create a new uninitialized `StaticLock`. + pub const fn new(init_fn: F) -> Self { + Self { + init: AtomicBool::new(false), + data: UnsafeCell::new(Data { + f: ManuallyDrop::new(init_fn), + }), + } + } + + /// Get a reference to the underlying value, initializing it if it + /// has not been done already. + #[inline] + pub fn get(&self) -> &T { + self.ensure_init_fast(); + unsafe { &(*self.data.get()).value } + } + + /// Consume the `LazyLock`, returning the underlying value. The + /// initialization function will be called if it has not been + /// already. + #[inline] + pub fn into_inner(self) -> T { + self.ensure_init_fast(); + let this = ManuallyDrop::new(self); + let data = unsafe { core::ptr::read(&this.data) }.into_inner(); + + ManuallyDrop::into_inner(unsafe { data.value }) + } + + /// Initialize the `LazyLock` if it has not been initialized yet. + /// This function is a fast track to [`Self::ensure_init`] + /// which does not require a critical section in most cases when + /// the value has been initialized already. + /// When this function returns, `self.data` is guaranteed to be + /// initialized and visible on the current core. + #[inline] + fn ensure_init_fast(&self) { + if !self.init.load(Ordering::Acquire) { + self.ensure_init(); + } + } + + /// Initialize the `LazyLock` if it has not been initialized yet. + /// When this function returns, `self.data` is guaranteed to be + /// initialized and visible on the current core. + fn ensure_init(&self) { + critical_section::with(|_| { + if !self.init.load(Ordering::Acquire) { + let data = unsafe { &mut *self.data.get() }; + let f = unsafe { ManuallyDrop::take(&mut data.f) }; + let value = f(); + data.value = ManuallyDrop::new(value); + + self.init.store(true, Ordering::Release); + } + }); + } +} + +impl Drop for LazyLock { + fn drop(&mut self) { + if self.init.load(Ordering::Acquire) { + unsafe { ManuallyDrop::drop(&mut self.data.get_mut().value) }; + } else { + unsafe { ManuallyDrop::drop(&mut self.data.get_mut().f) }; + } + } +} + +#[cfg(test)] +mod tests { + use core::sync::atomic::{AtomicU32, Ordering}; + + use super::*; + + #[test] + fn test_lazy_lock() { + static VALUE: LazyLock = LazyLock::new(|| 20); + let reference = VALUE.get(); + assert_eq!(reference, &20); + } + #[test] + fn test_lazy_lock_into_inner() { + let lazy: LazyLock = LazyLock::new(|| 20); + let value = lazy.into_inner(); + assert_eq!(value, 20); + } + + static DROP_CHECKER: AtomicU32 = AtomicU32::new(0); + struct DropCheck; + + impl Drop for DropCheck { + fn drop(&mut self) { + DROP_CHECKER.fetch_add(1, Ordering::Acquire); + } + } + + #[test] + fn test_lazy_drop() { + let lazy: LazyLock = LazyLock::new(|| DropCheck); + assert_eq!(DROP_CHECKER.load(Ordering::Acquire), 0); + lazy.get(); + drop(lazy); + assert_eq!(DROP_CHECKER.load(Ordering::Acquire), 1); + + let dropper = DropCheck; + let lazy_fn: LazyLock = LazyLock::new(move || { + let _a = dropper; + 20 + }); + assert_eq!(DROP_CHECKER.load(Ordering::Acquire), 1); + drop(lazy_fn); + assert_eq!(DROP_CHECKER.load(Ordering::Acquire), 2); + } +} diff --git a/embassy-sync/src/lib.rs b/embassy-sync/src/lib.rs index a5eee8d02..014bf1d06 100644 --- a/embassy-sync/src/lib.rs +++ b/embassy-sync/src/lib.rs @@ -12,6 +12,7 @@ mod ring_buffer; pub mod blocking_mutex; pub mod channel; +pub mod lazy_lock; pub mod mutex; pub mod once_lock; pub mod pipe; diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md index 75e17fd63..3b4d93387 100644 --- a/embassy-time/CHANGELOG.md +++ b/embassy-time/CHANGELOG.md @@ -7,7 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -## 0.4.0 - 2024-01-11 +## 0.3.2 - 2024-08-05 + +- Implement with_timeout()/with_deadline() method style call on Future +- Add collapse_debuginfo to fmt.rs macros. + +## 0.3.1 - 2024-01-11 - Add with\_deadline convenience function and example - Implement Clone for Delay diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 5d5bd8b23..c3b4e4e3a 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-time" -version = "0.3.1" +version = "0.3.2" edition = "2021" description = "Instant and Duration for embedded no-std systems, with async timer support" repository = "https://github.com/embassy-rs/embassy" @@ -431,4 +431,4 @@ wasm-timer = { version = "0.2.5", optional = true } [dev-dependencies] serial_test = "0.9" critical-section = { version = "1.1", features = ["std"] } -embassy-executor = { version = "0.5.0", path = "../embassy-executor" } +embassy-executor = { version = "0.6.0", path = "../embassy-executor" } diff --git a/embassy-time/src/fmt.rs b/embassy-time/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-time/src/fmt.rs +++ b/embassy-time/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index 968fbec74..481b2699a 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -31,11 +31,11 @@ log = { version = "0.4.17", optional = true } bitflags = "2.4.1" cortex-m = { version = "0.7.7", features = ["inline-asm"], optional = true } -embassy-boot = { version = "0.2.0", path = "../embassy-boot" } +embassy-boot = { version = "0.3.0", path = "../embassy-boot" } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } -embassy-time = { version = "0.3.1", path = "../embassy-time" } -embassy-usb = { version = "0.2.0", path = "../embassy-usb", default-features = false } +embassy-time = { version = "0.3.2", path = "../embassy-time" } +embassy-usb = { version = "0.3.0", path = "../embassy-usb", default-features = false } embedded-storage = { version = "0.3.1" } esp32c3-hal = { version = "0.13.0", optional = true, default-features = false } diff --git a/embassy-usb-dfu/src/fmt.rs b/embassy-usb-dfu/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-usb-dfu/src/fmt.rs +++ b/embassy-usb-dfu/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-usb-logger/Cargo.toml b/embassy-usb-logger/Cargo.toml index 62b4ee723..d796e5d8e 100644 --- a/embassy-usb-logger/Cargo.toml +++ b/embassy-usb-logger/Cargo.toml @@ -15,7 +15,7 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-l target = "thumbv7em-none-eabi" [dependencies] -embassy-usb = { version = "0.2.0", path = "../embassy-usb" } +embassy-usb = { version = "0.3.0", path = "../embassy-usb" } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } log = "0.4" diff --git a/embassy-usb-synopsys-otg/src/fmt.rs b/embassy-usb-synopsys-otg/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-usb-synopsys-otg/src/fmt.rs +++ b/embassy-usb-synopsys-otg/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs index b90e059f6..f155f1522 100644 --- a/embassy-usb-synopsys-otg/src/lib.rs +++ b/embassy-usb-synopsys-otg/src/lib.rs @@ -382,8 +382,8 @@ impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> { } let eps = match D::dir() { - Direction::Out => &mut self.ep_out, - Direction::In => &mut self.ep_in, + Direction::Out => &mut self.ep_out[..self.instance.endpoint_count], + Direction::In => &mut self.ep_in[..self.instance.endpoint_count], }; // Find free endpoint slot diff --git a/embassy-usb/CHANGELOG.md b/embassy-usb/CHANGELOG.md index 5f665ed25..efdda96fb 100644 --- a/embassy-usb/CHANGELOG.md +++ b/embassy-usb/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## 0.3.0 - 2024-08-05 + +- bump usbd-hid from 0.7.0 to 0.8.1 +- Add collapse_debuginfo to fmt.rs macros. +- update embassy-sync dependency + ## 0.2.0 - 2024-05-20 - [#2862](https://github.com/embassy-rs/embassy/pull/2862) WebUSB implementation by @chmanie diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 191ed0a6a..e310d8bae 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb" -version = "0.2.0" +version = "0.3.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Async USB device stack for embedded devices in Rust." @@ -49,12 +49,12 @@ max-handler-count-8 = [] embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } embassy-sync = { version = "0.6.0", path = "../embassy-sync" } -embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" } +embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } heapless = "0.8" # for HID -usbd-hid = { version = "0.7.0", optional = true } +usbd-hid = { version = "0.8.1", optional = true } ssmarshal = { version = "1.0", default-features = false, optional = true } diff --git a/embassy-usb/src/fmt.rs b/embassy-usb/src/fmt.rs index 35b929fde..8ca61bc39 100644 --- a/embassy-usb/src/fmt.rs +++ b/embassy-usb/src/fmt.rs @@ -90,19 +90,15 @@ macro_rules! todo { }; } -#[cfg(not(feature = "defmt"))] #[collapse_debuginfo(yes)] macro_rules! unreachable { ($($x:tt)*) => { - ::core::unreachable!($($x)*) - }; -} - -#[cfg(feature = "defmt")] -#[collapse_debuginfo(yes)] -macro_rules! unreachable { - ($($x:tt)*) => { - ::defmt::unreachable!($($x)*) + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } }; } diff --git a/embassy-usb/src/msos.rs b/embassy-usb/src/msos.rs index 25936d084..9f4e1a57b 100644 --- a/embassy-usb/src/msos.rs +++ b/embassy-usb/src/msos.rs @@ -278,6 +278,7 @@ pub enum DescriptorType { /// Table 5. Descriptor set information structure. #[allow(non_snake_case)] +#[allow(unused)] #[repr(C, packed(1))] pub struct DescriptorSetInformation { dwWindowsVersion: u32, @@ -288,6 +289,7 @@ pub struct DescriptorSetInformation { /// Table 4. Microsoft OS 2.0 platform capability descriptor header. #[allow(non_snake_case)] +#[allow(unused)] #[repr(C, packed(1))] pub struct PlatformDescriptor { bLength: u8, diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index dbbe0fddc..93e49faef 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [] } -embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } -embassy-boot = { version = "0.2.0", path = "../../../../embassy-boot", features = [] } -embassy-boot-nrf = { version = "0.2.0", path = "../../../../embassy-boot-nrf", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [] } +embassy-nrf = { version = "0.2.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } +embassy-boot = { version = "0.3.0", path = "../../../../embassy-boot", features = [] } +embassy-boot-nrf = { version = "0.3.0", path = "../../../../embassy-boot-nrf", features = [] } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } defmt-rtt = { version = "0.4", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index d4341e8f6..c109c0732 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [] } -embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", ] } -embassy-boot-rp = { version = "0.2.0", path = "../../../../embassy-boot-rp", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [] } +embassy-rp = { version = "0.2.0", path = "../../../../embassy-rp", features = ["time-driver", ] } +embassy-boot-rp = { version = "0.3.0", path = "../../../../embassy-boot-rp", features = [] } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index c203ffc9f..1c2934298 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32" } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } defmt-rtt = { version = "0.4", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index ed13eab65..09e34c7df 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } defmt-rtt = { version = "0.4", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index f25e9815d..5e7f4d5e7 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } defmt-rtt = { version = "0.4", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index c1a47dfe4..60fdcfafb 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } defmt-rtt = { version = "0.4", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 1e83d3113..fe3ab2c04 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } defmt-rtt = { version = "0.4", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index bca292681..169856358 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } defmt-rtt = { version = "0.4", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 0484e6ceb..7cef8fe0d 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } -embassy-usb = { version = "0.2.0", path = "../../../../embassy-usb" } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } +embassy-usb = { version = "0.3.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } defmt = { version = "0.3", optional = true } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index b785a1968..860a835a9 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.2.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } defmt-rtt = { version = "0.4", optional = true } diff --git a/examples/boot/bootloader/rp/memory.x b/examples/boot/bootloader/rp/memory.x index c3b54976e..88b5bbb15 100644 --- a/examples/boot/bootloader/rp/memory.x +++ b/examples/boot/bootloader/rp/memory.x @@ -2,7 +2,7 @@ MEMORY { /* NOTE 1 K = 1 KiBi = 1024 bytes */ BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 - FLASH : ORIGIN = 0x10000100, LENGTH = 24K + FLASH : ORIGIN = 0x10000100, LENGTH = 24K - 0x100 BOOTLOADER_STATE : ORIGIN = 0x10006000, LENGTH = 4K ACTIVE : ORIGIN = 0x10007000, LENGTH = 512K DFU : ORIGIN = 0x10087000, LENGTH = 516K diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 9950ed7b6..050b672ce 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -18,7 +18,7 @@ embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" cfg-if = "1.0.0" embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } -embassy-usb = { version = "0.2.0", path = "../../../../embassy-usb", default-features = false } +embassy-usb = { version = "0.3.0", path = "../../../../embassy-usb", default-features = false } embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } [features] diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 70a89bb30..98a678815 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -16,9 +16,9 @@ log = [ [dependencies] embassy-sync = { version = "0.6.0", path = "../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time" } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time" } +embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index c52256d8e..93a19bea7 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -5,9 +5,9 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 2031b253f..0e3e81c3f 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -7,9 +7,9 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-8192", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 731cee843..7fae7aefc 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -9,8 +9,8 @@ rtic = { version = "2", features = ["thumbv7-backend"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "generic-queue"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "generic-queue"] } +embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 000857821..17fa6234d 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -7,11 +7,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } @@ -27,7 +27,7 @@ cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } rand = { version = "0.8.4", default-features = false } embedded-storage = "0.3.1" -usbd-hid = "0.7.0" +usbd-hid = "0.8.1" serde = { version = "1.0.136", default-features = false } embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 02f6190f0..0da85be07 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -7,11 +7,11 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } defmt = "0.3" @@ -23,7 +23,7 @@ cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } rand = { version = "0.8.4", default-features = false } embedded-storage = "0.3.1" -usbd-hid = "0.7.0" +usbd-hid = "0.8.1" serde = { version = "1.0.136", default-features = false } [profile.release] diff --git a/examples/nrf9151/ns/.cargo/config.toml b/examples/nrf9151/ns/.cargo/config.toml new file mode 100644 index 000000000..1444b0cd1 --- /dev/null +++ b/examples/nrf9151/ns/.cargo/config.toml @@ -0,0 +1,9 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list` +runner = "probe-rs run --chip nRF9160_xxAA" + +[build] +target = "thumbv8m.main-none-eabihf" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml new file mode 100644 index 000000000..17fe27b67 --- /dev/null +++ b/examples/nrf9151/ns/Cargo.toml @@ -0,0 +1,20 @@ +[package] +edition = "2021" +name = "embassy-nrf9151-non-secure-examples" +version = "0.1.0" +license = "MIT OR Apache-2.0" + +[dependencies] +embassy-executor = { version = "0.6.0", path = "../../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.2.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } + +defmt = "0.3" +defmt-rtt = "0.4" + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" +panic-probe = { version = "0.3", features = ["print-defmt"] } + +[profile.release] +debug = 2 diff --git a/examples/nrf9151/ns/README.md b/examples/nrf9151/ns/README.md new file mode 100644 index 000000000..a3f81d24e --- /dev/null +++ b/examples/nrf9151/ns/README.md @@ -0,0 +1,4 @@ +You must flash the TFM before running any non-secure examples. The TFM +configures the secure and non-secure execution environments and then loads the +non-secure application. A reference TFM is included, and you can use the +provided helper script to flash it. diff --git a/examples/nrf9151/ns/build.rs b/examples/nrf9151/ns/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/nrf9151/ns/build.rs @@ -0,0 +1,35 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/examples/nrf9151/ns/flash_tfm.sh b/examples/nrf9151/ns/flash_tfm.sh new file mode 100644 index 000000000..29e4e0ed5 --- /dev/null +++ b/examples/nrf9151/ns/flash_tfm.sh @@ -0,0 +1,2 @@ +nrfjprog --family NRF91 --recover +nrfjprog --family NRF91 --chiperase --verify --program tfm.hex diff --git a/examples/nrf9151/ns/memory.x b/examples/nrf9151/ns/memory.x new file mode 100644 index 000000000..8d7b66fcc --- /dev/null +++ b/examples/nrf9151/ns/memory.x @@ -0,0 +1,7 @@ +MEMORY +{ + /* Trusted Firmware-M (TF-M) is flashed at the start */ + FLASH : ORIGIN = 0x00008000, LENGTH = 0xf8000 + RAM (rwx) : ORIGIN = 0x2000C568, LENGTH = 0x33a98 +} + diff --git a/examples/nrf9151/ns/src/bin/blinky.rs b/examples/nrf9151/ns/src/bin/blinky.rs new file mode 100644 index 000000000..7457a95a3 --- /dev/null +++ b/examples/nrf9151/ns/src/bin/blinky.rs @@ -0,0 +1,22 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_nrf::gpio::{Level, Output, OutputDrive}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + let mut led = Output::new(p.P0_00, Level::Low, OutputDrive::Standard); + + loop { + led.set_high(); + defmt::info!("high"); + Timer::after_millis(500).await; + led.set_low(); + defmt::info!("low"); + Timer::after_millis(1000).await; + } +} diff --git a/examples/nrf9151/ns/src/bin/uart.rs b/examples/nrf9151/ns/src/bin/uart.rs new file mode 100644 index 000000000..2220dccfb --- /dev/null +++ b/examples/nrf9151/ns/src/bin/uart.rs @@ -0,0 +1,37 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::{bind_interrupts, peripherals, uarte}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + SPIM0_SPIS0_TWIM0_TWIS0_UARTE0 => uarte::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + let mut config = uarte::Config::default(); + config.parity = uarte::Parity::EXCLUDED; + config.baudrate = uarte::Baudrate::BAUD115200; + + let mut uart = uarte::Uarte::new(p.SERIAL0, Irqs, p.P0_26, p.P0_27, config); + + info!("uarte initialized!"); + + // Message must be in SRAM + let mut buf = [0; 8]; + buf.copy_from_slice(b"Hello!\r\n"); + + unwrap!(uart.write(&buf).await); + info!("wrote hello in uart!"); + + loop { + info!("reading..."); + unwrap!(uart.read(&mut buf).await); + info!("writing..."); + unwrap!(uart.write(&buf).await); + } +} diff --git a/examples/nrf9151/ns/tfm.hex b/examples/nrf9151/ns/tfm.hex new file mode 100644 index 000000000..9864a1849 --- /dev/null +++ b/examples/nrf9151/ns/tfm.hex @@ -0,0 +1,1543 @@ +:10000000F80B0020690600000D070000255A0000CB +:10001000455A0000655A0000A55A0000855A0000A4 +:100020000000000000000000000000001D2700008C +:100030000D070000000000000D0700000D07000084 +:10004000000000000000000000000000F13200008D +:10005000000000000D07000000000000000000008C +:100060000D0700000D0700000D0700000D07000040 +:10007000000000000D0700000D0700000D07000044 +:100080000D0700000D070000000000000000000048 +:100090000D0700000D070000000000000000000038 +:1000A0000D07000000000000000000000D07000028 +:1000B0000D0700000D0700000D0700000D070000F0 +:1000C0000D0700000D0700000D0700000D070000E0 +:1000D0000D070000000000000D07000000000000F8 +:1000E0000D070000000000000D07000000000000E8 +:1000F0000D070000000000000000000000000000EC +:10010000000000000D0700000000000000000000DB +:1001100000000000000000000000000000000000DF +:10012000000000000D0700000000000000000000BB +:1001300000000000000000000000000000000000BF +:100140000D07000000015F5F00000000FE0B0000D3 +:10015000F9270000800600000000000000000000F9 +:10016000000000000000000000000000401200201D +:100170000000000001015F5F030100001F0100009B +:1001800085040000000000000000000001000000E5 +:10019000010000000000000000000000000000005E +:1001A0000000000070000000CC5E00008000000035 +:1001B000000F000001000000D102000001015F5F9C +:1001C000040100001F010000F30500000000000012 +:1001D000000000000000000001000000000000001E +:1001E000000000000000000000000000D75E0000DA +:1001F000400000000507000001000000DF040000CF +:1002000038B50025054C29462046D4F80024C4F80A +:10021000045405F0B0FCC4F8005438BD200C002094 +:1002200013B511460022CDE9002242680346382A60 +:10023000046844D194F82820022A19D01AB900F091 +:1002400047F902B010BD21482468D0F80404013AEF +:10025000CDE90040082A35D8DFE802F0050A0E1380 +:10026000181D22272C006A46184600F02EF9E8E7F0 +:10027000184600F018F9E4E76A46184600F016F947 +:10028000DFE76A46184600F00BF9DAE76A461846D7 +:1002900000F00FF9D5E76A46184600F00DF9D0E7EF +:1002A0006A46184600F00BF9CBE76A46184600F09C +:1002B00009F9C6E76A46184600F00EF9C1E76FF083 +:1002C0008000BEE76FF08500BBE700BF200C002078 +:1002D0002DE9F04F05680446A1B0002D40F0AA803A +:1002E0002022294602A805F046FC12AF202229460A +:1002F0000AA805F040FC38222946384605F03BFCA8 +:10030000E26904F11C039846B2B10426E26A04F1E2 +:100310002C03EAB10425EEB96FF08306304621B014 +:10032000BDE8F08F002EF1D053F8041D3246013E97 +:100330000029F7D01646E9E70326F5E7002DEAD0B5 +:1003400053F8041D2A46013D0029F7D01546E2E77F +:100350000325F5E738233A460021606805F048FC9C +:100360003828D9D14FF00109CDE90270334F0DF192 +:10037000080A04F1100B4E45D7F800141CD10DF1FA +:1003800028094B46002008EB850EC64533D108B13D +:10039000C7F80014A3683146C7F804340AAA2B46EC +:1003A00002A8FFF73DFF00270646BD4209F10809F4 +:1003B00038D1FFF725FFB1E75BF8043FC1F5806254 +:1003C000D81C20F00300904204D9FFF719FF6FF00A +:1003D0008C06A3E70844CA19C7F8000449466068B8 +:1003E000019205F005FC019ACAF80C0009F1010917 +:1003F0004AF8082FBFE758F804CFC1F5806A0CF11E +:10040000030222F00302524503F1080305D87818CD +:1004100043E9020C11440120B7E70028D5D0C7F802 +:100420000014D2E7394659E90223606805F0F5FB6C +:100430000137BAE76FF0850670E700BF200C002097 +:1004400008B528220021024805F095FB002008BDD0 +:100450002810002010B5044C0F222046034905F057 +:1004600065FB204610BD00BF51100020F6050000BE +:1004700008B50121024803F011FB002008BD00BFB0 +:100480005010002008B5FFF7DBFF40B9FFF7E2FF8F +:10049000FFF7EEFF18B9BDE8084003F06DBB08BDDB +:1004A0006FF0850070476FF0850070476FF0850032 +:1004B00070476FF0850070476FF0850070476FF0F0 +:1004C000850070476FF0850070476FF085007047BA +:1004D000D1E9000103F030BB6FF085007047F0B543 +:1004E00003680546B3F57D7FA7B007D040F2F5322B +:1004F000934207D06FF0850027B0F0BD01F08EFC6D +:100500000020F9E700243C22214607A8CDE9024457 +:10051000CDE90444069405F02EFB3C22214617A8A1 +:10052000169405F028FBEA69019405F11C0302B357 +:100530000426EA6A05F12C033AB30424731E012B46 +:1005400052D8012C50D80423002168680DEB030217 +:1005500005F04EFB04281AD06FF08000CCE7002E87 +:10056000E7D053F8041D3246013E0029F7D0164665 +:10057000DFE70326F5E7002CE0D053F8041D224600 +:10058000013C0029F7D01446D8E70324F5E7022EF2 +:1005900016D16E69402E29D806AF33463A4601215E +:1005A000686805F025FB8642D6D1CDE9027602A91E +:1005B00044B92246019801F01AFE044620469BE702 +:1005C0000021F5E72B6A402BC6D816AACDE90423F3 +:1005D000019804AA01F00BFEDDE904230446002182 +:1005E000686805F01AFBE9E7012085E76FF08900EC +:1005F00082E7002070474D62656420544C532033DD +:100600002E352E3000000000000000000000000029 +:1006100000000000000000000000000000000000DA +:100620005431000001000000407C000080100020D8 +:100630004A000000407C0000200C00200000000068 +:10064000407C0000000C002000000000A8110020E9 +:10065000C4050000200C002018010000000C002040 +:100660000800000002F07ABC08B572B61E4A1F4BA3 +:100670009A601F4B83F309881E4B83F30A8883F328 +:100680000B881D4B16A1D1E90001C3E9000100F060 +:1006900089F81A4B1A498B4212D30020194B1A4978 +:1006A0008B4218D303F06AF8186850F82240586853 +:1006B00040F82240013298688242F5D30C33EAE7D1 +:1006C0000022F8E71C6844F8220001325C68A2426C +:1006D000F8D30833E4E70022F8E700BFAFF3008067 +:1006E000A5EDF5FEA5EDF5FE0000000000ED00E033 +:1006F000F80B002000040020F80B00202806000062 +:100700004C0600004C06000064060000EFF3088071 +:10071000EFF309812DE9F00F6B46724600F038F9CE +:1007200008B0FFF79FFFFEE708B5EFF31083012B3A +:100730000C4A07D1126ABFF34F8F511C4A424A41FB +:10074000104608BD01F0BEFB00B172B6126ABFF3DD +:100750004F8F531C5A425A4101F0B4FB0028EFD08E +:1007600062B6EDE70080FF0008B5EFF31083012BC0 +:100770000B4A06D1D269BFF34F8F02F00102104637 +:1007800008BD01F09FFB00B172B6D269BFF34F8F75 +:1007900002F0010201F096FB0028F0D062B6EEE70D +:1007A0000080FF006F4A10B5D2F8D03043F002034A +:1007B000C2F8D03001F086FB30B14FF05023002258 +:1007C000C3F81421C3F8182101F08BFB28B10122D2 +:1007D000654BC3F8382AC3F878254FF47F02D2F866 +:1007E0003031D2F83421BFF34F8FC3F30B03092B01 +:1007F00005D1012A1EBF01225B4BC3F8782501F009 +:1008000070FB18B10E22594BC3F8E42E01F05AFBCD +:1008100030B10022544BC3F80C270122C3F8102733 +:100820000022D30003F57F03D3F80013BFF34F8FEB +:10083000013108D0D3F800130132D3F80433B2F5F4 +:10084000807F0B60EDD1EFF31084FFF78DFF002860 +:100850004DD0BFF34F8F464BD3F80024012AFBD174 +:10086000C3F80425D3F80024012AFBD1012C03D0BE +:1008700001F028FB00B172B6FFF776FF58B13D4A90 +:10088000D36923F00103D361BFF34F8F384AD2F805 +:100890000034012BFBD1FFF747FF68B1354A136ADB +:1008A00023F0FF0343F020031362BFF34F8F304A5E +:1008B000D2F80034012BFBD1012C03D001F002FB54 +:1008C00000B162B600222A4BC3F80425D3F80024F5 +:1008D000012AFBD1BFF34F8F2249274BCA6802F48C +:1008E000E0621343CB60BFF34F8F00BFFDE7FFF71C +:1008F0001BFF0028ADD11B4AD2F88C3043F4406373 +:10090000C2F88C304FF47F03D3F83021D3F8343160 +:10091000BFF34F8FC2F30B02092A16D1013B022B02 +:1009200002D8164AD35C83B1124815490368104AAD +:100930008B420CBF5A230023C2F8103EC36A8B427D +:100940000CBF5A230023C2F8003E064AD2F8883072 +:1009500043F47003C2F88830BFF34F8FBFF36F8F3B +:1009600010BD00BF00ED00E00040005000A00350AB +:10097000009003500080FF000400FA05C43300001B +:10098000FA50FA507C22014905F0D0B8DC1800205A +:1009900038B51D46374B384C5B68C3F308032360FA +:1009A000EFF30383C4E901206365C2F3801302F00F +:1009B0000C020C2AE16038D10BB9EFF389812022B7 +:1009C0002E48216105F0B2F825B1202229462C4895 +:1009D00005F0ACF8274B9A6AA265D96AE165986B75 +:1009E000206602F400406066586BA06602F080004A +:1009F000E0669A62D962D3F8E4202267D3F8E8105F +:100A0000616702F04001A167C3F8E42000F06AF8D2 +:100A10000E211C4801F077FA2268D31E042B1CD843 +:100A2000DFE803F0090F1215180013B9EFF38881FE +:100A3000C5E70146C3E70C211348BDE8384001F083 +:100A400062BA12211148F8E70B211148F5E70D2190 +:100A50001048F2E70E211048EFE70F2A98BF142143 +:100A6000BDE8384089BF25210C480D48103A01F0F7 +:100A7000F5BB00BF00ED00E0DC180020F0180020FE +:100A800010190020C7330000D5330000E133000007 +:100A9000F3330000FE3300000B3400001934000073 +:100AA0002D3400002DE9F34106460F460C4DD5F8D4 +:100AB0002C80C04710F00104FBD1394630466B69E9 +:100AC000984740B9C047C307FCD42B6A019302B0D2 +:100AD000BDE8F0411847204602B0BDE8F08100BFF4 +:100AE0005434000010B5094C0020A36898472369CE +:100AF00002209847A46A4FF4E1310120A047234621 +:100B0000BDE8104001211520184700BF54340000F3 +:100B100010B5044C002023699847E368BDE81040F5 +:100B2000184700BF54340000064B82B018680023F9 +:100B300082B262F30F03000C60F31F43184602B049 +:100B4000704700BF9C340000014B1869704700BF1C +:100B500084100020014B5869704700BF84100020AA +:100B600038B50C4D0C4695F8203013B94FF0FF30D6 +:100B700038BD0A460146284600F06CFF064B9842F5 +:100B800005D00B3B9842F1D100206C61F0E76FF08B +:100B90000100EDE7841000200B00AD0BF0B51B4EFB +:100BA000054696F820300C4691B01BB94FF0FF3047 +:100BB00011B0F0BD00F06043B3F1005F21D100231C +:100BC0000A460146304600F031FC114B98421AD0DB +:100BD0000B3B9842EAD1346111E0A71B402F28BF9C +:100BE0004027A9193A46684604F0A0FF39466846EE +:100BF000FFF7D4FF0028DBD14036B442EDD8002007 +:100C0000D6E70026F9E76FF00100D1E78410002055 +:100C10000B00AD0BC3B2012B10B540F096804DF622 +:100C2000C023994270D028D8B1F5615F6FD011D838 +:100C3000B1F5965F6DD008D8B1F5966F6BD0B1F570 +:100C4000166F6BD06FF007005DE0B1F5165FF9D15C +:100C5000454B33E047F61223994262D007D8B1F5ED +:100C6000964F61D0B1F5E14FECD1404B26E0B1F5A4 +:100C7000164FE7D14FF41D0320E03D4B994255D06C +:100C800011D8B1F5E13F54D007D8B1F5614F53D039 +:100C9000B1F5963FD6D1374B10E0B1F5613FD1D1D8 +:100CA0004FF06C730AE0B1F5612F48D0324B994296 +:100CB00048D0B1F5E12FC5D14FF0E86310F4E06FF3 +:100CC00046D110F4404103D0B1F5804F43D11021FB +:100CD00010F4405203D0B2F5805F3FD10E2210F4E1 +:100CE000403003D0B0F5403F3BD10120234C20766B +:100CF0006276E361A1760A4324681043C4F8243580 +:100D0000C4F86C05002010BD4FF46503D6E71C4BFA +:100D1000D4E71C4BD2E74FF49E23CFE74FF41D23BB +:100D2000CCE74FF40003C9E7174BC7E74FF08063E8 +:100D3000C4E74FF0EB73C1E74FF46B03BEE74FF02E +:100D40007063BBE74FF08053B8E76FF00300DAE75A +:100D50006FF00800D7E76FF00A00D4E76FF00900E2 +:100D6000D1E76FF00B00CEE70050270000C0750000 +:100D700090D0030000903A0140420F008410002000 +:100D800000F03A0000B0130000A04E0010B5114C66 +:100D9000204600F0D5FD0021206884F8201000F0E6 +:100DA00047FF226842F30732002A11DB0121530971 +:100DB0009B0003F1604303F56143D3F8800202F026 +:100DC0001F0201FA02F20243C3F88022D3F88032F4 +:100DD000002010BD8410002010B5264C0021206892 +:100DE0008EB000F017FF226842F30732002A12DBB0 +:100DF000012053099B0003F1604303F56143D3F8DD +:100E0000801202F01F0200FA02F221EA0202C3F885 +:100E10008022D3F880322422002105A804F0ABFE02 +:100E2000D4E902124FF0FF33CDE90133CDE90333AA +:100E30004FF0EB730B93072301A88DF8363001F0C8 +:100E400080F8014600220B4800F03AFA0A4B98421B +:100E50000DD10C9B002023831B0CA3760B9BC4E9B4 +:100E60000400E361012384F820300EB010BD6FF060 +:100E70000100FAE7841000200000AD0B7FB50025CB +:100E80000C46C0F808511646D0F80821D0F80022C8 +:100E900022F02002C0F80022104AC0F8082301F016 +:100EA000A0F8A560256104F14C03D3E8EF1F21F4FD +:100EB0007F0121F47041C3E8E21F002AF5D110221E +:100EC0002946684604F057FE042368468DF8003032 +:100ED0000196D4E90013984704B070BD10020A00CF +:100EE00000F01F03400909D1074A02EB8303D3F83E +:100EF0000012064A0A40C3F80022704700228033DD +:100F000052F82330FFDE00BF00258450F0F8FCFFCC +:100F10002DE9F04F804690F804A05020664F0E4611 +:100F200000FB0A70416885B049B113F0020304D098 +:100F3000836B002B00F0B2800123009300E000914E +:100F40004FF0500909FB0A73DB6CD90600F1A6804B +:100F50004FF0010BB3180293029BB34200F0A7803D +:100F600006F06043039398F80450D8F8004009FB5A +:100F700005739A6B9AB9039BB3F1005F40F09980B7 +:100F8000019200F0A1FD09FB0572D16C204601F031 +:100F9000010100F0F4FF28B900F09EFDE3E7012312 +:100FA0000193EEE7516C33460029BCBFD4F84C15D1 +:100FB0005164019A42B109FB05713078D1E90E23E1 +:100FC000D054D1E90E3213441BB1C4F84435C4F8EF +:100FD00048B50022C4F82021D4F82011C4F85821C3 +:100FE000D4F85811C4F85021D4F850210822C4F87C +:100FF0000025009AE2B14FF48003C4F80433C4F82A +:1010000008B000F069FD502303FB0A725168002903 +:101010004BD1D26C120748D503FB0A734C33D3E88B +:10102000EF1F21F00801C3E8E21F002A36D0F6E7DF +:10103000C4F808B0019300F04FFD09FB0572D16CB4 +:10104000019B01F001012046019300F098FF8446C6 +:10105000019BD4F84C05D4F84425BCF1000F0DD108 +:101060009342F0D005EB850507EB0515D1B100F0F3 +:101070002BFD2946204600F0F9FFC2E705EB850568 +:10108000934207EB0515F1D10028EFD100F01CFDCC +:101090002946204600F0EAFF00F01EFD074805B093 +:1010A000BDE8F08FC4F80CB0E1E7013654E704481E +:1010B000F5E70448F3E700BF581900200800AD0B1E +:1010C0000000AD0B0400AD0B430904D10123034A1A +:1010D00083409360704700239B60FFDE00258450AF +:1010E00000F01F0340090BD1084A02EB8302D2F83B +:1010F0000012074B0B4043F00303C2F80032704765 +:101100000022803352F82330FFDE00BF00258450D8 +:10111000F0F8FCFF2DE9F84391F8303005460C4615 +:1011200090F804800F6853BB5023DFF85091781C6F +:1011300003FB0893DE6C46F00072DA6404D0384694 +:10114000FFF7C2FFFFF7CCFF6068411C01D0FFF73B +:10115000C7FE94F82C30012B11D1502303FB0893C8 +:10116000E06846F02066421CDE6401D0FFF7B8FE5E +:10117000A068431C03D0FFF7A7FFFFF7B1FF94F867 +:101180002F0038B950223D4B02FB0833DA6C42F095 +:101190008072DA6494F82CC094F82D1094F82EE044 +:1011A000A26A2B6841EA0C01E668D4E90198C3F809 +:1011B00024254EEA0102C3F86C2550B9BCF1010F99 +:1011C000C3F80C75C3F8149504BFC3F80885C3F8B9 +:1011D0001065D3F8682503F26458012A08BFDA6065 +:1011E000D3F86425012A13D1082149F64046244F3B +:1011F000C3F8001547F001075A60D8F800309BBBD0 +:101200002B68D3F88024C3F880240022C3F800257B +:1012100000212B6894F83220C3F81011D3F8100184 +:10122000C3F82011D3F82001C3F82411D3F8240106 +:10123000C3F84411D3F84401C3F85811D3F8581136 +:1012400043F307335201002BD2B212DB0D49C81809 +:1012500080F800230122580903F01F0302FA03F368 +:1012600041F82030BDE8F8834020B847013EC4D1A2 +:10127000C6E7054903F00F03CA54F3E758190020E5 +:10128000A034000000E100E014ED00E000F01F03D6 +:1012900040090BD1084A02EB8302D2F80012074B37 +:1012A0000B4043F00203C2F8003270470022803343 +:1012B00052F82330FFDE00BF00258450F0F8FCFF19 +:1012C0002DE9F3479046502290F80490514C02FBD0 +:1012D00009FA04EB0A070D4697F84810064600295C +:1012E00040F0858009EB890004EB001004F043FC1A +:1012F0002B69AA6944F80A306B69BB6302B1013AF1 +:10130000502303FB0943DA632A6A042A81BFEA698E +:101310009A610022DA6195F83130B8F1000F37D0C8 +:1013200083F001073F0233B1502303FB0943DA6C1A +:1013300042F00102DA64502303FB09440123C4F89C +:10134000048084F848303468D4F84C2112BB294614 +:101350003046FFF7DFFE0822002334688DF807309F +:10136000C4F800250DF10702C4F84425C4F8483537 +:1013700001230A25A360E360D4F85831002B38D14B +:10138000254B402043F001039847013DF4D128E06C +:101390004746C8E708224FF06409C4F80025636097 +:1013A0001D4B43F0010AD4F84431F3B9D4F8243189 +:1013B000DBB94FF42070D047B9F10109F3D14B46A6 +:1013C0000022C4F84C21D4F84C11C4F81021D4F8F0 +:1013D0001011C4F84421D4F84411C4F80025002B9E +:1013E000B5D10E4802B0BDE8F0870123E8E70C480C +:1013F000F8E70023C4F820319845D4F82021C4F838 +:101400000035084B08BF00231F4333680648C3F864 +:101410000473E7E758190020A03400000100AD0B69 +:101420000C00AD0B10020A000000AD0B2DE9F047D7 +:1014300084460F469E4616460579002A51D04FF045 +:10144000500ADFF8BC80D0F800900AFB058ADAF871 +:10145000044074B96BB9DAF82C50002D43D1CAF8A6 +:101460002C20FFF755FD0446CAF82C502046BDE855 +:10147000F0871EF0030F07D0734632463946BDE8A9 +:10148000F0476046FFF744BD07F06043B3F1005FEB +:101490004FF0500414D104FB058400F015FBE26A00 +:1014A0001AB1134C00F018FBE0E7C4E90A7605EB2B +:1014B0008505484608EB051100F0E3FD0D4CF1E70A +:1014C00004FB0584A36B83B100F0FEFAE36A002BF2 +:1014D000E7D1E36C012243F00203C4E90A76E36436 +:1014E000E5E7054CC2E7024CC0E7044CBEE700BF8D +:1014F0000B00AD0B0000AD0B0600AD0B0A00AD0BF1 +:10150000581900202DE9F84350230679284D046826 +:1015100003FB0653D4F80473DA6AC4F8087322B9DB +:101520002448C4F80473BDE8F88306EB860005F18F +:101530004C024FEA001802EB0012D2E8EFCF4CF059 +:10154000080CC2E8E0CF0028F7D10122E26031B3F5 +:10155000D96C01EA02094946204600F010FD002836 +:10156000FAD000F0B1FAB9F1000F1CD1D4F8203153 +:1015700053B10123E360D4F85831002BFBD020464F +:1015800005EB080100F072FD00F0A6FA0023C4F894 +:101590002031D4F82021502202FB0655EB62064888 +:1015A000C4F80473BFE7D4F85831002BE7D1EBE758 +:1015B000581900200500AD0B0000AD0B2DE9F843D4 +:1015C00090F80480484F08EB8806360106F14C0578 +:1015D00004683D44D5E8EF3F43F48052C5E8E02F6E +:1015E0000028F7D1DB047BD4480705D5502303FB43 +:1015F00008739B69002B75D03C4B3E44C4F80833FC +:101600000823C4F800350023C4F81031D4F81021A1 +:10161000C4F84C31D4F84C21C4F844310A03D4F84E +:1016200044318B0303F4804302F400524903134313 +:1016300001F400410B43D5E8EF2F1A43C5E8E12F31 +:101640000029F8D14FF0500909FB0879D9F8083082 +:10165000BBB9D9F8043063B9D5E8EF3F23F47F0371 +:1016600023F47043C5E8E23F002AF5D12048BDE8E5 +:10167000F8830321304600F08FFCD9F80830002BA6 +:10168000EAD0D4F80433590713D5502303FB087369 +:101690005A6872B1DB6C1A030BD5D5E8EF3F23F41F +:1016A0000023C5E8E23F002AF7D10621304600F0CA +:1016B00073FC502303FB0873DB6CDB0401D40D487F +:1016C000D5E7D4F84C310BB901232360502303FB39 +:1016D00008735B68002BF2D0044BC4F80433EEE7C8 +:1016E0000548C4E70548C2E75819002010020A005F +:1016F0000200AD0B0000AD0B0B00AD0B0800AD0BF5 +:101700002DE9F84F056801F06043D5F804A3B3F163 +:10171000005F90F804B089461746C5F808A37CD14D +:101720005023404E03FB0B639A6852B15B68002B59 +:101730005ED1D5F81021002A5AD0C5F81031D5F85D +:101740001031502404FB0B64E269C4E90297002ABB +:101750003CD00BEB8B0897424FEA081824D24FF08D +:10176000000B3A46A1694846C4E902BB04F0DEF921 +:10177000E269A069D21BC119E26104F0A1F96368B2 +:101780006BB1B04449463A46404600F016FCE36C63 +:10179000990404D55A4641462846FFF76FFB224874 +:1017A000C5F804A3BDE8F88F4846A16904F0BEF966 +:1017B000E36963620023E3611C4B9844D8E8EF3F80 +:1017C00043F40023C8E8E23F002AF7D1502303FB8B +:1017D0000B63586ADA689968DB6C121A0144C5F821 +:1017E0003415C5F83825DA04D9D501232B60D6E79E +:1017F000502303FB0B6633698BB9F36CC5F8349542 +:101800005B04C6E90497C5F83875C8D5D5F8003229 +:1018100043F02003C5F80032C1E70548C0E705489A +:10182000BEE700BF581900200000AD0BA41900202E +:101830000A00AD0B0B00AD0B50232DE9F0413C4DE0 +:1018400090F80480046803FB0853DB6CD4F80002B2 +:1018500003F48223B3F5805F68D1D4F80463C4F83D +:10186000086309B9830656D4D4F8003223F0200364 +:10187000C4F800324FF4842308EB8801090101F118 +:101880004C072F44D7E8EF0F1843C7E8EC0FBCF123 +:10189000000FF7D12AB9502303FB08535B68002BD4 +:1018A00041D1244BC4F8083301236360D4F8443198 +:1018B000002BFBD00023C4F84C31D4F84C21C4F8E1 +:1018C0001031D4F81021C4F84431D4F844315023F5 +:1018D00003FB0853DA6C12F400421FD1DA61204690 +:1018E00000F07FFB502303FB08550023AB602B6106 +:1018F000D7E8EF3F23F47F0323F47043C7E8E23FC8 +:10190000002AF5D126F4202626F404760A48C4F8E5 +:101910000463BDE8F0814FF48033ADE720462944ED +:1019200000F071FBDBE701236360EFE70348F0E7BA +:101930005819002010020A000000AD0B0500AD0B85 +:101940002DE9F8432F4A03680679C3F8082343F3C7 +:101950000733002B04460DDB01215A0903F01F0356 +:10196000994002F12003284A42F82310BFF34F8F19 +:10197000BFF36F8F012220461146FFF75DFF012163 +:101980002046FFF7BFFD50212279204D236801FB3F +:101990000252D46CD3F80C05E201D3F81495D3F8B5 +:1019A0000875D3F8108509D54FF0FF32C3F80C2520 +:1019B000C3F81425C3F80825C3F81025A30116D5CC +:1019C000411C01D0FFF762FCB9F1FF3F02D048464D +:1019D000FFF75CFC22010AD5B8F1FF3F02D0404678 +:1019E000FFF754FC7B1C02D03846FFF74FFC502316 +:1019F000002203FB0653DA6483F848205A60BDE8EE +:101A0000F88300BF10034A0000E100E058190020ED +:101A100010B5502402790B4B04FB02335B686BB9A1 +:101A20000368D3F810211AB9D3F80025082A07D083 +:101A300011B1D3F83C350B60034810BD0348FCE7F7 +:101A40000348FAE7581900200000AD0B0800AD0B61 +:101A50000B00AD0BF7B505461646FFF751FE164BCA +:101A60000446984222D1032128462F79FFF7A6FD8C +:101A7000124B984201D0A0421BD15022104B02FBC6 +:101A800007335B6893B90C4C284601A9FFF7C0FFE8 +:101A9000A042F9D1019BB34207D301222846114647 +:101AA00003B0BDE8F040FFF7C7BE064C204603B0C8 +:101AB000F0BD0446FAE700BF0000AD0B0B00AD0B14 +:101AC000581900200800AD0B72B6024A13680133A2 +:101AD00013607047A8190020034A1368013B136084 +:101AE00003B962B6704700BFA81900200722024B55 +:101AF000C3F80423704700BF00300050084BD3F8F0 +:101B00000801D3F80021003818BF012080000AB175 +:101B100040F00100D3F804310BB140F002007047EF +:101B2000003000500022074BC3F80021D3F8001109 +:101B3000C3F80421D3F80411C3F80821D3F80831FD +:101B4000704700BF0030005000231720094A03F5FA +:101B5000C0710133202B42F82100F8D10023172057 +:101B6000044A03F5E0710133202B42F82100F8D13B +:101B7000704700BF0030005010B59DF80840C00B02 +:101B800043EA0423064CC90B43EA0213884200D9F6 +:101B900010BDC2B202F5C07244F822300130F5E740 +:101BA0000030005010B59DF8084000F1604043EA55 +:101BB000042301F16041074C400B490B43EA021337 +:101BC000884200D910BDC2B202F5E07244F822305A +:101BD0000130F5E700300050C0F30E03C3F50043B9 +:101BE000B3FA83F3C3F11B03064AC0F3C730DBB279 +:101BF00040F4807043F48073C2F80005C2F80435E5 +:101C0000704700BF0030005043030148184470473C +:101C1000FF1FF81F054BC0F30730090241F03001E8 +:101C200000F5007043F82010704700BF00300050EE +:101C3000044BC0F30730090200F5007043F8201090 +:101C4000704700BF00300050003A18BF0122003931 +:101C500018BF012103688900074841EA420118635F +:101C600059605A6842F001025A60BFF34F8FBFF3C8 +:101C70006F8F0020704700BF04AAFF0008B5FFF770 +:101C80003DFF044B162118600348BDE8084000F0F2 +:101C90003AB900BFEC1F0020A63400000C22014915 +:101CA00003F044BFEC1F002010B501F006FB044612 +:101CB00090B901F097FF044680B90A4A2E21D368F3 +:101CC000094823F008031B041B0C43F0BF6343F4D3 +:101CD0000033D36000F017F9204610BD45F22354BD +:101CE000FAE700BF00ED00E0BC340000024B1860D2 +:101CF000024B002019607047FC1F0020F81F0020D5 +:101D00001FB5374C426923685A6282699A62C26978 +:101D1000DA62026A1A63426A5A63826A9A63C26A20 +:101D2000DA63026B1A64426B5A60826B9A60C26B10 +:101D3000DA60026C1A61426C5A61826C9A61C26C00 +:101D4000DA61026D1A62826D5A65C26D9A65026F20 +:101D5000DA65026E1A66826E5A66426F9A66EFF311 +:101D600088825A64EFF389829A644268DA64EFF3F6 +:101D700094821A65026801A81A67FFF78FFF23682B +:101D8000019ADA6601221A70164B1C686408640016 +:101D90002046214622462346B7EE000AF7EE000A07 +:101DA000B7EE001AF7EE001AB7EE002AF7EE002A97 +:101DB000B7EE003AF7EE003AB7EE004AF7EE004A07 +:101DC000B7EE005AF7EE005AB7EE006AF7EE006A77 +:101DD000B7EE007AF7EE007A03F081FF04B010BD91 +:101DE000FC1F0020F81F002000B5A1B001A8FEF7DD +:101DF000C9FD029B63B15B060AD4019B23F0020379 +:101E0000052B05D1044B1B6813B101A8FFF778FF20 +:101E100021B05DF804FB00BFF81F0020BFF34F8F17 +:101E20000549064BCA6802F4E0621343CB60BFF376 +:101E30004F8F00BFFDE700BF00ED00E00400FA0592 +:101E400038B543680C2B30D14B68042B2DD14FF0A3 +:101E5000FF3304680D6821682B6031B3A26822B398 +:101E60000623012001F081F9F8B96168104B99420D +:101E70000DD9A2680F485318834202D9F43883421F +:101E800010D8206803F052FE0020286038BD0A4BAD +:101E900099420AD9A26809488B188342F1D90730C0 +:101EA000814202D906488342EBD90220EEE700BF07 +:101EB000FF01FF002C02FF002F01FF003801FF008F +:101EC0004C01FF004FF47F03D3F83001D3F83431D5 +:101ED000BFF34F8FC0F30B00A0F1090358425841E4 +:101EE00070474FF47F02D2F83031D2F83401BFF39B +:101EF0004F8FC3F30B03092B03D1431E58425841A4 +:101F0000704700207047FEF7CDBD012070476FF08D +:101F100003007047002382B00193019802B070471C +:101F20006FF003007047002382B00193019802B064 +:101F30007047022814BF6FF0030000207047FEF7BF +:101F40002DBE30B501EB8202914200D130BD51F877 +:101F5000044B04F07F037F2B4FEA144408BF4FF07B +:101F6000FF33032CF0D8DFE804F002040608036016 +:101F7000EAE74360E8E78360E6E7C360E4E7034637 +:101F8000D0F8580130B931B9D3F82001003818BF62 +:101F9000012070470120704730B504460D4685B0DA +:101FA00010220021684603F0E6FDD4E900136846DC +:101FB0008DF80050984705B030BD7FB504460E46F9 +:101FC000154600211022684603F0D5FD012368461E +:101FD0008DF80030CDE90165D4E90013984704B0CD +:101FE00070BD10B50446FFF76FFDD4F8583133B11A +:101FF000D4F8043313F4800308BFC4F80035BDE8F7 +:102000001040FFF769BD70B50D4604460522AA21B0 +:10201000D0F83C65A86903F0AEFD0522AB69C4F8B1 +:102020003435C4F838250022C4F81021D4F8101132 +:102030000121E162D4F810110029FBD0C4F84C2131 +:10204000D4F84C11C4F81021D4F81021D4F83C2550 +:102050009642EA6109D15A1E043312F8011FAA29D7 +:1020600003D19A42F9D10023EB6170BDD0F8583109 +:1020700033B1CB6CC3F30032DB0458BFC0F800258A +:10208000704770B5CE6C0D4606F001010446FFF7AF +:1020900076FF38B94FF4800346F00406EE64C4F8C6 +:1020A000043370BDD5E90A365AB1296CEA6B761A49 +:1020B000964228BF164619443246A86B03F036FDF7 +:1020C000AB6B4FF0FF326A641BB1C4F84435C4F8FF +:1020D00048650023C4F82031D4F82021C4F85831D1 +:1020E000D4F85821C4F85031D4F850310823C4F83A +:1020F00000354FF48003C4F804330123A360D0E714 +:10210000C0037047C00300F5FF407F3070470020D8 +:1021100070471F2070474FF40040704700F57F4024 +:10212000C03040037047402070475F2070474FF435 +:10213000005070474B6830B513F01F052DD1026871 +:102140000C681068C0F30720844226D2506855609E +:1021500094600C7C23F01F0304F001041C438B7C6F +:10216000DB0003F018031C434B7C5B0003F0060309 +:102170002343D3608B68013B23F01F04CB685B00D3 +:1021800003F00E03234343F0010313615060BFF3D8 +:102190004F8FBFF36F8F284630BD0120FCE70368E7 +:1021A00000205A68C9B258609960D86018615A60B6 +:1021B000704770B50546002403681E68C6F30726FD +:1021C000B44201D1002070BD21462846FFF7E7FF49 +:1021D0000134F5E70020704708B5FFF705FE72B639 +:1021E00020BFFDE7002070470020704770470B4676 +:1021F00070B5114618B1032806D0032070BD1846EB +:10220000BDE87040FFF71CBE5A68082A01D00220C2 +:10221000F4E74C68042CFAD11D684FF0FF330E68C8 +:10222000296833600029F2D06B68002BEFD0262399 +:102230007422012000F099FF0028E8D122462323D0 +:102240000120696800F091FF04460028DFD1D5E93C +:102250000001FFF74BFD30602046CFE730B50C465C +:10226000154685B038B139B1FFF74DFE041E03DACB +:10227000204605B030BD044640F60D23ADF80E30C3 +:1022800009230B4901A805F00F028A5C2D091A5495 +:10229000013B012BF7D147F630030C21ADF8043098 +:1022A000FFF731FE0028B4BF04462418E0E700BF62 +:1022B000EA34000008B5194B83F30A88184800F087 +:1022C000E7FF40BBFFF7F0FC28BBFFF783FF10BB25 +:1022D000FFF788FFD8B9FFF789FF00F067FA3521CB +:1022E0001048FFF710FE17210F48FFF70CFE1821CA +:1022F0000E48FFF708FE00F03FFC21210C48FFF7D5 +:1023000002FE00F03FFA00F0CDFE002008BDFFF70E +:102310006BFF0028DFD000F021FEEEE70004002074 +:10232000AC190020FA3400002F35000046350000BB +:102330005E3500002DE9F04F93B00093574B814676 +:10234000D3F800B00BB2002B0D461646C1F302685D +:10235000C1F3024A04DA6FF0800013B0BDE8F08FD9 +:102360008B42C36001D10020F7E708EB0A03042B7E +:10237000F1D8CC0F64014FEAC80731463A46DBF882 +:10238000080044F0020300F0F0FE01460028E2D10C +:10239000202202A803F0EFFB3A46314602A84FEA9A +:1023A000CA0603F0C3FB32460099DBF8080044F08C +:1023B000060300F0DAFE07460028CCD101462022B1 +:1023C0000AA803F0D8FB324600990AA802AE03F02F +:1023D000ADFB33460137B84514D91A46BC460DE06B +:1023E000D2F808E0D16818687144884203D259686D +:1023F00008448645AFD30CF1010C0832C445EFD137 +:102400000833E7E715F0006F18BF202409F118071B +:1024100007EB880844F00203474513D1202C26D14E +:10242000002D02DBC5F3C0456C0109F128050AAE99 +:1024300005EB8A0A44F0060455451AD1009BC9F8F9 +:102440007C3090E77268DBF8080056F8081B0193AF +:1024500000F08BFE00287FF47EAF56F8042C019B21 +:1024600047F8042F56F8082C38633A62D4E7002462 +:10247000DBE77268234656F8081BDBF8080000F01B +:1024800074FE00287FF467AF56F8043C45F8043F1B +:1024900056F8083C28642B63CEE700BFB019002033 +:1024A0002DE9F0411F461A4B0D461646D3F8008021 +:1024B00000F051FF044608B900F050FDE368002B1E +:1024C00001DA00F04BFD032D01D900F047FD04EBCC +:1024D0008504E569E36CED1A16D006233A463146C9 +:1024E000D8F8080000F041FE08B100F037FDBD4209 +:1024F00028BF3D46E36CE16B2A461944304603F0A1 +:1025000015FBE36C2B44E3642846BDE8F08100BF73 +:10251000B01900202DE9F0411D461A4B0F46164612 +:10252000D3F8008000F017FF044608B900F016FD4C +:10253000E368002B01DA00F011FD032F01D900F050 +:102540000DFD04EB8704E36AE26E9B1AAB4201D2F5 +:1025500000F004FD02232A463146D8F8080000F0B6 +:1025600004FE08B100F0FAFCE36EE06D2A46314645 +:10257000184403F0DBFAE36E00202B44E366BDE869 +:10258000F08100BFB01900202DE9F04105464FF061 +:1025900001080E4E0E4B37685C681CB92846376040 +:1025A000BDE8F0812268936813F400700CD1A36930 +:1025B000012B09D0D368346023B19847002801DA91 +:1025C00000F0CCFCC4F81880246AE6E7B0190020BB +:1025D000B419002038B5044610B96FF0800038BD3A +:1025E0008368002BF9D01A68002AF6D05D68002DA8 +:1025F000F3D00B4BE861A8691D6020B92B68DB683C +:1026000053B90123AB61A36804F10C001B681B697B +:10261000984701232360E2E798470028F1DADCE7D6 +:10262000B01900204268024B08461A60704700BF8C +:10263000B0190020002330B505680446AA68C0E937 +:10264000063312F4406F85B01CD012F4006202D041 +:1026500000F0C2F90246A96A2B6968460B440731AB +:1026600023F0070321F00701CDE9021300930023B3 +:1026700005490193EB6800F09FFA684600F04EFEB2 +:10268000024B1C6005B030BD89250000B019002048 +:1026900001F00C0370B50C2B0CBF154605464A061D +:1026A0000C461ED58B0658BF2835AB6913F8026C53 +:1026B00084F00803C3F3C003C6F38012934201D031 +:1026C00000F04CFC16F0A00F1ED176B1032E17D0EF +:1026D00032461C210E48FFF7C1FD6FF083032B60CB +:1026E0000CE000F03BFC2026E2E700F03BFB044658 +:1026F000FEF70EFA2146074800F00AFE204670BD9C +:10270000284600F03FFAF9E732461F210248E2E787 +:102710007F350000F80B00209B350000EFF30880A8 +:102720007146EFF30982EFF30B830CB406B4FFF7A5 +:10273000AFFF8646009900F0080001F00801401A3A +:1027400002DC12DB04B070471EF020031CBF2DE931 +:10275000F00FBDF1080D0A4C254626462746A04637 +:10276000A146A246A34630B4704704B030BC1EF068 +:1027700020031CBF1DF1080DBDE8F00F04B0704729 +:10278000A5EDF5FE084BDA6882F07F4282F47F0205 +:1027900042F48042DA6000221A765A76DA76DA77E4 +:1027A000602283F82220704700ED00E0114BD3F83F +:1027B000882042F47002C3F88820BFF34F8FBFF324 +:1027C0006F8FD3F88C2042F44062C3F88C20D3F88A +:1027D000342242F08042C3F83422D3F8342242F04B +:1027E0003C42C3F834224FF0E022D36843F4200384 +:1027F000D360704700ED00E0009A164B9A4227D153 +:1028000001229043014641EC100B41EC110B41ECCD +:10281000120B41EC130B41EC140B41EC150B41EC8A +:10282000160B41EC170BEFF3148222F0040282F333 +:102830001488BFF36F8F02460346044605460646DA +:10284000074680468146824683468446864604473C +:10285000FEE70000A5EDF5FE2DE9F041044618B9AC +:1028600043F6DA30BDE8F0810029F9D0836800250D +:1028700013F4406F14BF01230023134F43F00203EE +:10288000DFF848800B6000F13006236AAB4201D8C4 +:102890000020E7E71421A369E26906EB830301FB4B +:1028A00002330C226A4399188968090709D59B5895 +:1028B000BB4201D04345D3D1186810B10121FFF7C5 +:1028C000A9F90135E1E700BFB4100020AC100020E9 +:1028D00070B5324C86B03248FFF76BFC2368012597 +:1028E0005A1C01932F4B2260DA681B694FF4407623 +:1028F000039300232A4801A902920495ADF81460BD +:102900008DF81630FFF716FC18B143F6DA3006B032 +:1029100070BD23688DF816005A1C0193224B204885 +:102920000293224B01A9CDE903352260ADF8146072 +:10293000FFF700FC0028E8D123688DF816005A1C28 +:1029400001931B4B164802931A4B01A9CDE903359D +:102950002260ADF81460FFF7EDFB0028D5D12368A5 +:102960008DF816005A1C0193134B0D480293134B1C +:1029700001A903930223049340F201132260ADF8EE +:102980001430FFF7D7FB04460028BED12A4629465B +:102990000348FFF759F92046B9E700BFBC190020EA +:1029A000A81000202C36000060360000005F0000F8 +:1029B0002006000020060000000C0020200C002053 +:1029C000014B1868704700BF2C360000014B1B6894 +:1029D000186870472C360000014B1B685868704718 +:1029E0002C36000008B5FFF749F9FFF79BF80A4BB2 +:1029F0005A68103AD3B2120609D401215A0903F0D9 +:102A00001F03994002F16003044A42F82310BDE815 +:102A1000084000F0A3BA00BF00ED00E000E100E0D4 +:102A20000020034BD8765A6A42F470225A627047EB +:102A300000ED00E00349044BCA68002092B2134342 +:102A4000CB60704700ED00E00800FA0500224FF06F +:102A5000FF300D4B02F1A0010132102A43F8210092 +:102A6000F8D1D3F88022002022F00802C3F8802297 +:102A7000D3F88022D3F8802222F40072C3F8802297 +:102A8000D3F88032704700BF00E100E008B5FFF7DF +:102A90002DF80822024BC3F880211A60002008BDDF +:102AA00000E100E0064BD3F8D02022F00102C3F889 +:102AB000D020D3F8D02042F00202C3F8D0207047D3 +:102AC00000ED00E037B50124FFF73EF8134D224634 +:102AD000052347F6FF7100200094FFF74DF82246CA +:102AE00007234FF000500E490094FFF75BF8D5E93B +:102AF0000101072300220094FFF73EF8072300227C +:102B0000084909480094FFF74DF82969E868013938 +:102B1000FFF762F8002003B030BD00BF2C36000084 +:102B2000FF7F0020FFFF03200080002038B5002435 +:102B30000E4D002155F8040B0134FFF779F81C2CD9 +:102B4000F7D10020012240F20111094BC3F88004A3 +:102B5000C3F88424C3F8C004C3F8C424054AC2F8E7 +:102B600040154FF48072C3F8402438BDBC350000D6 +:102B700000300050009003500122014B1A60704752 +:102B8000C019002010B50446094B228918686168F5 +:102B90000623806800F0E9FA28B9064B1B68012B70 +:102BA00001D100F087F86FF08603236010BD00BFED +:102BB000B0190020C01900202DE9F84305461E4633 +:102BC0000068134B9046AA68A0F1080440E902335C +:102BD000503890420F4601D200F0C0F9A4F14809E4 +:102BE00048220021484602F0C6FF002344E907338B +:102BF00044F8143C4FF0807344F8043C6FF0020337 +:102C000044E9036744F8208CC5E90093BDE8F883E4 +:102C1000A5EDF5FE30B5094C024661680023084673 +:102C200040B105686D68954205D11BB1826860604E +:102C30009A60816030BD03468068F1E7441A002045 +:102C400038B504462AB10B689B68DB0512D5002015 +:102C500038BD0B4B1D680DB900F080F900222B68C0 +:102C600099692C338A4203D053F8040FA04204D14F +:102C70009142ECD16FF0FC00EAE70132F2E700BFCD +:102C8000B019002070B504460E46154600213022CA +:102C90000C3002F070FF064B20461B68A660636094 +:102CA000656100F001FA00232061236070BD00BF60 +:102CB000B0190020044B1B681BB11B680BB158688E +:102CC00070474FF0FF307047B0190020064B10B529 +:102CD0001C680CB900F042F923689B6813F4406F3C +:102CE00014BF0120002010BDB01900202DE9F843C9 +:102CF000904607460C46FFF7E9FF024624B96FF0FD +:102D000080042046BDE8F8836300F8D5144B04F036 +:102D10001F0153F82150002DF1D02B682946586827 +:102D2000FFF78EFFB0B9C4F30721284600F001FB7E +:102D300004460028E3D1EFF3108972B600F0C1F920 +:102D4000064689F3108840B142462946FFF79AFFAC +:102D50003E60D6E76FF08104D3E76FF08204D0E7DE +:102D6000C41900202DE9F04100F0AAF90023134E08 +:102D7000134F73607B6000F0E5F8DFF84880304661 +:102D800000F022F80446A8B139468023424600F0FC +:102D90007FF80546204600F011FB206804F1080189 +:102DA000FFF75AFD08B100F0D9F829462046FFF791 +:102DB00041FCE4E7BDE8F04100F071B9B41900202E +:102DC000441A0020C4190020F8B5054608B900F0DF +:102DD000C5F82A4E346814F1290F4CD8284B1968CD +:102DE00004F128038B4246D2236AA26903EB430312 +:102DF0000C321344606AE269024402EB820213441B +:102E00009B00E31801D2994201D200F0A7F8236891 +:102E10001C4A1B0C1B04934201D000F09FF823882E +:102E2000B3F5817F01D300F099F86368002B01DAD4 +:102E300000F094F8144A176807F124031360134A4A +:102E40001268934201D900F089F8236AA26903EB62 +:102E500043030C32616A1344E2693C600A4402EBAA +:102E600082021344326802EB83026B6832603B6279 +:102E70006F603846F8BD0027FBE700BFC410002094 +:102E80004836000000005F5FC0100020443600009C +:102E90002DE9F74F0F4690460646009300B109B959 +:102EA00000F05CF8D6F800A0DAF818200AF1300338 +:102EB00003EB820BDAF81C40204B1D6854B10C2246 +:102EC00002FB04541C601E4B1B689C4201D900F09D +:102ED00045F82C4625464FF00009DAF81C204A45F3 +:102EE00000D91CB9002003B0BDE8F08F142303FB08 +:102EF00009B20023C5E900269268AB60930516D598 +:102F0000B8F1000F02D0009B802B03D0019200F09B +:102F100025F8019A12F0E00FD0B202D158F8202023 +:102F20001AB1019000F01AF8019848F820507A6818 +:102F300009F10109AA607D600C35CEE7BC100020C4 +:102F40004036000008B5FFF73BFD034B9860FFF7E4 +:102F50003DFD80F3888808BD00ED02E0FFF73CB935 +:102F60008230012808B506D8FFF7B0FE18B9BDE8D1 +:102F70000840FFF7F3BF08BDF8B506460D4600F060 +:102F8000EAF9044608B9FFF7E9FFA7680FB9FFF7A8 +:102F9000E5FFE368991C20D05A1C21D1A5B315F197 +:102FA000820F13D102232360EFF3108672B62946F5 +:102FB0002046FFF737FB054686F310882368022B6F +:102FC00024D1204600F086F82846F8BD15F1830F7D +:102FD000EAD0FFF7C3FF0025E6E702232360FAE704 +:102FE000002BF6DB204600F0DAF93B689B689B0576 +:102FF00001D50223236015F1810FD5D16369002B20 +:10300000D2DBFFF7ABFFCFE73546F4E700232360C1 +:10301000DAE708B5FFF7E0F86FF0830008BD2DE9A7 +:10302000F3410E46174698460546FFF74FFE00F05F +:10303000A6F92946024601A8FFF758FE044660B9E2 +:1030400043463A4631460198FFF774F9044640B1C9 +:103050006B0002D5019800F03DF8204602B0BDE8B3 +:10306000F0810198FFF7B6FA0446F6E740F2011046 +:10307000704770B50546FFF729FE06462846FFF75C +:10308000C9FD044608B9002070BD014632462846F5 +:10309000FFF7D6FD0028F6D12368D868F4E76FF073 +:1030A0000200704700DF70474FF480507047B0F562 +:1030B000805F03D1EFF30B808038704700207047AA +:1030C0007047EFF30B8000F1800383F30B887047A8 +:1030D00000207047EFF30B83803B83F30B8870472E +:1030E00080EA0000E1EE100A00EE100A00EE900AFD +:1030F00001EE100A01EE900A02EE100A02EE900AAA +:1031000003EE100A03EE900A04EE100A04EE900A91 +:1031100005EE100A05EE900A06EE100A06EE900A79 +:1031200007EE100A07EE900A08EE100A08EE900A61 +:1031300009EE100A09EE900A0AEE100A0AEE900A49 +:103140000BEE100A0BEE900A0CEE100A0CEE900A31 +:103150000DEE100A0DEE900A0EEE100A0EEE900A19 +:103160000FEE100A0FEE900A70472DE9F0410E465F +:103170001546002A4AD0C4074BD480F00204C4F399 +:103180004004A40003F00602062A4AD144F00104D8 +:1031900022462946304602F077FBB8BB46E800F2EB +:1031A00005EB0608100E120208F1FF3747E800F39E +:1031B0004FEA136166D51B0264D5884262D046E8A7 +:1031C00000F547E800F7FEF7A2FF2D0E85424FEA13 +:1031D000176734D3FEF79DFF874230D82846FEF7A5 +:1031E00091FF2246C6F101010144304602F04CFB3A +:1031F000002847D00135AF4218D83846FEF780FF87 +:103200002246A8EB000102F03FFBD8B30020BDE846 +:10321000F081EFF39484A40004F0040444F0120459 +:10322000B0E7990731D544F00804B1E72846FEF726 +:1032300067FF0646FEF76FFF22460146D5E7FEF719 +:1032400072FF85421ED3FEF770FF87421AD82846C8 +:10325000FEF7DAFC2246C6F101010144304602F0D5 +:1032600013FB78B10135AF4203D83846FEF756FF5D +:10327000C6E72846FEF752FF0646FEF758FF2246ED +:103280000146EBE76FF07F00C1E74CF2DA20BEE7C2 +:1032900010B50446FFF706FCFFF714FC10B143F627 +:1032A000DA3010BDFFF742FC0028F8D1FFF710FB21 +:1032B0000028F4D102232360F3E708B5FFF7B0FB41 +:1032C00010B143F6DA3008BDFFF7B4FB0028F8D19F +:1032D00000F01CF80028F4D162B6FDF703FCFFF7FC +:1032E000B5FB0028EDD1FFF7D1FB0028EBD0E8E7D4 +:1032F000EFF30880EFF309812DE9F00F6B4672467A +:10330000FDF746FB08B0FFF76DFBFEE700207047B6 +:1033100004460D46FFF7E4FEA54628470368283318 +:1033200083F30988836883F30B88BFF36F8F40684A +:10333000704703689A68DB6812F4806F05D18B428E +:103340002CBF00206FF0FA0070478B420CBF0020AA +:103350006FF0FA00704710B5FFF7A9FE0446FFF7BB +:10336000B7FE50B9FFF7A6FCA3685B681B685B68F3 +:10337000834218BF0024204610BD0024FBE738B567 +:10338000054648B100F01BF8B5EBD07F044601D0EC +:10339000FFF7E4FD204638BDFFF78CFCF4E700237F +:1033A00010B500F1280252F8041F19B1C16F146C56 +:1033B00019444C600833202BF5D110BD70474FF0F5 +:1033C000FF307047000001464154414C20455252A5 +:1033D0004F523A2000486172644661756C740D0A60 +:1033E000004D656D4D616E616765206661756C7439 +:1033F0000D0A004275734661756C740D0A005573B1 +:103400006167654661756C740D0A0053656375727A +:10341000654661756C740D0A005265736572766558 +:103420006420457863657074696F6E2000506C612C +:1034300074666F726D2065787465726E616C206958 +:103440006E7465727275707420284952516E293AF3 +:1034500020000000290B00000B1F0000D90D000008 +:103460008D0D0000331F00003F1F0000610B0000A6 +:103470000F1F0000490B0000550B0000150C000049 +:10348000151F0000211F0000271F00001D00000065 +:10349000100004001C0002001100060003020202DA +:1034A0000338FDD87047506C6174666F726D2045AB +:1034B0007863657074696F6E3A0D0A00416C6C2018 +:1034C00070696E732068617665206265656E206341 +:1034D0006F6E66696775726564206173206E6F6ECA +:1034E0002D7365637572650D0A00303132333435E2 +:1034F000363738394142434445461B5B313B333410 +:103500006D5B536563205468726561645D2053652B +:103510006375726520696D61676520696E6974699C +:10352000616C697A696E67211B5B306D0D0A00540E +:10353000462D4D20466C6F6174204142493A204827 +:103540006172640D0A004C617A7920737461636B57 +:10355000696E6720656E61626C65640D0A001B5BB5 +:10356000313B33346D426F6F74696E672054462D62 +:103570004D2076322E302E301B5B306D0D0A0055FB +:103580006E6B6E6F776E2053504D205356432072F2 +:1035900065717565737465643A2000556E6B6E6F66 +:1035A000776E20535643206E756D6265722072658A +:1035B000717565737465643A200000000040005026 +:1035C000005000500080005000A0005000B000509B +:1035D00000E0005000F000500000015000100150C9 +:1035E0000040015000500150007001500080015017 +:1035F00000B0015000C0015000D0015000E0015067 +:1036000000F0015000000250001002500020025053 +:103610000030025000400250006002500080025012 +:1036200000A002500090035000258450008000004C +:1036300000800000FFFF0F00007C00000080000001 +:0C3640002C1200201412002000020000D8 +:10366000009A204B9A4208D110B502F0A7FA02F056 +:10367000A9F906BC96460C46744702F0E3FA009A94 +:10368000184B9A4208D110B502F0A4FA02F09AF948 +:1036900006BC96460C46744702F0D4FA0CB4029A63 +:1036A000104B9A420CD14FF0004319430CBC10B59B +:1036B00000F09EF802F086F906BC96460C46744768 +:1036C00002F0C0FA009A074B9A4202D106490868F4 +:1036D000744702F0B7FA009A024B9A4200D174473D +:1036E00002F0B0FAA5EDF5FE801000200348044B6F +:1036F000834202D0034B03B118477047A811002042 +:10370000A8110020000000000548064B1B1AD90F25 +:1037100001EBA301491002D0034B03B118477047D6 +:10372000A8110020A81100200000000010B5064CD0 +:10373000237843B9FFF7DAFF044B13B10448AFF322 +:1037400000800123237010BDC0180020000000007D +:10375000EC5E000008B5044B1BB104490448AFF30C +:103760000080BDE80840CFE700000000C41800203A +:10377000EC5E0000A3F5803A704700BF174B002BAA +:1037800008BF134B9D46FFF7F5FF00218B460F4600 +:103790001348144A121A02F0EEF90E4B002B00D017 +:1037A00098470D4B002B00D09847002000210400C3 +:1037B0000D000D48002802D00C48AFF3008002F045 +:1037C000DBF820002900FEF775FD02F0C1F800BF0C +:1037D000000008000000000000000000F80B0020BE +:1037E000A8110020B8280020000000000000000000 +:1037F0002DE9F84304460D4616461F46EFF30583B0 +:10380000C3F308030BB1FFF7A9FBDFF834903B4685 +:10381000204632462946D9F80080FFF700FCD9F847 +:1038200000300446984506D0DB6901461869BDE8BA +:10383000F843FFF7A1BBFFF793FB2046BDE8F883F1 +:10384000B019002001680E4A0346914215D1C169A2 +:10385000A2F11022A2F1EF1291420ED18268012A48 +:103860000BD8C26812B101698A4206D0586928B1E2 +:103870009B691B1A5842584170470120704700BF8E +:1038800055AA00FF0D4B70B59E68A6B13046FFF7F4 +:10389000D9FF044678B9F3686BB935690DB920468C +:1038A00070BD2846FFF7CEFF28B9EB68B34202D1BE +:1038B0002E462D69F2E70124F1E700BF4C1A0020E3 +:1038C0002DE9F041394E3468F368D4B1B468C4B11D +:1038D000002861D000295FD001FB00F5B5FBF0F0B6 +:1038E000884259D1291D57D8AA070DD025F00302C7 +:1038F00004321C4603E0616891424FD2A469002C57 +:10390000F9D12046BDE8F0812A46F2E7891A232939 +:1039100004F12007D4E9050C1AD80123A360A0B153 +:10392000C0F818C0A36903B158610023C4E9053386 +:103930003369DB0702D5FFF7A5FFA0BB2A460021AC +:1039400038463C4602F017F9DBE7C6F80CC0E9E759 +:1039500002F1200804EB08032039C3E9011E2169A4 +:10396000DFF84CE0DC60196144F808E0AEF1102E9D +:10397000AEF1EF1EC3F81CE001B1CB60C3E9050C4A +:1039800040B18361996901B14B6101212361C4E9AF +:103990000121CAE7F360F5E70024B2E7D4F808E0B4 +:1039A000BEF1000FB2D0012001F0D2FF4C1A00206E +:1039B00055AA00FFF8B5054600283AD0364E3368C0 +:1039C000002B36D0B268002A33D0834203D8726805 +:1039D0001344984202D3012001F0BAFFA0F1200461 +:1039E0002046FFF72FFF0028F5D155F8183C012B92 +:1039F000F1D145F8180C55E90570DFB1BB68CBB9BA +:103A000055F81C2C7B68203213447B60386100B170 +:103A1000C76020220021204602F0ADF8386908B1C5 +:103A200083682BB333699B0703D5FFF72BFF00286F +:103A3000D1D1F8BD40B3836833BB42686368134497 +:103A4000203363600369D4E90521236192B9B9B9D0 +:103A5000426981696261A161A2B19461A26902B106 +:103A6000546103B1DC602022002102F084F8D9E720 +:103A70003C46E2E79161A1690029E9D04A61E7E7A4 +:103A8000F160F8E7F460E9E7F36845F8083C03B152 +:103A90005C61F460C6E700BF4C1A002038B50D46E3 +:103AA000142200210446124802F065F81149124818 +:103AB00000F02CF8232D1AD914F003031FBF043D86 +:103AC000ED18C3F10403E4182A460021204602F051 +:103AD00052F8074B094AC3E900459C602260A2F1F5 +:103AE0001022203DA2F1EF126560E261DC6038BD7A +:103AF0004C1A0020B5390000C138000055AA00FF5B +:103B0000014B1B68184700BFC8100020024B18600B +:103B1000024B002019607047CC100020C810002014 +:103B200010B50A46044619B1024B00211B6898479C +:103B300010BD00BFD0100020054B0A46197819B1FE +:103B40000146181D02F0B8B86FF08800704700BF3A +:103B5000601A002010B5074C00F032F8204602F041 +:103B6000BCF8201F0821FFF7DBFFBDE8104002F082 +:103B7000A0B800BF641A002070B50C4D2B787BB93B +:103B800002F095F8044670B90126281D6E7002F007 +:103B900091F8044638B900F00BF8044618B92E70B5 +:103BA0000024204670BDFFF7D5FFFAE7601A002019 +:103BB0000122024B002083F880257047681A0020FC +:103BC000F8B5074C2025264601272046276202F03B +:103BD0005DF8013D04F12C04F7D186F88055F8BD5D +:103BE000681A002010B50C4C236813B10B4B1B68EE +:103BF0002BB900F089FC30B90122084B1A6001236F +:103C00002360002010BD0138062801D9044810BDEA +:103C1000044B53F8200010BD042000200020002099 +:103C2000FE8FFFFF545D0000144B2DE9F043002888 +:103C300014BF04461C46124F236883B0BB4219D000 +:103C400016460D4620464FF4147104F1040900F0A5 +:103C500047F804F58E78484600F0CEF8404600F06C +:103C600019FA2B464A4640460649009600F034FBB6 +:103C700008B92760002003B0BDE8F08308200020C9 +:103C8000A5BCC95A7D3E000070B50D4C1D460028EC +:103C900014BF064626460B4B306882B098420DD1C1 +:103CA00006F58E70002633460096144600F03EFB63 +:103CB000002818BF34462C6002B070BD0248FBE7F4 +:103CC00008200020A5BCC95AE88FFFFF38B131B1E8 +:103CD000002201440346013081421A70FAD1704734 +:103CE00038B131B1002201440346013088421A70D4 +:103CF000FAD170472DE9F043202B1D460646884631 +:103D000091468BB026D8DBB202AF8DF80480B04666 +:103D100058F8041B8DF8053021B9404601F038F9F8 +:103D2000044640B9012302224046336001A901F054 +:103D300043F9044638B138462021FFF7D1FF204629 +:103D40000BB0BDE8F0832A464946404601F034F9FD +:103D50000446F0E702AF1946104600233A4601F048 +:103D6000B1FA04460028E6D12023B9461D46CCE727 +:103D70002DE9F041D0F8F830A6B0002BD8BF02AE44 +:103D800031DD05460027D0F80C4102AEA4F1010850 +:103D90009022D5F8FC403146D0F8000101AB0197E4 +:103DA000B8FA88F8A0474FEA5818044620B9019B92 +:103DB00053B9B8F1000F16D030469021FFF790FFAD +:103DC000204626B0BDE8F081014632462846FFF77E +:103DD00091FF58B9D5F80431019A1344C5F804315C +:103DE000B8F1000FE8D16FF03C04E5E70446204647 +:103DF00026B0BDE8F08100BF70B50025044614224E +:103E000004F588762946C0F8F850FC3001F0B3FE7E +:103E100008222946304601F0AEFE144B30461B689E +:103E20009847204640F8045B01F098F8104B304664 +:103E30001B689847C8B9D4F8F830AB420FDC03EBE5 +:103E4000830204EB82022021C2F800010120C2E9B2 +:103E5000421008490133C2F8FC10C4F8F830064B90 +:103E60003046BDE870401B68184770BDF010002058 +:103E7000EC100020614E0000E81000202DE9F04712 +:103E8000202A88B07AD83F4B00F5887904461B6811 +:103E900048461746884698470546F8B940F2011645 +:103EA000D4F8F830002B65D02046FFF761FF0546B7 +:103EB00038B9D4F8F830002B14DC013EF2D16FF0A1 +:103EC0003B056E4620213046FFF70AFF2E4B484641 +:103ED0001B689847002818BF6FF01D05284608B0DA +:103EE000BDE8F087D4E94132934203D3D4F80C21E2 +:103EF000012A02D0013ED7D1E1E71F2BFAD96E4645 +:103F000001462022304604F1040A01F034FE314615 +:103F1000504601F07BF805460028D3D1504601F009 +:103F200031F8504601F01AF82946504601F030F8B1 +:103F300005460028C6D150462022314601F03CF803 +:103F400005460028BED1034632462021304601F006 +:103F5000B9F905460028B5D1D4F8F8303A46002B17 +:103F6000C8BF002340463146C8BFC4F8043101F041 +:103F7000DDFDA7E76FF03F056E46A3E76FF03B0559 +:103F8000ACE700BFEC100020E810002070B590B046 +:103F900000287AD03E4C0D46402236210646204667 +:103FA00001F0E9FD40225C21A01801F0E4FD2B1D89 +:103FB000A34203D904F144039D4252D32B682268E3 +:103FC000534023602B68226C534023646B68626803 +:103FD000534063606B68626C53406364AB68A26873 +:103FE0005340A360AB68A26C5340A364EB68E268E3 +:103FF0005340E360EB68E26C5340E3642B69226951 +:1040000053402361226D2B695340236562696B69BC +:10401000534063616B69626D53406365AB69A2692C +:104020005340A361AB69A26D5340A365EB69E2699C +:104030005340E361EB69E26D5340E3650021304694 +:1040400000F0A6FF044628B940223046104900F08F +:10405000B3FF044640216846FFF742FE204610B0F9 +:1040600070BD631E04F13F01013D1F3415F8010FBF +:1040700013F8012F42401A7011F8012F2878A3423B +:1040800082EA00020A70F1D1D8E76FF07304E5E725 +:104090005822002010B54FF49A720021044601F016 +:1040A0006AFD42F21072044BC4F8202104F59670A8 +:1040B0001B68BDE810401847F01000202DE9F04FB4 +:1040C00004468846914695B0002900F0A780002A52 +:1040D0000CBF0126022600238DF80C30002C00F0C6 +:1040E0009F80DFF844A104AF0AF1400B0021204675 +:1040F00000F04EFF034648B1384620210193FFF7F8 +:10410000EFFD019B184615B0BDE8F08F40225146E7 +:10411000204600F051FF03460028EDD104F1F405DC +:1041200020222946204600F047FF03460028E3D11D +:104130000122204603A900F03FFF03460028DBD1FF +:10414000022E62D020460CA900F060FF0346002832 +:10415000D2D10146204600F01BFF03460028CBD1F8 +:1041600040225946204600F027FF03460028C3D1CD +:10417000202220460CA900F01FFF03460028BBD1D7 +:104180003946204600F042FF03460028B4D13946A4 +:104190002046FFF7FBFE03460028ADD1202229462A +:1041A000204600F009FF03460028A5D120460CA9AF +:1041B00000F02CFF034600289ED10146204600F067 +:1041C000E7FE0346002897D140225946204600F0DA +:1041D000F3FE034600288FD1202220460CA900F0D0 +:1041E000EBFE0346002887D12946204600F00EFF4B +:1041F0000346002880D19DF80C200132D2B2B24291 +:104200008DF80C20FFF472AF76E74A46414620460F +:1042100000F0D2FE0346002894D06DE701265AE74D +:104220006FF0730304AF67E7582200202DE9F041D7 +:104230000446884615461F46D0F81801E0B013B171 +:1042400000EB40004008B5F5807F3ED82844B0F52B +:10425000C07F3AD84FF4C0720021684601F08BFC51 +:104260006946D4F82431D4F81821D4F828019847A5 +:1042700070BBD4F8186157B1D4E9493072080DEB1E +:104280000601984720BBD4F8183106EB5306B8F165 +:10429000000F00D08DB9324669462046FFF70EFF69 +:1042A000054610B90123C4F8143131466846FFF7BA +:1042B00017FD284660B0BDE8F0810DEB06004146D1 +:1042C0002A462E4401F032FCE5E76FF00405F0E7E2 +:1042D0006FF00805EDE700BF2DE9F047044604F153 +:1042E000F4050F4691461E46DDF8208000F036FEAC +:1042F00029462046FFF74AFE08B1BDE8F087284668 +:104300002022012101F037FCD4F81831C4F82471BF +:10431000C4F8289113B92023C4F818314246314615 +:104320002046BDE8F0470123FFF780BFB2F5806F5C +:1043300000F295802DE9F04F89B09A46129BB3F5B3 +:10434000807F00F29080D0F82431164604460F4654 +:104350004BB3D0F81C31012B05D0D0F81421D0F884 +:1043600020319A421FDD514600232046129AFFF762 +:104370005DFF014698B900231293002E5ED0DFF84E +:10438000EC9009F1400B0021204600F001FE202EA8 +:104390003546014628BF202504F1F40890B10846AF +:1043A00009B0BDE8F08FBAF1000FE6D0129B002BE8 +:1043B000E1D051461A462046FFF780FE014600280C +:1043C000DBD0ECE749464022204600F0F5FD0146EF +:1043D0000028E4D141462022204600F0EDFD0146B0 +:1043E0000028DCD16946204600F010FE0146002876 +:1043F000D5D1204600F0CCFD01460028CFD159464A +:104400004022204600F0D8FD01460028C7D1694669 +:104410002022204600F0D0FD01460028BFD14146B1 +:10442000204600F0F3FD01460028B8D138462A4660 +:10443000414601F07BFB761B2F44A4D15146204618 +:10444000129AFFF73BFE01460028A8D10846D4F88F +:1044500014310133C4F8143109B0BDE8F08F6FF0A6 +:104460000201084670476FF0040198E758220020C7 +:10447000002130B58DB0282202A8019101F07BFB0C +:1044800002A800F047FF044610B120460DB030BD31 +:10449000174D4FF0FF31286800F042F9044620B173 +:1044A000144800F0D3F9012C18D0002000F068F96E +:1044B000D0B9114A02A901A800F0C4FC04460120A9 +:1044C00000F05EF960B9286800F032F90028DCD00D +:1044D0000A4800F0BBF920460DB030BD0524F2E7D4 +:1044E000074800F0B3F9EEE7064800F0AFF9E0E75F +:1044F000D4100020705D0000D8220020C85D0000AC +:10450000A85D0000885D000030B583B000F05CF865 +:1045100028B100F0ABF80324204603B030BD00F012 +:1045200077F8D8B900F02CF9E0B9224CD4F8283942 +:104530001B0EF02B0AD1D4F8242A1F4B9A4231D0FB +:1045400000F044F8072400F091F8E5E7062400F0B5 +:104550003DF800F08BF8204603B030BD042420461F +:1045600003B030BD00F032F800F080F8FFF780FFB4 +:10457000044698B9114D2B68002BCDD10246014657 +:10458000FFF752FB50B968220D4901ABFFF77CFBE6 +:1045900020B920460B4B2B6003B030BD05242046CC +:1045A00003B030BD012000F0EBF80028DAD1C4F8E8 +:1045B0000C0ADBE7001084500000E020F824002003 +:1045C000FC2400205AEA5A5A002070470020704705 +:1045D000430504D54FF0FF32034BC3F80821024BCB +:1045E000C3F8080A704700BF00108450014BC3F89D +:1045F000040A70470010845008B100F06BB84FF403 +:104600007500704708B100F04FB84FF4750070475F +:1046100010B5114800F070F800B110BD0F4800F05F +:104620006BF80028F9D10E4C204600F065F8002800 +:10463000F3D10C4B0C481C6000F05EF801460028DA +:10464000EBD100F02DF8044608B1204610BD00F073 +:1046500079F82046FAE700BFE4100020E0100020BF +:10466000DC100020D4100020D810002008B5084825 +:1046700000F04CF8074800F049F8074800F046F809 +:10468000064800F043F8BDE8084000F00BB800BF52 +:10469000E4100020E0100020DC100020D8100020E2 +:1046A00000207047704700BF024610B4084CD4F891 +:1046B000003A1342FBD021B1D4F804310B60C4F8A6 +:1046C0000831034B0020C3F8082A5DF8044B7047FB +:1046D00000108450044AD2F8003A1842FBD0C2F8C5 +:1046E000080A0020704700BF0010845001F0E8B9AC +:1046F0000A46002101F03FBA08B5034B02681B6867 +:1047000010689847002008BD1011002008B5034B21 +:1047100002685B6810689847002008BD10110020EF +:10472000024B02689B681068184700BF10110020F8 +:1047300008B5034B0268DB6810689847002008BD85 +:104740001011002070B5094C094D2069AB689847DD +:1047500018B1084B08485B6898470021074AEB6886 +:1047600011602069BDE87040184700BFFC100020B0 +:1047700010110020F4100020E05D000064250020EE +:10478000F8B51A4D1A4E0446B26828699047E8B940 +:10479000184F3B684CB1A3B1012B19D0013B3B60D2 +:1047A0002869F36898470020F8BD43B90121124AEF +:1047B000C2F800151149D1F81029002AFBD10133A4 +:1047C0003B60F368286998470020F8BD0C48F8BDA5 +:1047D0000A4AD2F81039002BFBD1074A6FF07E400D +:1047E000C2F80035FFF702FF3B68D7E7FC10002056 +:1047F0001011002064250020000084500010845017 +:10480000E98FFFFF014B1B68184700BF1011002004 +:10481000014B9B68184700BF10110020014BDB685B +:10482000184700BF10110020BFF34F8F0549064BFA +:10483000CA6802F4E0621343CB60BFF34F8F00BF3E +:10484000FDE700BF00ED00E00400FA0530B44FF0D2 +:10485000FE320025074B084C08494968C3F800247C +:10486000C3F80424C3F80824C3F80C24C4F8005582 +:1048700030BC08470010845000008450F410002021 +:1048800010B5044650B1636813F0685F05D0064A5E +:10489000934202D000236260236010BD034B0448A2 +:1048A0005B689847EFE700BF2C5F5CA9F41000201D +:1048B000005E0000C8B143680D4A934213D013F064 +:1048C000685F0ED0012350E8002F194640E8001C15 +:1048D0009CF0000FF7D1012AF5D0BFF35F8F0020C5 +:1048E000704704487047044870476FF4E0407047D1 +:1048F0002C5F5CA9E98FFFFFEA8FFFFF034680B1C1 +:10490000426809498A420AD012F0685F05D0BFF3B5 +:104910005F8F002210461A607047044870470448B1 +:1049200070476FF4E04070472C5F5CA9E98FFFFF90 +:10493000EA8FFFFF10B5044620B10023034A23602D +:10494000626010BD0248FFF781FFF6E73A00003AC7 +:10495000285E00002DE9F047002878D00C46002999 +:1049600075D01D46002B72D007461AB101220023D4 +:104970002A6003602B68002B64D02946204600F093 +:10498000B7FD804600285FD12146286800F096FDDB +:104990008046002858D12B68082B6CD0042B6DD092 +:1049A000A3F10209B9FA89F94FEA59190121354EE3 +:1049B000C6F8C411C6F84011C6F8C411636AC6F837 +:1049C0003031D6F830219342F6D14FF0000A4FF043 +:1049D000FF30C6F82CA1FFF7FBFD6FF01B0350461C +:1049E000C6F80031FFF702FEC6F80C91D6F8040AAB +:1049F00040F48060FFF7FAFD0A23C6F83831089BBF +:104A0000012B29D02369204AA2FB03231B09626AD8 +:104A1000404602FB03F303EB43031A4ADB039B0903 +:104A2000C2F8D8310123C2F82C313B682A6823F040 +:104A30007F4343EA02633B602A6843EA02233B6008 +:104A4000BDE8F087DFF844804046BDE8F087DFF836 +:104A500040804046BDE8F0874FF47F03D3F80C2C2C +:104A6000013206D0D3F80C3C074AA2FB03231B09F2 +:104A7000CDE71623CBE74FF0030997E74FF0020984 +:104A800094E700BF00108450ABAAAAAA310CF10031 +:104A9000350CF10058B34B1EB3F5047F27D230B567 +:104AA0004FF0000ECD00744671464B0901F01F0C0B +:104AB00050F82330BCF11F0F23FA0CF306D003F09B +:104AC000010319B901211C468E46EEE79C4201F113 +:104AD000010106D01C464FF0010EA942E5D100208D +:104AE00030BD0EF1010E9645F7D1024830BD0148A8 +:104AF000704700BF360CF100C0B32DE9F0434C1EE7 +:104B0000B4F5047F1DD2E3B1DAB100252E46A846E4 +:104B10002C46CF0003F1FF394FEA541C04F01F0E5E +:104B200050F82C10BEF11F0F21FA0EFC0CD00CF027 +:104B3000010C4CB90126E04634463546ECE7964276 +:104B400016D90C48BDE8F083AB420BD0C44508BF72 +:104B50000136A945F3D001350134BC42DCD1002037 +:104B6000BDE8F0830125E0462E46F5E70148704791 +:104B70001D46F1E7370CF1002DE9F04F91B0834667 +:104B8000DDE91B460D46002E6ED10F691C60002327 +:104B90001A990B60002A00F02F819D4B6A6AD3F8A6 +:104BA0003811D3F830319A4269D10A2967D19BF87C +:104BB0000330089304F10803079304230593954BEE +:104BC000934CA3FB07239B0803EB4303A7EB43038F +:104BD000039306971A9B069E1E60002E00F0EA8043 +:104BE00000F096FC00230993BBF1000F00F0D58084 +:104BF00098464FF0010ADDF81C90002D00F0CD80A2 +:104C0000089B002B3DD0284608A900F071FC002825 +:104C100039D0814B984220D0089B082B00F0E480CB +:104C200000225B000893294608AB58460092FFF724 +:104C300091FE7A4B984200F0D38070B9DBF80020E7 +:104C4000130A03F47F03134323F07F43CBF80030B0 +:104C5000059B013B0593BDD10020039000F058FC5B +:104C6000039811B0BDE8F08F4FF47F01D1F80C0C20 +:104C700001300CBF4FF40477D1F80C7C86E768480C +:104C8000EBE76648C5E72946089800F017FC0028BE +:104C9000BFD1089B082B00F0A980042B00F0A9804D +:104CA000A3F10203B3FA83F35B090493C4F8C4A12C +:104CB000C4F840A1C4F8C4A16B6AC4F83031D4F878 +:104CC00030219342F6D100234FF0FF30C4F82C314D +:104CD000FFF77EFC002318466FF01B03C4F8003179 +:104CE000FFF784FC049B4B4FC4F80C31D4F8040A42 +:104CF00040F48060FFF77AFC0A23C4F838312B694E +:104D000009A8A7FB03236A6A1B0902FB03F303EB51 +:104D10004303DB039B09C4F8D831C4F82CA1DBF8AA +:104D20000030089923F07F420B0243EA01631343EA +:104D3000CBF8003000F0B2FB099B03F01A030343E9 +:104D40007FF46AAFA7FB0637D4F81431B8EB970F9E +:104D50000A93D4F818310B93D4F81C310C93D4F87F +:104D600020310D93D4F824310E93D4F828310F93C9 +:104D700001D1039B9BB9484618220AA9183EFFF7A8 +:104D8000B5FC09F1180908F101089EB100F0C0FB5B +:104D900000230993002D7FF433AF224839E74846BA +:104DA0001A46F61A0AA9994408F10108FFF79EFC71 +:104DB000002EEBD1069F079E6A6939463046FFF701 +:104DC00069FEAA6940B94FF4806339463046FFF75F +:104DD00093FE00283FF440AF00231A9A136018E7AF +:104DE0002B6A002B3FF439AF0F4836E703230493B7 +:104DF0005CE70223049359E70122294658460096AE +:104E000008ABFFF7A7FD00283FF4D4AE25E700BFAD +:104E100000108450ABAAAAAA020CF100310CF100D8 +:104E2000300CF100350CF100320CF10030B4DDE94A +:104E3000023402940024049DCDE9035430BCFFF7F2 +:104E40009BBE00BF30B51546012487B005AB00936B +:104E50000022CDE9015404ABFFF78EFE07B030BD50 +:104E6000F0B587B0002966D01E46002B63D01446EB +:104E7000002A60D0314F0D4638684FF0FF31FFF700 +:104E80004FFC00284DD10020FFF77AFC002844D1C8 +:104E90002B4800F03FFAD8B101204FF0FF35FFF763 +:104EA0006FFC002835D14FF408712648FEF70EFF3D +:104EB00004212548FEF70AFF21482821FEF706FFB6 +:104EC0003868FFF735FC00282FD1284607B0F0BD21 +:104ED0001C4A0346029205AA019204AA039000927A +:104EE000174902461848FFF7A1FF03460028D3D10F +:104EF00028461D46059B22469C4228BF1A46049917 +:104F000032600831FFF7F2FB0120FFF739FC00287F +:104F1000C9D00E48FFF79AFCC5E70D48FFF796FC8D +:104F2000B6E70C48FFF792FCADE70B48FFF78EFCA5 +:104F3000284607B0F0BD4FF0FF35C6E7D41000207B +:104F40007C250020A425002078250020A85D0000F5 +:104F5000885D0000705D00004C5E000010B50446E6 +:104F600028B12046BDE81040F421FFF7C1BB04483A +:104F7000FFF76CFC2046BDE81040F421FFF7B8BBFA +:104F8000645E000010B1F421FEF7A0BE704700BFC0 +:104F900008B521B1012908D06FF0360008BD012104 +:104FA00000F058F80028F7D108BD022100F052F8AF +:104FB0000028F9D0F0E700BF30B505468818B0F5F5 +:104FC000801F0B461446A1B001D8802A0CD9B3F536 +:104FD000801F17D922461946284600F07DF804465E +:104FE00084B9204621B030BD6846FFF77FFB2246DA +:104FF0006946284600F070F8802104466846FFF7AD +:1050000077FBEDE76FF03604EBE700BF70B5E8B172 +:105010000E46D9B1044600F031F80546B0B9236810 +:10502000012B0BD0022B01D0284670BD1C2230462C +:1050300004F10801FFF75AFB284670BD20223046D4 +:1050400004F10801FFF752FB284670BD6FF03605EA +:10505000EAE700BF78B138B50D46F0210446FFF706 +:1050600047FB402320462560E36500F091FA0038B5 +:1050700018BF012038BD0120704700BFF0B5056E94 +:10508000A5B0044604AEE5B90023012701933046DC +:105090006760294602AA009300F046FA10B1012089 +:1050A00025B0F0BD2A46204602A900F099FA002852 +:1050B000F5D1204600F0AAFB0028F0D1206625B0EB +:1050C000F0BD802D2A46304628BF802204F16401BD +:1050D000FFF70CFB256ED7E7002800F0AE802DE926 +:1050E000F04F1446A5B0002A3DD00F46002949D004 +:1050F000B2F5803F0546006E20D34FF6FF7805F1EC +:10510000640AEB6D1A1AB2FBF3F103FB1122002AB9 +:1051100065D18342B9464FF6FF7672D0B6FBF3FBFA +:1051200003FB0BFBBBF1000F30D1002E45D1A4F5E2 +:105130007F44FF3CB4F5803F4744E2D2EA6D161A43 +:10514000B6FBF2F302FB1366A64228BF2646002EEA +:1051500075D1824200F08D80B4FBF2F602FB06F6B8 +:105160002EB9002C79D1002025B0BDE8F08F0023A6 +:1051700031463846CDE9003302AA00F0D5F90028BF +:1051800000F09580012025B0BDE8F08F002359463E +:105190004846CDE9003302AA00F0C6F90028F1D153 +:1051A0005A46284602A900F01BFA0028EAD1A6EBCD +:1051B0000B06286ED944002EB9D019304946324624 +:1051C00005EB8000FFF792FAA4F57F44286EFF3CC0 +:1051D0003044B4F5803F4744286692D2AEE742455A +:1051E00028BF4246164639465044FFF77FFA286EDC +:1051F000EB6D3044834207EB06092866A8EB0606F0 +:105200008CD1802B28BF802351461A4604A8FFF773 +:105210006DFA0023E96D02AACDE9003304A800F07D +:1052200083F90028AED12846EA6D02A900F0D8F92A +:105230000028A7D1EB6D286670E70120704705F1C3 +:105240006403394632461844FFF750FA286EEA6D77 +:105250003044A41B374428667BE72B6E2246193363 +:1052600005EB83003946FFF741FA2B6E23442B668A +:1052700079E7802A28BF802205F1640104A8FFF79E +:1052800035FA0023E96D04A8CDE9003302AA00F045 +:105290004BF900287FF476AF2846EA6D02A900F0AA +:1052A0009FF900287FF46EAFEA6D286654E7324616 +:1052B000284602A900F094F900287FF463AF374430 +:1052C000A41B4EE7F8B51C460546114816460F4686 +:1052D000FFF744FE21460E48FFF75AFE044620B170 +:1052E0000B48FFF74FFE2046F8BD3A4629460848CE +:1052F000FFF762FE04460028F2D131460448FFF76A +:1053000085FE04460248FFF73DFE2046F8BD00BF7B +:10531000C42700201C2370B582B001A90546019363 +:1053200000F032F8044638B9019B1C2B07D0144C0E +:105330001C212846FFF7DCF9204602B070BDD5E9F4 +:105340000112131E18BF0123003918BF01210126C5 +:1053500028689B00EA6843EA4103002818BF43F02D +:105360000103EE612AB9C5E90834002BE4D1054CEC +:10537000DEE7204643F00803C5E9083402B070BDFB +:10538000370CF0000E0CF0000346002866D0002910 +:1053900064D00A681C2A61D14FF47F023B49D2F8DD +:1053A000100C88425CD0D2F8101C013158D0D2F8D1 +:1053B000101C4FF47F021960D2F8140C3449884253 +:1053C00060D0D2F8141C01315CD0D2F8141C4FF418 +:1053D0007F025960D2F8181C11F5947F4FD0D2F893 +:1053E000181C01314BD0D2F8181C4FF47F02996081 +:1053F000D2F81C0C274988423ED0D2F81C1C01313F +:105400003AD0D2F81C1C4FF47F02D960D2F8001CAD +:1054100070312FD0D2F8001C01312BD0D2F8001CF3 +:105420004FF47F021961D2F8041CAF3120D0D2F8BA +:10543000041C01311CD0D2F8041C4FF47F025961C6 +:10544000D2F8080C144988420DD0D2F8081C01315A +:1054500009D0D2F8082C00209A61704701207047CB +:1054600040F6FC01A5E740F2373200209A61704710 +:105470005121E2E79021D3E742F60411C3E740F659 +:10548000D861B2E742F2D001A1E700BFFCF8FFFF0C +:10549000D020FFFF0429FFFF37F3FFFF014608B5C7 +:1054A0004FF48060FFF7AEF80022034BC3F8C82129 +:1054B000C3F82C2108BD00BF001084500138072814 +:1054C00005D8DFE800F0100E040A040404060748BB +:1054D0007047CB6800204B6270478B6800204B629E +:1054E00070474B68F6E70B68F4E700BF310CF1003A +:1054F0000B6802E0082B0B6006D8026A13424FEAE1 +:105500004303F7D00020704700487047310CF1008A +:105510000022044B4FF48060C3F82C21C3F8C4214F +:10552000FFF756B800108450F0B5002483B0B0F1F6 +:10553000005F8DF8074025D38C468444BCF1804F32 +:1055400004461FD817461D4601220DF1070300F03F +:1055500097F90646B0B99DF80730099A3C603B714F +:1055600092B14DB10246089928460DF1070300F0AB +:1055700087F938B99DF807303046099A15601371DC +:1055800003B0F0BD4FF47506304603B0F0BD00BF68 +:10559000D8B108B50368012B04D0022B0FD043B15A +:1055A0000B4808BD20220B490830FFF79FF8002068 +:1055B00008BD142208490830FFF798F8F7E72022C1 +:1055C00006490830FFF792F8F1E74FF4730070478F +:1055D0000100F300745E0000B45E0000945E000001 +:1055E0002DE9F843002900F0F9800446002800F076 +:1055F000F98003680F469046002B00F0C380013B02 +:10560000012B00F2D7804FF0FF3178484FF00209AC +:10561000FFF786F8002840F0BF800020FFF7B0F8C1 +:105620000646002840F0C280714AD2F81C39002B8F +:10563000FBD16F4DD5F8203C002BFBD14FF0FF3054 +:10564000FEF7C6FFD5F8040A20F04000FEF7CEFFB3 +:1056500001230722C5F81838C5F80029C5F8C43752 +:10566000A36CC5F8CC37E36CC5F8D037C5F8C09744 +:1056700023685BB1013B012B18D8636AC5F85C361F +:10568000236AC5F85836E369C5F85436A269584B01 +:10569000C3F850266269C3F84C262269C3F848262D +:1056A000E268C3F84426A268C3F84026504AD2F8FC +:1056B0001039002BFBD1B8F1000F5FD06368402098 +:1056C000012B08BFC2F884363A68494BC3F8282C2E +:1056D000C3F82C8CFEF790FF0646454AD2F81039E5 +:1056E000002BFBD1424AD2F8203C002BFBD123688F +:1056F0005BB1013B012B18D8D2F85C366362D2F85B +:1057000058362362D2F85436E361394BD3F8502629 +:10571000A261D3F84C266261D3F848262261D3F8FF +:105720004426E260D3F84036A36000230121304ACA +:10573000D2F8CC07A064D2F8D007E064C2F8C4174E +:10574000C2F88436C2F8C837D2F81039002BFBD122 +:10575000C2F81838002E3BD1254BD3F8040A40F08C +:105760004000FEF743FF0120FFF70AF860BB1F4827 +:10577000FEF7DEFF10BB3046BDE8F8830423C2F815 +:10578000C837AAE74FF0FF3118484FF00109FEF77C +:10579000C7FF00283FF441AF1648FFF757F8002035 +:1057A000FEF7EEFF064600283FF43EAF1248FFF733 +:1057B0004DF839E7114E3046BDE8F8831048FFF741 +:1057C00045F83046BDE8F8830E48FFF73FF8CEE7CE +:1057D000102104F10800FEF78BFFBDE70A4E3046AA +:1057E000BDE8F8834FF47306C5E700BFE41000205E +:1057F00000108450705D0000885D00000100F3001F +:10580000C85D0000A85D00000300F300A0B30346DC +:1058100070B4D0E90240D3E9041226BA05BA0CBA32 +:1058200010BAC3E90440D3E90612986A09BAC3E979 +:10583000026512BA996100BAD3E9084125BA0CBAD7 +:10584000C3E90725D3E90B12C3E9094009BAD86BAC +:1058500012BAD962D3E90D4125BAC3E90C250CBAB5 +:1058600000BAD3E9101209BA12BAC3E90E4019649A +:1058700000205A6470BC70474FF47300704700BF3B +:1058800000201870704700BF431810B501D21F2ABE +:1058900001D9002010BD013902F014030144102B7E +:1058A00080EA01043CD009DC8BB1042BF1D11F2C20 +:1058B00040E840F315D941E840F10EE0142BE8D15F +:1058C0001F2C40E8C0F30CD941E8C0F105E01F2CC3 +:1058D00040E800F305D941E800F11C460B468C4234 +:1058E000D7D122F01402013A0A2AD2D801A151F8E4 +:1058F00022F000BF435900003D5900002F5900001D +:1059000093580000935800009358000093580000EB +:105910004959000043590000375900002F59000031 +:105920001F2C40E880F3DCD941E880F1D5E713F47F +:10593000001FAFD1ADE713F4801FFAE75B02A9D5D2 +:10594000A7E713F4002FF4E713F4802FF1E700BF6B +:1059500008B5074B044613B10021AFF30080054B97 +:105960001868836A03B19847204600F029F800BF01 +:1059700000000000C85E000070B50D4D00260D4C03 +:10598000641BA410A64209D10B4D00260B4C00F05D +:10599000D5F9641BA410A64205D170BD55F8043B8F +:1059A00001369847EEE755F8043B01369847F2E791 +:1059B000A0110020A0110020A0110020A41100209F +:1059C000FEE700BFB7EE000AF7EE000AB7EE001AD6 +:1059D000F7EE001AB7EE002AF7EE002AB7EE003A0B +:1059E000F7EE003AB7EE004AF7EE004AB7EE005A7B +:1059F000F7EE005AB7EE006AF7EE006AB7EE007AEB +:105A0000F7EE007AF1EE10CA40F29F01CFF20001EA +:105A10003CEA010CE1EE10CA002383F300887047D2 +:105A2000FDF79CBAEFF30880EFF309812DE9F00F41 +:105A30006B467246FAF7ACFF08B0FFF7F1FFFEE7DE +:105A4000FDF78CBAEFF30880EFF309812DE9F00F31 +:105A50006B467246FAF79CFF08B0FFF7F1FFFEE7CE +:105A6000FDF77CBAEFF30880EFF309812DE9F00F21 +:105A70006B467246FAF78CFF08B0FFF7F1FFFEE7BE +:105A8000FDF76CBAEFF30880EFF309812DE9F00F11 +:105A90006B467246FAF77CFF08B0FFF7F1FFFEE7AE +:105AA000FDF75CBAEFF30880EFF309812DE9F00F01 +:105AB0006B467246FAF76CFF08B0FFF7F1FFFEE79E +:105AC000814270B40546144602D370BC00F02EB873 +:105AD000821821443CB141EA020313F003030FD1C1 +:105AE000E018032812D86FF00300A30843430020F6 +:105AF00019441A442344984210D1284670BC704778 +:105B000011F8013D013C02F8013DE3E7581850F857 +:105B1000046C981840F8046C043BE1E70C1A14F884 +:105B2000016C141A04F8016C0130E4E770B5044606 +:105B30003AB141EA040313F003030CD1D518032D45 +:105B40000FD822F003031C441944002302F003027F +:105B500093420CD170BD11F8013B013A04F8013BAE +:105B6000E6E7CD1A2E68E51A2E60043BE6E75D5C99 +:105B7000E5540133ECE7F0B5044662B922F00303C3 +:105B8000234402F003021A44934214D1F0BD04F8F6 +:105B9000011B013AF1E7A307F9D115460B0443EACB +:105BA00001630B4343EA01231619032DE6D9771B42 +:105BB0003B60043DF9E703F8011BE5E708B5EFF3A7 +:105BC0000583C3F308030BB1FDF7C8F9BDE808402E +:105BD000FDF74CBA10B50446EFF30583C3F3080391 +:105BE0000BB1FDF7BBF92046BDE81040FDF741BA07 +:105BF0002DE9F04104460D4616461F46EFF3058396 +:105C0000C3F308030BB1FDF7A9F93B463246294619 +:105C10002046BDE8F041FCF743BC2DE9F0410446C5 +:105C20000D4616461F46EFF30583C3F308030BB179 +:105C3000FDF794F93B46324629462046BDE8F0413F +:105C4000FCF768BC08B5EFF30583C3F308030BB199 +:105C5000FDF784F9BDE80840FDF7DBB90020704787 +:105C6000704710B5044608B1FDF75AFF2046BDE85D +:105C70001040FDF745BF10B50446406A10B1A16A57 +:105C8000FFF7EFFF0020C4E9090010BD38B5044656 +:105C9000FFF7F1FF236A2C22012B0CBF05466FF0A2 +:105CA000960500212046FFF766FF284638BD0020F4 +:105CB000704770470020704713B5002001AB1446B1 +:105CC000FDF7E2FF30B9019BA34218BF6FF09300CC +:105CD00002B010BD6FF09200FAE7002070472DE986 +:105CE000E04F2746A046A146A246A346A4462DED76 +:105CF000108B4FF0000545EC185B45EC195A45EC4C +:105D00001A5A45EC1B5A45EC1C5A45EC1D5A45ECF9 +:105D10001E5A45EC1F5AF1EE105A4FF66076C0F647 +:105D2000FF763540E1EE105A84F30088254626467A +:105D3000A447BDEC108BBDE8E08F0000F8B500BFB4 +:105D4000F8BC08BC9E467047F8B500BFF8BC08BC5C +:105D50009E467047FF8FFFFFFF8FFFFFFE8FFFFF05 +:105D6000FE8FFFFFFD8FFFFFFC8FFFFFFC8FFFFF0C +:105D70004661696C20746F2061637175697265207A +:105D80006D757465780A00004661696C20746F2037 +:105D9000696E63726561736520504D20636F756E27 +:105DA0007465720A000000004661696C20746F20FF +:105DB000646563726561736520504D20636F756E15 +:105DC0007465720A000000004661696C20746F20DF +:105DD00072656C65617365206D757465780A000085 +:105DE000436F756C64206E6F74206C6F636B2070F2 +:105DF0006F7765722073617665206D7574657800C4 +:105E00006D757465785F667265652063616C6C653D +:105E1000642077697468204E554C4C207061726123 +:105E20006D6574657200000043616E277420696EB1 +:105E3000697469616C697A65206D757465782C2068 +:105E4000776173204E554C4C0D0A00004661696C19 +:105E500020746F20756E6C6F636B206D7574657840 +:105E60000A0000000A637478206973204E554C4C78 +:105E70000A00000067E6096A85AE67BB72F36E3CF4 +:105E80003AF54FA57F520E518C68059BABD9831F05 +:105E900019CDE05BD89E05C107D57C3617DD703083 +:105EA00039590EF7310BC0FF11155868A78FF964E7 +:105EB000A44FFABE0123456789ABCDEFFEDCBA984B +:105EC00076543210F0E1D2C34011002054464D5FA9 +:105ED00043525950544F0054464D5F504C41544624 +:105EE0004F524D5F53455256494345000000000054 +:105EF00000000000000000000000000000000000A2 +:107C00007FE97FE9FBF72CBD7FE97FE9FBF737BD13 +:107C10007FE97FE9FBF75FBD7FE97FE9FBF752BDB5 +:107C20007FE97FE9FBF73ABD00000000000000009B +:107C30000000000000000000000000000000000044 +:107C40007AFFFFFF00900050000000008C3400001D +:107C50000400000000000000000000000000000020 +:107C6000000000000000000090ED00E000A00350C4 +:107C70007FA60350009000506F9500501412002012 +:107C8000A811002044010000615C00005D5C000060 +:107C9000775B0000DC1000200C1100200411002094 +:107CA00000110020FC1000201D48000011480000B9 +:107CB000054800000000000029480000381100209D +:107CC00030110020281100200000000020110020A9 +:107CD0003549000081480000B5480000FD4800001B +:107CE000682500203A00003A6C2500203A00003A4E +:107CF000702500203A00003A742500203A00003A2E +:107D00000000000000000000000000000000000073 +:107D10000000000000000000000000000000000063 +:107D20000000000000000000000000000000000053 +:107D30000000000000000000000000000000000043 +:107D40000000000000000000000000000000000033 +:107D50000000000000000000000000000000000023 +:087D6000553700002D3700002B +:00000001FF diff --git a/examples/nrf9151/s/.cargo/config.toml b/examples/nrf9151/s/.cargo/config.toml new file mode 100644 index 000000000..f64c63966 --- /dev/null +++ b/examples/nrf9151/s/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +runner = "probe-rs run --chip nRF9160_xxAA" + +[build] +target = "thumbv8m.main-none-eabihf" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml new file mode 100644 index 000000000..7253fc4be --- /dev/null +++ b/examples/nrf9151/s/Cargo.toml @@ -0,0 +1,20 @@ +[package] +edition = "2021" +name = "embassy-nrf9151-secure-examples" +version = "0.1.0" +license = "MIT OR Apache-2.0" + +[dependencies] +embassy-executor = { version = "0.6.0", path = "../../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.2.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } + +defmt = "0.3" +defmt-rtt = "0.4" + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" +panic-probe = { version = "0.3", features = ["print-defmt"] } + +[profile.release] +debug = 2 diff --git a/examples/nrf9151/s/build.rs b/examples/nrf9151/s/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/nrf9151/s/build.rs @@ -0,0 +1,35 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/examples/nrf9151/s/memory.x b/examples/nrf9151/s/memory.x new file mode 100644 index 000000000..4c7d4ebf0 --- /dev/null +++ b/examples/nrf9151/s/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 1024K + RAM : ORIGIN = 0x20018000, LENGTH = 160K +} diff --git a/examples/nrf9151/s/src/bin/blinky.rs b/examples/nrf9151/s/src/bin/blinky.rs new file mode 100644 index 000000000..7457a95a3 --- /dev/null +++ b/examples/nrf9151/s/src/bin/blinky.rs @@ -0,0 +1,22 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_nrf::gpio::{Level, Output, OutputDrive}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + let mut led = Output::new(p.P0_00, Level::Low, OutputDrive::Standard); + + loop { + led.set_high(); + defmt::info!("high"); + Timer::after_millis(500).await; + led.set_low(); + defmt::info!("low"); + Timer::after_millis(1000).await; + } +} diff --git a/examples/nrf9160/.cargo/config.toml b/examples/nrf9160/.cargo/config.toml index 1444b0cd1..f64c63966 100644 --- a/examples/nrf9160/.cargo/config.toml +++ b/examples/nrf9160/.cargo/config.toml @@ -1,5 +1,4 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] -# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list` runner = "probe-rs run --chip nRF9160_xxAA" [build] diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index 2ff692b24..c30b54ebd 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -5,9 +5,9 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 9bd403f02..5ed51a5c0 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" [dependencies] -embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-98304", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-98304", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-rp = { version = "0.2.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } @@ -29,6 +29,9 @@ reqwless = { version = "0.12.0", features = ["defmt",]} serde = { version = "1.0.203", default-features = false, features = ["derive"] } serde-json-core = "0.5.1" +# for assign resources example +assign-resources = { git = "https://github.com/adamgreig/assign-resources", rev = "94ad10e2729afdf0fd5a77cd12e68409a982f58a" } + #cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m = { version = "0.7.6", features = ["inline-asm"] } cortex-m-rt = "0.7.0" @@ -41,7 +44,7 @@ display-interface = "0.4.1" byte-slice-cast = { version = "1.2.0", default-features = false } smart-leds = "0.3.0" heapless = "0.8" -usbd-hid = "0.7.0" +usbd-hid = "0.8.1" embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0" diff --git a/examples/rp/src/bin/assign_resources.rs b/examples/rp/src/bin/assign_resources.rs new file mode 100644 index 000000000..ff6eff4a2 --- /dev/null +++ b/examples/rp/src/bin/assign_resources.rs @@ -0,0 +1,79 @@ +//! This example demonstrates how to assign resources to multiple tasks by splitting up the peripherals. +//! It is not about sharing the same resources between tasks, see sharing.rs for that or head to https://embassy.dev/book/#_sharing_peripherals_between_tasks) +//! Of course splitting up resources and sharing resources can be combined, yet this example is only about splitting up resources. +//! +//! There are basically two ways we demonstrate here: +//! 1) Assigning resources to a task by passing parts of the peripherals +//! 2) Assigning resources to a task by passing a struct with the split up peripherals, using the assign-resources macro +//! +//! using four LEDs on Pins 10, 11, 20 and 21 + +#![no_std] +#![no_main] + +use assign_resources::assign_resources; +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::{self, PIN_20, PIN_21}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + // initialize the peripherals + let p = embassy_rp::init(Default::default()); + + // 1) Assigning a resource to a task by passing parts of the peripherals. + spawner + .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21)) + .unwrap(); + + // 2) Using the assign-resources macro to assign resources to a task. + // we perform the split, see further below for the definition of the resources struct + let r = split_resources!(p); + // and then we can use them + spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); +} + +// 1) Assigning a resource to a task by passing parts of the peripherals. +#[embassy_executor::task] +async fn double_blinky_manually_assigned(_spawner: Spawner, pin_20: PIN_20, pin_21: PIN_21) { + let mut led_20 = Output::new(pin_20, Level::Low); + let mut led_21 = Output::new(pin_21, Level::High); + + loop { + info!("toggling leds"); + led_20.toggle(); + led_21.toggle(); + Timer::after_secs(1).await; + } +} + +// 2) Using the assign-resources macro to assign resources to a task. +// first we define the resources we want to assign to the task using the assign_resources! macro +// basically this will split up the peripherals struct into smaller structs, that we define here +// naming is up to you, make sure your future self understands what you did here +assign_resources! { + leds: Leds{ + led_10: PIN_10, + led_11: PIN_11, + } + // add more resources to more structs if needed, for example defining one struct for each task +} +// this could be done in another file and imported here, but for the sake of simplicity we do it here +// see https://github.com/adamgreig/assign-resources for more information + +// 2) Using the split resources in a task +#[embassy_executor::task] +async fn double_blinky_macro_assigned(_spawner: Spawner, r: Leds) { + let mut led_10 = Output::new(r.led_10, Level::Low); + let mut led_11 = Output::new(r.led_11, Level::High); + + loop { + info!("toggling leds"); + led_10.toggle(); + led_11.toggle(); + Timer::after_secs(1).await; + } +} diff --git a/examples/rp/src/bin/shared_bus.rs b/examples/rp/src/bin/shared_bus.rs new file mode 100644 index 000000000..c6cb5d64c --- /dev/null +++ b/examples/rp/src/bin/shared_bus.rs @@ -0,0 +1,115 @@ +//! This example shows how to share (async) I2C and SPI buses between multiple devices. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice; +use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice; +use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; +use embassy_rp::gpio::{AnyPin, Level, Output}; +use embassy_rp::i2c::{self, I2c, InterruptHandler}; +use embassy_rp::peripherals::{I2C1, SPI1}; +use embassy_rp::spi::{self, Spi}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::Timer; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +type Spi1Bus = Mutex>; +type I2c1Bus = Mutex>; + +bind_interrupts!(struct Irqs { + I2C1_IRQ => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Here we go!"); + + // Shared I2C bus + let i2c = I2c::new_async(p.I2C1, p.PIN_15, p.PIN_14, Irqs, i2c::Config::default()); + static I2C_BUS: StaticCell = StaticCell::new(); + let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); + + spawner.must_spawn(i2c_task_a(i2c_bus)); + spawner.must_spawn(i2c_task_b(i2c_bus)); + + // Shared SPI bus + let spi_cfg = spi::Config::default(); + let spi = Spi::new(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.DMA_CH0, p.DMA_CH1, spi_cfg); + static SPI_BUS: StaticCell = StaticCell::new(); + let spi_bus = SPI_BUS.init(Mutex::new(spi)); + + // Chip select pins for the SPI devices + let cs_a = Output::new(AnyPin::from(p.PIN_0), Level::High); + let cs_b = Output::new(AnyPin::from(p.PIN_1), Level::High); + + spawner.must_spawn(spi_task_a(spi_bus, cs_a)); + spawner.must_spawn(spi_task_b(spi_bus, cs_b)); +} + +#[embassy_executor::task] +async fn i2c_task_a(i2c_bus: &'static I2c1Bus) { + let i2c_dev = I2cDevice::new(i2c_bus); + let _sensor = DummyI2cDeviceDriver::new(i2c_dev, 0xC0); + loop { + info!("i2c task A"); + Timer::after_secs(1).await; + } +} + +#[embassy_executor::task] +async fn i2c_task_b(i2c_bus: &'static I2c1Bus) { + let i2c_dev = I2cDevice::new(i2c_bus); + let _sensor = DummyI2cDeviceDriver::new(i2c_dev, 0xDE); + loop { + info!("i2c task B"); + Timer::after_secs(1).await; + } +} + +#[embassy_executor::task] +async fn spi_task_a(spi_bus: &'static Spi1Bus, cs: Output<'static>) { + let spi_dev = SpiDevice::new(spi_bus, cs); + let _sensor = DummySpiDeviceDriver::new(spi_dev); + loop { + info!("spi task A"); + Timer::after_secs(1).await; + } +} + +#[embassy_executor::task] +async fn spi_task_b(spi_bus: &'static Spi1Bus, cs: Output<'static>) { + let spi_dev = SpiDevice::new(spi_bus, cs); + let _sensor = DummySpiDeviceDriver::new(spi_dev); + loop { + info!("spi task B"); + Timer::after_secs(1).await; + } +} + +// Dummy I2C device driver, using `embedded-hal-async` +struct DummyI2cDeviceDriver { + _i2c: I2C, +} + +impl DummyI2cDeviceDriver { + fn new(i2c_dev: I2C, _address: u8) -> Self { + Self { _i2c: i2c_dev } + } +} + +// Dummy SPI device driver, using `embedded-hal-async` +struct DummySpiDeviceDriver { + _spi: SPI, +} + +impl DummySpiDeviceDriver { + fn new(spi_dev: SPI) -> Self { + Self { _spi: spi_dev } + } +} diff --git a/examples/rp/src/bin/sharing.rs b/examples/rp/src/bin/sharing.rs new file mode 100644 index 000000000..5416e20ce --- /dev/null +++ b/examples/rp/src/bin/sharing.rs @@ -0,0 +1,150 @@ +//! This example shows some common strategies for sharing resources between tasks. +//! +//! We demonstrate five different ways of sharing, covering different use cases: +//! - Atomics: This method is used for simple values, such as bool and u8..u32 +//! - Blocking Mutex: This is used for sharing non-async things, using Cell/RefCell for interior mutability. +//! - Async Mutex: This is used for sharing async resources, where you need to hold the lock across await points. +//! The async Mutex has interior mutability built-in, so no RefCell is needed. +//! - Cell: For sharing Copy types between tasks running on the same executor. +//! - RefCell: When you want &mut access to a value shared between tasks running on the same executor. +//! +//! More information: https://embassy.dev/book/#_sharing_peripherals_between_tasks + +#![no_std] +#![no_main] + +use core::cell::{Cell, RefCell}; +use core::sync::atomic::{AtomicU32, Ordering}; + +use cortex_m_rt::entry; +use defmt::info; +use embassy_executor::{Executor, InterruptExecutor}; +use embassy_rp::clocks::RoscRng; +use embassy_rp::interrupt::{InterruptExt, Priority}; +use embassy_rp::peripherals::UART0; +use embassy_rp::uart::{self, InterruptHandler, UartTx}; +use embassy_rp::{bind_interrupts, interrupt}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::{blocking_mutex, mutex}; +use embassy_time::{Duration, Ticker}; +use rand::RngCore; +use static_cell::{ConstStaticCell, StaticCell}; +use {defmt_rtt as _, panic_probe as _}; + +type UartAsyncMutex = mutex::Mutex>; + +struct MyType { + inner: u32, +} + +static EXECUTOR_HI: InterruptExecutor = InterruptExecutor::new(); +static EXECUTOR_LOW: StaticCell = StaticCell::new(); + +// Use Atomics for simple values +static ATOMIC: AtomicU32 = AtomicU32::new(0); + +// Use blocking Mutex with Cell/RefCell for sharing non-async things +static MUTEX_BLOCKING: blocking_mutex::Mutex> = + blocking_mutex::Mutex::new(RefCell::new(MyType { inner: 0 })); + +bind_interrupts!(struct Irqs { + UART0_IRQ => InterruptHandler; +}); + +#[interrupt] +unsafe fn SWI_IRQ_0() { + EXECUTOR_HI.on_interrupt() +} + +#[entry] +fn main() -> ! { + let p = embassy_rp::init(Default::default()); + info!("Here we go!"); + + let uart = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, uart::Config::default()); + // Use the async Mutex for sharing async things (built-in interior mutability) + static UART: StaticCell = StaticCell::new(); + let uart = UART.init(mutex::Mutex::new(uart)); + + // High-priority executor: runs in interrupt mode + interrupt::SWI_IRQ_0.set_priority(Priority::P3); + let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); + spawner.must_spawn(task_a(uart)); + + // Low priority executor: runs in thread mode + let executor = EXECUTOR_LOW.init(Executor::new()); + executor.run(|spawner| { + // No Mutex needed when sharing between tasks running on the same executor + + // Use Cell for Copy-types + static CELL: ConstStaticCell> = ConstStaticCell::new(Cell::new([0; 4])); + let cell = CELL.take(); + + // Use RefCell for &mut access + static REF_CELL: ConstStaticCell> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); + let ref_cell = REF_CELL.take(); + + spawner.must_spawn(task_b(uart, cell, ref_cell)); + spawner.must_spawn(task_c(cell, ref_cell)); + }); +} + +#[embassy_executor::task] +async fn task_a(uart: &'static UartAsyncMutex) { + let mut ticker = Ticker::every(Duration::from_secs(1)); + loop { + let random = RoscRng.next_u32(); + + { + let mut uart = uart.lock().await; + uart.write(b"task a").await.unwrap(); + // The uart lock is released when it goes out of scope + } + + ATOMIC.store(random, Ordering::Relaxed); + + MUTEX_BLOCKING.lock(|x| x.borrow_mut().inner = random); + + ticker.next().await; + } +} + +#[embassy_executor::task] +async fn task_b(uart: &'static UartAsyncMutex, cell: &'static Cell<[u8; 4]>, ref_cell: &'static RefCell) { + let mut ticker = Ticker::every(Duration::from_secs(1)); + loop { + let random = RoscRng.next_u32(); + + uart.lock().await.write(b"task b").await.unwrap(); + + cell.set(random.to_be_bytes()); + + ref_cell.borrow_mut().inner = random; + + ticker.next().await; + } +} + +#[embassy_executor::task] +async fn task_c(cell: &'static Cell<[u8; 4]>, ref_cell: &'static RefCell) { + let mut ticker = Ticker::every(Duration::from_secs(1)); + loop { + info!("======================="); + + let atomic_val = ATOMIC.load(Ordering::Relaxed); + info!("atomic: {}", atomic_val); + + MUTEX_BLOCKING.lock(|x| { + let val = x.borrow().inner; + info!("blocking mutex: {}", val); + }); + + let cell_val = cell.get(); + info!("cell: {:?}", cell_val); + + let ref_cell_val = ref_cell.borrow().inner; + info!("ref_cell: {:?}", ref_cell_val); + + ticker.next().await; + } +} diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index fac61aa04..468d2b61a 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -31,7 +31,7 @@ async fn main(spawner: Spawner) { static RX_BUF: StaticCell<[u8; 16]> = StaticCell::new(); let rx_buf = &mut RX_BUF.init([0; 16])[..]; let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); - let (rx, mut tx) = uart.split(); + let (mut tx, rx) = uart.split(); unwrap!(spawner.spawn(reader(rx))); diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 58ea894f3..87491b1d2 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -6,8 +6,8 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["log"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-std", "executor-thread", "log", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["log", "std", ] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-std", "executor-thread", "log", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["log", "std", ] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features=[ "std", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } embassy-net-ppp = { version = "0.1.0", path = "../../embassy-net-ppp", features = ["log"]} diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 331046a80..9102467eb 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" # Change stm32c031c6 to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 15fb55ca7..724efdaff 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -13,8 +13,8 @@ defmt = "0.3" defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } static_cell = "2" portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 38b615795..0084651a3 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" # Change stm32f103c8 to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index ec9b54920..60eb0eb93 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" # Change stm32f207zg to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 62c0fed16..7fda410d9 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" # Change stm32f303ze to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32f3/src/bin/blocking-tsc.rs b/examples/stm32f3/src/bin/blocking-tsc.rs new file mode 100644 index 000000000..5c8dac94f --- /dev/null +++ b/examples/stm32f3/src/bin/blocking-tsc.rs @@ -0,0 +1,98 @@ +// Example of polling TSC (Touch Sensing Controller) that lights an LED when touch is detected. +// +// Suggested physical setup on STM32F303ZE Nucleo board: +// - Connect a 1000pF capacitor between pin A0 and GND. This is your sampling capacitor. +// - Connect one end of a 1K resistor to pin A1 and leave the other end loose. +// The loose end will act as touch sensor which will register your touch. +// +// Troubleshooting the setup: +// - If no touch seems to be registered, then try to disconnect the sampling capacitor from GND momentarily, +// now the led should light up. Next try using a different value for the sampling capacitor. +// Also experiment with increasing the values for `ct_pulse_high_length`, `ct_pulse_low_length`, `pulse_generator_prescaler`, `max_count_value` and `discharge_delay`. +// +// All configuration values and sampling capacitor value have been determined experimentally. +// Suitable configuration and discharge delay values are highly dependent on the value of the sample capacitor. For example, a shorter discharge delay can be used with smaller capacitor values. +// +#![no_std] +#![no_main] + +use defmt::*; +use embassy_stm32::gpio::{Level, Output, Speed}; +use embassy_stm32::tsc::{self, *}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +/// This example is written for the nucleo-stm32f303ze, with a stm32f303ze chip. +/// +/// Make sure you check/update the following (whether you use the F303ZE or another board): +/// +/// * [ ] Update .cargo/config.toml with the correct `probe-rs run --chip STM32F303ZETx`chip name. +/// * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature, for F303ZE it should be `stm32f303ze`. +/// * [ ] If your board has a special clock or power configuration, make sure that it is +/// set up appropriately. +/// * [ ] If your board has different pin mapping, update any pin numbers or peripherals +/// to match your schematic +/// +/// If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: +/// +/// * Which example you are trying to run +/// * Which chip and board you are using +/// +/// Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org +#[embassy_executor::main] +async fn main(_spawner: embassy_executor::Spawner) { + let device_config = embassy_stm32::Config::default(); + let context = embassy_stm32::init(device_config); + + let tsc_conf = Config { + ct_pulse_high_length: ChargeTransferPulseCycle::_8, + ct_pulse_low_length: ChargeTransferPulseCycle::_8, + spread_spectrum: false, + spread_spectrum_deviation: SSDeviation::new(2).unwrap(), + spread_spectrum_prescaler: false, + pulse_generator_prescaler: PGPrescalerDivider::_32, + max_count_value: MaxCount::_255, + io_default_mode: false, + synchro_pin_polarity: false, + acquisition_mode: false, + max_count_interrupt: false, + channel_ios: TscIOPin::Group1Io1.into(), + shield_ios: 0, // no shield + sampling_ios: TscIOPin::Group1Io2.into(), + }; + + let mut g1: PinGroup = PinGroup::new(); + g1.set_io1(context.PA0, PinType::Sample); + g1.set_io2(context.PA1, PinType::Channel); + + let mut touch_controller = tsc::Tsc::new_blocking(context.TSC, Some(g1), None, None, None, None, None, tsc_conf); + + // LED2 on the STM32F303ZE nucleo-board + let mut led = Output::new(context.PB7, Level::High, Speed::Low); + + // smaller sample capacitor discharge faster and can be used with shorter delay. + let discharge_delay = 5; // ms + + // the interval at which the loop polls for new touch sensor values + let polling_interval = 100; // ms + + info!("polling for touch"); + loop { + touch_controller.start(); + touch_controller.poll_for_acquisition(); + touch_controller.discharge_io(true); + Timer::after_millis(discharge_delay).await; + + let grp1_status = touch_controller.group_get_status(Group::One); + match grp1_status { + GroupStatus::Complete => { + let group_one_val = touch_controller.group_get_value(Group::One); + info!("{}", group_one_val); + led.set_high(); + } + GroupStatus::Ongoing => led.set_low(), + } + + Timer::after_millis(polling_interval).await; + } +} diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 84c44a7b7..1cc0a97da 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -6,10 +6,10 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index d909c7e68..b85361596 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" # Change stm32f429zi to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt" ] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt" ] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } @@ -30,7 +30,7 @@ heapless = { version = "0.8", default-features = false } nb = "1.0.0" embedded-storage = "0.3.1" micromath = "2.0.0" -usbd-hid = "0.7.0" +usbd-hid = "0.8.1" static_cell = "2" chrono = { version = "^0.4", default-features = false} diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index 634f13f4e..6a5bd0b29 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml @@ -7,8 +7,8 @@ license = "MIT OR Apache-2.0" [dependencies] # Specific examples only for stm32f469 embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 7fc7d6f42..8c591ebd2 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -8,11 +8,11 @@ license = "MIT OR Apache-2.0" # Change stm32f777zi to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embedded-io-async = { version = "0.6.1" } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index b9d710ca7..a50074ce0 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" # Change stm32g0b1re to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index ac6010f5f..2768147a1 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -8,11 +8,11 @@ license = "MIT OR Apache-2.0" # Change stm32g491re to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -usbd-hid = "0.7.0" +usbd-hid = "0.8.1" defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 59d3a9759..30b1d2be9 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -8,10 +8,10 @@ license = "MIT OR Apache-2.0" # Change stm32h563zi to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 78343b74f..13fce7dc7 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -8,11 +8,11 @@ license = "MIT OR Apache-2.0" # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index fc21cc894..93e9575b6 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -7,9 +7,9 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index 13d33320f..f97dfd722 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -8,10 +8,10 @@ license = "MIT OR Apache-2.0" # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 5b0519ac4..2577f19e0 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" # Change stm32l072cz to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32l0/src/bin/async-tsc.rs b/examples/stm32l0/src/bin/async-tsc.rs new file mode 100644 index 000000000..c40b86af9 --- /dev/null +++ b/examples/stm32l0/src/bin/async-tsc.rs @@ -0,0 +1,122 @@ +// Example of async TSC (Touch Sensing Controller) that lights an LED when touch is detected. +// +// Suggested physical setup on STM32L073RZ Nucleo board: +// - Connect a 1000pF capacitor between pin A0 and GND. This is your sampling capacitor. +// - Connect one end of a 1K resistor to pin A1 and leave the other end loose. +// The loose end will act as touch sensor which will register your touch. +// +// Troubleshooting the setup: +// - If no touch seems to be registered, then try to disconnect the sampling capacitor from GND momentarily, +// now the led should light up. Next try using a different value for the sampling capacitor. +// Also experiment with increasing the values for `ct_pulse_high_length`, `ct_pulse_low_length`, `pulse_generator_prescaler`, `max_count_value` and `discharge_delay`. +// +// All configuration values and sampling capacitor value have been determined experimentally. +// Suitable configuration and discharge delay values are highly dependent on the value of the sample capacitor. For example, a shorter discharge delay can be used with smaller capacitor values. +// +#![no_std] +#![no_main] + +use defmt::*; +use embassy_stm32::bind_interrupts; +use embassy_stm32::gpio::{Level, Output, Speed}; +use embassy_stm32::tsc::{self, *}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + TSC => InterruptHandler; +}); + +#[cortex_m_rt::exception] +unsafe fn HardFault(_: &cortex_m_rt::ExceptionFrame) -> ! { + cortex_m::peripheral::SCB::sys_reset(); +} + +/// This example is written for the nucleo-stm32l073rz, with a stm32l073rz chip. +/// +/// Make sure you check/update the following (whether you use the L073RZ or another board): +/// +/// * [ ] Update .cargo/config.toml with the correct `probe-rs run --chip STM32L073RZTx`chip name. +/// * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature, for L073RZ it should be `stm32l073rz`. +/// * [ ] If your board has a special clock or power configuration, make sure that it is +/// set up appropriately. +/// * [ ] If your board has different pin mapping, update any pin numbers or peripherals +/// to match your schematic +/// +/// If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: +/// +/// * Which example you are trying to run +/// * Which chip and board you are using +/// +/// Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org +#[embassy_executor::main] +async fn main(_spawner: embassy_executor::Spawner) { + let device_config = embassy_stm32::Config::default(); + let context = embassy_stm32::init(device_config); + + let config = tsc::Config { + ct_pulse_high_length: ChargeTransferPulseCycle::_4, + ct_pulse_low_length: ChargeTransferPulseCycle::_4, + spread_spectrum: false, + spread_spectrum_deviation: SSDeviation::new(2).unwrap(), + spread_spectrum_prescaler: false, + pulse_generator_prescaler: PGPrescalerDivider::_16, + max_count_value: MaxCount::_255, + io_default_mode: false, + synchro_pin_polarity: false, + acquisition_mode: false, + max_count_interrupt: false, + channel_ios: TscIOPin::Group1Io1.into(), + shield_ios: 0, // no shield + sampling_ios: TscIOPin::Group1Io2.into(), + }; + + let mut g1: PinGroup = PinGroup::new(); + g1.set_io1(context.PA0, PinType::Sample); + g1.set_io2(context.PA1, PinType::Channel); + + let mut touch_controller = tsc::Tsc::new_async( + context.TSC, + Some(g1), + None, + None, + None, + None, + None, + None, + None, + config, + Irqs, + ); + + // Check if TSC is ready + if touch_controller.get_state() != State::Ready { + info!("TSC not ready!"); + loop {} // Halt execution + } + info!("TSC initialized successfully"); + + // LED2 on the STM32L073RZ nucleo-board (PA5) + let mut led = Output::new(context.PA5, Level::High, Speed::Low); + + // smaller sample capacitor discharge faster and can be used with shorter delay. + let discharge_delay = 5; // ms + + info!("Starting touch_controller interface"); + loop { + touch_controller.start(); + touch_controller.pend_for_acquisition().await; + touch_controller.discharge_io(true); + Timer::after_millis(discharge_delay).await; + + let grp1_status = touch_controller.group_get_status(Group::One); + match grp1_status { + GroupStatus::Complete => { + let group_one_val = touch_controller.group_get_value(Group::One); + info!("{}", group_one_val); + led.set_high(); + } + GroupStatus::Ongoing => led.set_low(), + } + } +} diff --git a/examples/stm32l0/src/bin/blocking-tsc.rs b/examples/stm32l0/src/bin/blocking-tsc.rs new file mode 100644 index 000000000..7e4f40946 --- /dev/null +++ b/examples/stm32l0/src/bin/blocking-tsc.rs @@ -0,0 +1,116 @@ +// Example of polling TSC (Touch Sensing Controller) that lights an LED when touch is detected. +// +// Suggested physical setup on STM32L073RZ Nucleo board: +// - Connect a 1000pF capacitor between pin A0 and GND. This is your sampling capacitor. +// - Connect one end of a 1K resistor to pin A1 and leave the other end loose. +// The loose end will act as touch sensor which will register your touch. +// +// Troubleshooting the setup: +// - If no touch seems to be registered, then try to disconnect the sampling capacitor from GND momentarily, +// now the led should light up. Next try using a different value for the sampling capacitor. +// Also experiment with increasing the values for `ct_pulse_high_length`, `ct_pulse_low_length`, `pulse_generator_prescaler`, `max_count_value` and `discharge_delay`. +// +// All configuration values and sampling capacitor value have been determined experimentally. +// Suitable configuration and discharge delay values are highly dependent on the value of the sample capacitor. For example, a shorter discharge delay can be used with smaller capacitor values. +// +#![no_std] +#![no_main] + +use defmt::*; +use embassy_stm32::gpio::{Level, Output, Speed}; +use embassy_stm32::tsc::{self, *}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +/// This example is written for the nucleo-stm32l073rz, with a stm32l073rz chip. +/// +/// Make sure you check/update the following (whether you use the L073RZ or another board): +/// +/// * [ ] Update .cargo/config.toml with the correct `probe-rs run --chip STM32L073RZTx`chip name. +/// * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature, for L073RZ it should be `stm32l073rz`. +/// * [ ] If your board has a special clock or power configuration, make sure that it is +/// set up appropriately. +/// * [ ] If your board has different pin mapping, update any pin numbers or peripherals +/// to match your schematic +/// +/// If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: +/// +/// * Which example you are trying to run +/// * Which chip and board you are using +/// +/// Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org +#[embassy_executor::main] +async fn main(_spawner: embassy_executor::Spawner) { + let device_config = embassy_stm32::Config::default(); + let context = embassy_stm32::init(device_config); + + let tsc_conf = Config { + ct_pulse_high_length: ChargeTransferPulseCycle::_4, + ct_pulse_low_length: ChargeTransferPulseCycle::_4, + spread_spectrum: false, + spread_spectrum_deviation: SSDeviation::new(2).unwrap(), + spread_spectrum_prescaler: false, + pulse_generator_prescaler: PGPrescalerDivider::_16, + max_count_value: MaxCount::_255, + io_default_mode: false, + synchro_pin_polarity: false, + acquisition_mode: false, + max_count_interrupt: false, + channel_ios: TscIOPin::Group1Io1.into(), + shield_ios: 0, // no shield + sampling_ios: TscIOPin::Group1Io2.into(), + }; + + let mut g1: PinGroup = PinGroup::new(); + g1.set_io1(context.PA0, PinType::Sample); + g1.set_io2(context.PA1, PinType::Channel); + + let mut touch_controller = tsc::Tsc::new_blocking( + context.TSC, + Some(g1), + None, + None, + None, + None, + None, + None, + None, + tsc_conf, + ); + + // Check if TSC is ready + if touch_controller.get_state() != State::Ready { + info!("TSC not ready!"); + loop {} // Halt execution + } + info!("TSC initialized successfully"); + + // LED2 on the STM32L073RZ nucleo-board (PA5) + let mut led = Output::new(context.PA5, Level::High, Speed::Low); + + // smaller sample capacitor discharge faster and can be used with shorter delay. + let discharge_delay = 5; // ms + + // the interval at which the loop polls for new touch sensor values + let polling_interval = 100; // ms + + info!("polling for touch"); + loop { + touch_controller.start(); + touch_controller.poll_for_acquisition(); + touch_controller.discharge_io(true); + Timer::after_millis(discharge_delay).await; + + let grp1_status = touch_controller.group_get_status(Group::One); + match grp1_status { + GroupStatus::Complete => { + let group_one_val = touch_controller.group_get_value(Group::One); + info!("{}", group_one_val); + led.set_high(); + } + GroupStatus::Ongoing => led.set_low(), + } + + Timer::after_millis(polling_interval).await; + } +} diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 9e4ceac6a..062044f32 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -6,10 +6,10 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index de2b2bd4d..c5478b17b 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -8,10 +8,10 @@ license = "MIT OR Apache-2.0" # Change stm32l4s5vi to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "chrono"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } -embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } +embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net-adin1110 = { version = "0.2.0", path = "../../embassy-net-adin1110" } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index e4a3c8e9c..16c184de2 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -8,12 +8,12 @@ license = "MIT OR Apache-2.0" # Change stm32l552ze to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -usbd-hid = "0.7.0" +usbd-hid = "0.8.1" defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index afeb4dc34..2e890cdb5 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" # Change stm32u083rc to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index d0134b972..20d64c6f7 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" # Change stm32u585ai to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index c3a11b14b..1e1a0efe2 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -9,8 +9,8 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } defmt = "0.3" diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index dc788e15b..401281c0b 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -7,8 +7,8 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } defmt = "0.3" diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 3ea7d0cbe..46af5218c 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -8,9 +8,9 @@ license = "MIT OR Apache-2.0" # Change stm32wl55jc-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 9d7acc175..9bd37550c 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -9,8 +9,8 @@ crate-type = ["cdylib"] [dependencies] embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["log"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["log", "wasm", ] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["log", "wasm", ] } wasm-logger = "0.2.0" wasm-bindgen = "0.2" diff --git a/rust-toolchain-nightly.toml b/rust-toolchain-nightly.toml index d965d67dd..dfa231344 100644 --- a/rust-toolchain-nightly.toml +++ b/rust-toolchain-nightly.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "nightly-2024-06-18" +channel = "nightly-2024-07-16" components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ] targets = [ "thumbv7em-none-eabi", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 037fc5c6a..ce9040a70 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.79" +channel = "1.80" components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv7em-none-eabi", diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index c714e8f7e..f666634d5 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -9,9 +9,9 @@ teleprobe-meta = "1" embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt", ] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "task-arena-size-16384", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "task-arena-size-16384", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.2.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } diff --git a/tests/perf-client/Cargo.toml b/tests/perf-client/Cargo.toml index 6ecc2d5e1..eb2a33a30 100644 --- a/tests/perf-client/Cargo.toml +++ b/tests/perf-client/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", ] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", ] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3.0" diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index 4f1d3e5c6..ae2b0e180 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml @@ -7,8 +7,8 @@ license = "MIT OR Apache-2.0" [dependencies] critical-section = { version = "1.1.1", features = ["restore-state-bool"] } embassy-sync = { version = "0.6.0", path = "../../embassy-sync" } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-riscv32", "executor-thread"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time" } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-riscv32", "executor-thread"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time" } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } riscv-rt = "0.12.2" diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 45050ee0e..def270558 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -8,13 +8,13 @@ license = "MIT OR Apache-2.0" teleprobe-meta = "1.1" embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", ] } -embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", ] } +embassy-rp = { version = "0.2.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal/"} +embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal/"} cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { path = "../../cyw43-pio", features = ["defmt", "overclock"] } perf-client = { path = "../perf-client" } diff --git a/tests/rp/src/bin/timer.rs b/tests/rp/src/bin/timer.rs new file mode 100644 index 000000000..be9242144 --- /dev/null +++ b/tests/rp/src/bin/timer.rs @@ -0,0 +1,25 @@ +#![no_std] +#![no_main] +teleprobe_meta::target!(b"rpi-pico"); + +use defmt::{assert, *}; +use embassy_executor::Spawner; +use embassy_time::{Instant, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + let start = Instant::now(); + Timer::after_millis(100).await; + let end = Instant::now(); + let ms = (end - start).as_millis(); + info!("slept for {} ms", ms); + assert!(ms >= 99); + assert!(ms < 110); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index f94814e70..2eac636e5 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -60,8 +60,8 @@ cm0 = ["portable-atomic/unsafe-assume-single-core"] teleprobe-meta = "1" embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.3.1", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } +embassy-executor = { version = "0.6.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] }