Initial commit

This commit is contained in:
ris 2024-12-21 00:48:45 -05:00
commit ec43b90ddd
1976 changed files with 308007 additions and 0 deletions

13
.cargo/config.toml Normal file
View File

@ -0,0 +1,13 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
#runner = "probe-rs run --chip RP2040"
runner = "probe-rs run --chip esp32c6"
[build]
target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
[env]
SSID = "SSID"
SSID_PASSWORD = "PSK"
CLIENT_ID = "495f6297-b962-4266-9c00-74138ae5a1f1"
DEFMT_LOG = "debug"
LED_SIZE = "100"

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "embassy"]
path = embassy
url = https://github.com/embassy-rs/embassy.git
[submodule "embedded-nal"]
path = embedded-nal
url = https://github.com/rust-embedded-community/embedded-nal.git
[submodule "rp-hal"]
path = rp-hal
url = https://github.com/rp-rs/rp-hal.git

View File

@ -0,0 +1,5 @@
# This directory is a Syncthing folder marker.
# Do not delete.
folderID: ggvqx-3ckoc
created: 2024-10-27T17:32:22-04:00

1
.stignore Normal file
View File

@ -0,0 +1 @@
target/

View File

@ -0,0 +1,18 @@
[package]
authors = ["Dario Nieuwenhuis <dirbaio@dirbaio.net>"]
edition = "2018"
name = "embassy-basic-example"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
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"
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }

View File

@ -0,0 +1,15 @@
[package]
name = "blinky-async"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
[dependencies]
cortex-m = "0.7"
cortex-m-rt = "0.7"
embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] }
embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", "executor-thread"] }
defmt = "0.3.0"
defmt-rtt = "0.3.0"
panic-probe = { version = "0.3.0", features = ["print-defmt"] }

View File

@ -0,0 +1,24 @@
= Embassy in the wild!
Here are known examples of real-world projects which make use of Embassy. Feel free to link:https://github.com/embassy-rs/embassy/blob/main/docs/pages/embassy_in_the_wild.adoc[add more]!
* link:https://github.com/1-rafael-1/pi-pico-alarmclock-rust[A Raspberry Pi Pico W Alarmclock]
** A hobbyist project building an alarm clock around a Pi Pico W complete with code, components list and enclosure design files.
* link:https://github.com/haobogu/rmk/[RMK: A feature-rich Rust keyboard firmware]
** RMK has built-in layer support, wireless(BLE) support, real-time key editing support using vial, and more!
** Targets STM32, RP2040, nRF52 and ESP32 MCUs
* link:https://github.com/cbruiz/printhor/[Printhor: The highly reliable but not necessarily functional 3D printer firmware]
** Targets some STM32 MCUs
* link:https://github.com/card-io-ecg/card-io-fw[Card/IO firmware] - firmware for an open source ECG device
** Targets the ESP32-S3 or ESP32-C6 MCU
* The link:https://github.com/lora-rs/lora-rs[lora-rs] project includes link:https://github.com/lora-rs/lora-rs/tree/main/examples/stm32l0/src/bin[various standalone examples] for NRF52840, RP2040, STM32L0 and STM32WL
* link:https://github.com/matoushybl/air-force-one[Air force one: A simple air quality monitoring system]
** Targets nRF52 and uses nrf-softdevice
* link:https://github.com/schmettow/ylab-edge-go[YLab Edge Go] and link:https://github.com/schmettow/ylab-edge-pro[YLab Edge Pro] projects develop
firmware (RP2040, STM32) for capturing physiological data in behavioural science research. Included so far are:
** biopotentials (analog ports)
** motion capture (6-axis accelerometers)
** air quality (CO2, Temp, Humidity)
** comes with an app for capturing and visualizing data [link:https://github.com/schmettow/ystudio-zero[Ystudio]]

View File

@ -0,0 +1,202 @@
= Starting a new project
Once youve successfully xref:#_getting_started[run some example projects], the next step is to make a standalone Embassy project.
== Tools for generating Embassy projects
=== CLI
- link:https://github.com/adinack/cargo-embassy[cargo-embassy] (STM32 and NRF)
=== cargo-generate
- link:https://github.com/lulf/embassy-template[embassy-template] (STM32, NRF, and RP)
- link:https://github.com/bentwire/embassy-rp2040-template[embassy-rp2040-template] (RP)
== Starting a project from scratch
As an example, lets create a new embassy project from scratch for a STM32G474. The same instructions are applicable for any supported chip with some minor changes.
Run:
[source,bash]
----
cargo new stm32g474-example
cd stm32g474-example
----
to create an empty rust project:
[source]
----
stm32g474-example
├── Cargo.toml
└── src
└── main.rs
----
Looking in link:https://github.com/embassy-rs/embassy/tree/main/examples[the Embassy examples], we can see theres a `stm32g4` folder. Find `src/blinky.rs` and copy its contents into our `src/main.rs`.
=== The .cargo/config.toml
Currently, wed need to provide cargo with a target triple every time we run `cargo build` or `cargo run`. Lets spare ourselves that work by copying `.cargo/config.toml` from `examples/stm32g4` into our project.
[source]
----
stm32g474-example
├── .cargo
│   └── config.toml
├── Cargo.toml
└── src
└── main.rs
----
In addition to a target triple, `.cargo/config.toml` contains a `runner` key which allows us to conveniently run our project on hardware with `cargo run` via probe-rs. In order for this to work, we need to provide the correct chip ID. We can do this by checking `probe-rs chip list`:
[source,bash]
----
$ probe-rs chip list | grep -i stm32g474re
STM32G474RETx
----
and copying `STM32G474RETx` into `.cargo/config.toml` as so:
[source,toml]
----
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# replace STM32G071C8Rx with your chip as listed in `probe-rs chip list`
runner = "probe-rs run --chip STM32G474RETx"
----
=== Cargo.toml
Now that cargo knows what target to compile for (and probe-rs knows what chip to run it on), were ready to add some dependencies.
Looking in `examples/stm32g4/Cargo.toml`, we can see that the examples require a number of embassy crates. For blinky, well only need three of them: `embassy-stm32`, `embassy-executor` and `embassy-time`.
At the time of writing, embassy is already published to crates.io. Therefore, dependencies can easily added via Cargo.toml.
[source,toml]
----
[dependencies]
embassy-stm32 = { version = "0.1.0", features = ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"] }
embassy-executor = { version = "0.6.1", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
----
Prior, embassy needed to be installed straight from the git repository. Installing from git is still useful, if you want to checkout a specic revision of an embassy crate which is not yet published.
The recommended way of doing so is as follows:
* Copy the required `embassy-*` lines from the example `Cargo.toml`
* Make any necessary changes to `features`, e.g. requiring the `stm32g474re` feature of `embassy-stm32`
* Remove the `path = ""` keys in the `embassy-*` entries
* Create a `[patch.crates-io]` section, with entries for each embassy crate we need. These should all contain identical values: a link to the git repository, and a reference to the commit were checking out. Assuming you want the latest commit, you can find it by running `git ls-remote https://github.com/embassy-rs/embassy.git HEAD`
NOTE: When using this method, its necessary that the `version` keys in `[dependencies]` match up with the versions defined in each crates `Cargo.toml` in the specificed `rev` under `[patch.crates.io]`. This means that when updating, you have to a pick a new revision, change everything in `[patch.crates.io]` to match it, and then correct any versions under `[dependencies]` which have changed.
An example Cargo.toml file might look as follows:
[source,toml]
----
[dependencies]
embassy-stm32 = {version = "0.1.0", features = ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"]}
embassy-executor = { version = "0.3.3", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
[patch.crates-io]
embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }
embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }
----
There are a few other dependencies we need to build the project, but fortunately theyre much simpler to install. Copy their lines from the example `Cargo.toml` to the the `[dependencies]` section in the new `Cargo.toml`:
[source,toml]
----
defmt = "0.3.5"
defmt-rtt = "0.4.0"
cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]}
cortex-m-rt = "0.7.3"
panic-probe = "0.3.1"
----
These are the bare minimum dependencies required to run `blinky.rs`, but its worth taking a look at the other dependencies specified in the example `Cargo.toml`, and noting what features are required for use with embassy for example `futures = { version = "0.3.17", default-features = false, features = ["async-await"] }`.
Finally, copy the `[profile.release]` section from the example `Cargo.toml` into ours.
[source,toml]
----
[profile.release]
debug = 2
----
=== rust-toolchain.toml
Before we can build our project, we need to add an additional file to tell cargo to use the nightly toolchain. Copy the `rust-toolchain.toml` from the embassy repo to ours, and trim the list of targets down to only the target triple relevent for our project — in this case, `thumbv7em-none-eabi`:
[source]
----
stm32g474-example
├── .cargo
│   └── config.toml
├── Cargo.toml
├── rust-toolchain.toml
└── src
└── main.rs
----
[source,toml]
----
# Before upgrading check that everything is available on all tier1 targets here:
# https://rust-lang.github.io/rustup-components-history
[toolchain]
channel = "nightly-2023-11-01"
components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ]
targets = ["thumbv7em-none-eabi"]
----
=== build.rs
In order to produce a working binary for our target, cargo requires a custom build script. Copy `build.rs` from the example to our project:
[source]
----
stm32g474-example
├── build.rs
├── .cargo
│ └── config.toml
├── Cargo.toml
├── rust-toolchain.toml
└── src
└── main.rs
----
=== Building and running
At this point, were finally ready to build and run our project! Connect your board via a debug probe and run:
[source,bash]
----
cargo run --release
----
should result in a blinking LED (if theres one attached to the pin in `src/main.rs` change it if not!) and the following output:
[source]
----
Compiling stm32g474-example v0.1.0 (/home/you/stm32g474-example)
Finished release [optimized + debuginfo] target(s) in 0.22s
Running `probe-rs run --chip STM32G474RETx target/thumbv7em-none-eabi/release/stm32g474-example`
Erasing sectors ✔ [00:00:00] [#########################################################] 18.00 KiB/18.00 KiB @ 54.09 KiB/s (eta 0s )
Programming pages ✔ [00:00:00] [#########################################################] 17.00 KiB/17.00 KiB @ 35.91 KiB/s (eta 0s ) Finished in 0.817s
0.000000 TRACE BDCR configured: 00008200
└─ embassy_stm32::rcc::bd::{impl#3}::init::{closure#4} @ /home/you/.cargo/git/checkouts/embassy-9312dcb0ed774b29/7703f47/embassy-stm32/src/fmt.rs:117
0.000000 DEBUG rcc: Clocks { sys: Hertz(16000000), pclk1: Hertz(16000000), pclk1_tim: Hertz(16000000), pclk2: Hertz(16000000), pclk2_tim: Hertz(16000000), hclk1: Hertz(16000000), hclk2: Hertz(16000000), pll1_p: None, adc: None, adc34: None, rtc: Some(Hertz(32000)) }
└─ embassy_stm32::rcc::set_freqs @ /home/you/.cargo/git/checkouts/embassy-9312dcb0ed774b29/7703f47/embassy-stm32/src/fmt.rs:130
0.000000 INFO Hello World!
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:14
0.000091 INFO high
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:19
0.300201 INFO low
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:23
----

View File

@ -0,0 +1,87 @@
# Changelog
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.6.2 - 2024-11-06
- The `nightly` feature no longer requires `nightly-2024-09-06` or newer.
## 0.6.1 - 2024-10-21
- Soundness fix: Deny using `impl Trait` in task arguments. This was previously accidentally allowed when not using the `nightly` feature,
and could cause out of bounds memory accesses if spawning the same task mulitple times with different underlying types
for the `impl Trait`. Affected versions are 0.4.x, 0.5.0 and 0.6.0, which have been yanked.
- Add an architecture-agnostic executor that spins waiting for tasks to run, enabled with the `arch-spin` feature.
- Update for breaking change in the nightly waker_getters API. The `nightly` feature now requires `nightly-2024-09-06` or newer.
- Improve macro error messages.
## 0.6.0 - 2024-08-05
- Add collapse_debuginfo to fmt.rs macros.
- initial support for AVR
- use nightly waker_getters APIs
## 0.5.1 - 2024-10-21
- Soundness fix: Deny using `impl Trait` in task arguments. This was previously accidentally allowed when not using the `nightly` feature,
and could cause out of bounds memory accesses if spawning the same task mulitple times with different underlying types
for the `impl Trait`. Affected versions are 0.4.x, 0.5.0 and 0.6.0, which have been yanked.
## 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.
## 0.4.0 - 2023-12-05
- Removed `arch-xtensa`. Use the executor provided by the HAL crate (`esp-hal`, `esp32s3-hal`, etc...) instead.
- Added an arena allocator for tasks, allowing using the `main` and `task` macros on Rust 1.75 stable. (it is only used if the `nightly` feature is not enabled. When `nightly` is enabled, `type_alias_impl_trait` is used to statically allocate tasks, as before).
## 0.3.3 - 2023-11-15
- Add `main` macro reexport for Xtensa arch.
- Remove use of `atomic-polyfill`. The executor now has multiple implementations of its internal data structures for cases where the target supports atomics or doesn't.
## 0.3.2 - 2023-11-06
- Use `atomic-polyfill` for `riscv32`
- Removed unused dependencies (static_cell, futures-util)
## 0.3.1 - 2023-11-01
- Fix spurious "Found waker not created by the Embassy executor" error in recent nightlies.
## 0.3.0 - 2023-08-25
- Replaced Pender. Implementations now must define an extern function called `__pender`.
- Made `raw::AvailableTask` public
- Made `SpawnToken::new_failed` public
- You can now use arbitrary expressions to specify `#[task(pool_size = X)]`
## 0.2.1 - 2023-08-10
- Avoid calling `pend()` when waking expired timers
- Properly reset finished task state with `integrated-timers` enabled
- Introduce `InterruptExecutor::spawner()`
- Fix incorrect critical section in Xtensa executor
## 0.2.0 - 2023-04-27
- Replace unnecessary atomics in runqueue
- add Pender, rework Cargo features.
- add support for turbo-wakers.
- Allow TaskStorage to auto-implement `Sync`
- Use AtomicPtr for signal_ctx, removes 1 unsafe.
- Replace unsound critical sections with atomics
## 0.1.1 - 2022-11-23
- Fix features for documentation
## 0.1.0 - 2022-11-23
- First release

View File

@ -0,0 +1,191 @@
[package]
name = "embassy-executor"
version = "0.6.2"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "async/await executor designed for embedded usage"
repository = "https://github.com/embassy-rs/embassy"
documentation = "https://docs.embassy.dev/embassy-executor"
categories = [
"embedded",
"no-std",
"asynchronous",
]
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/"
features = ["defmt"]
flavors = [
{ name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] },
{ name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] },
{ name = "cortex-m", target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] },
{ name = "riscv32", target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32", "executor-thread"] },
]
[package.metadata.docs.rs]
default-target = "thumbv7em-none-eabi"
targets = ["thumbv7em-none-eabi"]
features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"]
[dependencies]
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.6.2", 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"
document-features = "0.2.7"
# needed for AVR
portable-atomic = { version = "1.5", optional = true }
# arch-cortex-m dependencies
cortex-m = { version = "0.7.6", optional = true }
# arch-wasm dependencies
wasm-bindgen = { version = "0.2.82", optional = true }
js-sys = { version = "0.3", optional = true }
# arch-avr dependencies
avr-device = { version = "0.5.3", optional = true }
[dev-dependencies]
critical-section = { version = "1.1", features = ["std"] }
trybuild = "1.0"
[build-dependencies]
rustc_version = "0.4.1"
[features]
## Enable nightly-only features
nightly = ["embassy-executor-macros/nightly"]
# Enables turbo wakers, which requires patching core. Not surfaced in the docs by default due to
# being an complicated advanced and undocumented feature.
# See: https://github.com/embassy-rs/embassy/pull/1263
turbowakers = []
## Use the executor-integrated `embassy-time` timer queue.
integrated-timers = ["dep:embassy-time-driver", "dep:embassy-time-queue-driver"]
#! ### Architecture
_arch = [] # some arch was picked
## std
arch-std = ["_arch", "critical-section/std"]
## Cortex-M
arch-cortex-m = ["_arch", "dep:cortex-m"]
## RISC-V 32
arch-riscv32 = ["_arch"]
## WASM
arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys", "critical-section/std"]
## AVR
arch-avr = ["_arch", "dep:portable-atomic", "dep:avr-device"]
## spin (architecture agnostic; never sleeps)
arch-spin = ["_arch"]
#! ### Executor
## Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs)
executor-thread = []
## Enable the interrupt-mode executor (available in Cortex-M only)
executor-interrupt = []
#! ### Task Arena Size
#! Sets the [task arena](#task-arena) size. Necessary if youre not using `nightly`.
#!
#! <details>
#! <summary>Preconfigured Task Arena Sizes:</summary>
#! <!-- rustdoc requires the following blank line for the feature list to render correctly! -->
#!
# BEGIN AUTOGENERATED CONFIG FEATURES
# Generated by gen_config.py. DO NOT EDIT.
## 64
task-arena-size-64 = []
## 128
task-arena-size-128 = []
## 192
task-arena-size-192 = []
## 256
task-arena-size-256 = []
## 320
task-arena-size-320 = []
## 384
task-arena-size-384 = []
## 512
task-arena-size-512 = []
## 640
task-arena-size-640 = []
## 768
task-arena-size-768 = []
## 1024
task-arena-size-1024 = []
## 1280
task-arena-size-1280 = []
## 1536
task-arena-size-1536 = []
## 2048
task-arena-size-2048 = []
## 2560
task-arena-size-2560 = []
## 3072
task-arena-size-3072 = []
## 4096 (default)
task-arena-size-4096 = [] # Default
## 5120
task-arena-size-5120 = []
## 6144
task-arena-size-6144 = []
## 8192
task-arena-size-8192 = []
## 10240
task-arena-size-10240 = []
## 12288
task-arena-size-12288 = []
## 16384
task-arena-size-16384 = []
## 20480
task-arena-size-20480 = []
## 24576
task-arena-size-24576 = []
## 32768
task-arena-size-32768 = []
## 40960
task-arena-size-40960 = []
## 49152
task-arena-size-49152 = []
## 65536
task-arena-size-65536 = []
## 81920
task-arena-size-81920 = []
## 98304
task-arena-size-98304 = []
## 131072
task-arena-size-131072 = []
## 163840
task-arena-size-163840 = []
## 196608
task-arena-size-196608 = []
## 262144
task-arena-size-262144 = []
## 327680
task-arena-size-327680 = []
## 393216
task-arena-size-393216 = []
## 524288
task-arena-size-524288 = []
## 655360
task-arena-size-655360 = []
## 786432
task-arena-size-786432 = []
## 1048576
task-arena-size-1048576 = []
# END AUTOGENERATED CONFIG FEATURES
#! </details>

View File

@ -0,0 +1,145 @@
// NOTE: this file is copy-pasted between several Embassy crates, because there is no
// straightforward way to share this code:
// - it cannot be placed into the root of the repo and linked from each build.rs using `#[path =
// "../build_common.rs"]`, because `cargo publish` requires that all files published with a crate
// reside in the crate's directory,
// - it cannot be symlinked from `embassy-xxx/build_common.rs` to `../build_common.rs`, because
// symlinks don't work on Windows.
use std::collections::HashSet;
use std::env;
/// Helper for emitting cargo instruction for enabling configs (`cargo:rustc-cfg=X`) and declaring
/// them (`cargo:rust-check-cfg=cfg(X)`).
#[derive(Debug)]
pub struct CfgSet {
enabled: HashSet<String>,
declared: HashSet<String>,
}
impl CfgSet {
pub fn new() -> Self {
Self {
enabled: HashSet::new(),
declared: HashSet::new(),
}
}
/// Enable a config, which can then be used in `#[cfg(...)]` for conditional compilation.
///
/// All configs that can potentially be enabled should be unconditionally declared using
/// [`Self::declare()`].
pub fn enable(&mut self, cfg: impl AsRef<str>) {
if self.enabled.insert(cfg.as_ref().to_owned()) {
println!("cargo:rustc-cfg={}", cfg.as_ref());
}
}
pub fn enable_all(&mut self, cfgs: &[impl AsRef<str>]) {
for cfg in cfgs.iter() {
self.enable(cfg.as_ref());
}
}
/// Declare a valid config for conditional compilation, without enabling it.
///
/// This enables rustc to check that the configs in `#[cfg(...)]` attributes are valid.
pub fn declare(&mut self, cfg: impl AsRef<str>) {
if self.declared.insert(cfg.as_ref().to_owned()) {
println!("cargo:rustc-check-cfg=cfg({})", cfg.as_ref());
}
}
pub fn declare_all(&mut self, cfgs: &[impl AsRef<str>]) {
for cfg in cfgs.iter() {
self.declare(cfg.as_ref());
}
}
pub fn set(&mut self, cfg: impl Into<String>, enable: bool) {
let cfg = cfg.into();
if enable {
self.enable(cfg.clone());
}
self.declare(cfg);
}
}
/// Sets configs that describe the target platform.
pub fn set_target_cfgs(cfgs: &mut CfgSet) {
let target = env::var("TARGET").unwrap();
if target.starts_with("thumbv6m-") {
cfgs.enable_all(&["cortex_m", "armv6m"]);
} else if target.starts_with("thumbv7m-") {
cfgs.enable_all(&["cortex_m", "armv7m"]);
} else if target.starts_with("thumbv7em-") {
cfgs.enable_all(&["cortex_m", "armv7m", "armv7em"]);
} else if target.starts_with("thumbv8m.base") {
cfgs.enable_all(&["cortex_m", "armv8m", "armv8m_base"]);
} else if target.starts_with("thumbv8m.main") {
cfgs.enable_all(&["cortex_m", "armv8m", "armv8m_main"]);
}
cfgs.declare_all(&[
"cortex_m",
"armv6m",
"armv7m",
"armv7em",
"armv8m",
"armv8m_base",
"armv8m_main",
]);
cfgs.set("has_fpu", target.ends_with("-eabihf"));
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct CompilerDate {
year: u16,
month: u8,
day: u8,
}
impl CompilerDate {
fn parse(date: &str) -> Option<Self> {
let mut parts = date.split('-');
let year = parts.next()?.parse().ok()?;
let month = parts.next()?.parse().ok()?;
let day = parts.next()?.parse().ok()?;
Some(Self { year, month, day })
}
}
impl PartialEq<&str> for CompilerDate {
fn eq(&self, other: &&str) -> bool {
let Some(other) = Self::parse(other) else {
return false;
};
self.eq(&other)
}
}
impl PartialOrd<&str> for CompilerDate {
fn partial_cmp(&self, other: &&str) -> Option<std::cmp::Ordering> {
Self::parse(other).map(|other| self.cmp(&other))
}
}
pub struct CompilerInfo {
#[allow(unused)]
pub version: rustc_version::Version,
pub channel: rustc_version::Channel,
pub commit_date: Option<CompilerDate>,
}
pub fn compiler_info() -> Option<CompilerInfo> {
let Ok(meta) = rustc_version::version_meta() else {
return None;
};
Some(CompilerInfo {
version: meta.semver,
channel: meta.channel,
commit_date: meta.commit_date.as_deref().and_then(CompilerDate::parse),
})
}

View File

@ -0,0 +1,110 @@
use std::collections::HashMap;
use std::fmt::Write;
use std::path::PathBuf;
use std::{env, fs};
#[path = "./build_common.rs"]
mod common;
static CONFIGS: &[(&str, usize)] = &[
// BEGIN AUTOGENERATED CONFIG FEATURES
// Generated by gen_config.py. DO NOT EDIT.
("TASK_ARENA_SIZE", 4096),
// END AUTOGENERATED CONFIG FEATURES
];
struct ConfigState {
value: usize,
seen_feature: bool,
seen_env: bool,
}
fn main() {
let crate_name = env::var("CARGO_PKG_NAME")
.unwrap()
.to_ascii_uppercase()
.replace('-', "_");
// only rebuild if build.rs changed. Otherwise Cargo will rebuild if any
// other file changed.
println!("cargo:rerun-if-changed=build.rs");
// Rebuild if config envvar changed.
for (name, _) in CONFIGS {
println!("cargo:rerun-if-env-changed={crate_name}_{name}");
}
let mut configs = HashMap::new();
for (name, default) in CONFIGS {
configs.insert(
*name,
ConfigState {
value: *default,
seen_env: false,
seen_feature: false,
},
);
}
let prefix = format!("{crate_name}_");
for (var, value) in env::vars() {
if let Some(name) = var.strip_prefix(&prefix) {
let Some(cfg) = configs.get_mut(name) else {
panic!("Unknown env var {name}")
};
let Ok(value) = value.parse::<usize>() else {
panic!("Invalid value for env var {name}: {value}")
};
cfg.value = value;
cfg.seen_env = true;
}
if let Some(feature) = var.strip_prefix("CARGO_FEATURE_") {
if let Some(i) = feature.rfind('_') {
let name = &feature[..i];
let value = &feature[i + 1..];
if let Some(cfg) = configs.get_mut(name) {
let Ok(value) = value.parse::<usize>() else {
panic!("Invalid value for feature {name}: {value}")
};
// envvars take priority.
if !cfg.seen_env {
if cfg.seen_feature {
panic!("multiple values set for feature {}: {} and {}", name, cfg.value, value);
}
cfg.value = value;
cfg.seen_feature = true;
}
}
}
}
}
let mut data = String::new();
for (name, cfg) in &configs {
writeln!(&mut data, "pub const {}: usize = {};", name, cfg.value).unwrap();
}
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let out_file = out_dir.join("config.rs").to_string_lossy().to_string();
fs::write(out_file, data).unwrap();
let mut rustc_cfgs = common::CfgSet::new();
common::set_target_cfgs(&mut rustc_cfgs);
// Waker API changed on 2024-09-06
rustc_cfgs.declare("at_least_2024_09_06");
let Some(compiler) = common::compiler_info() else {
return;
};
if compiler.channel == rustc_version::Channel::Nightly
&& compiler.commit_date.map(|d| d >= "2024-09-06").unwrap_or(false)
{
rustc_cfgs.enable("at_least_2024_09_06");
}
}

View File

@ -0,0 +1,151 @@
#![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)]
#![cfg_attr(all(feature = "nightly", not(at_least_2024_09_06)), feature(waker_getters))]
#![allow(clippy::new_without_default)]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
//! ## Feature flags
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;
pub use embassy_executor_macros::task;
macro_rules! check_at_most_one {
(@amo [$($feats:literal)*] [] [$($res:tt)*]) => {
#[cfg(any($($res)*))]
compile_error!(concat!("At most one of these features can be enabled at the same time:", $(" `", $feats, "`",)*));
};
(@amo $feats:tt [$curr:literal $($rest:literal)*] [$($res:tt)*]) => {
check_at_most_one!(@amo $feats [$($rest)*] [$($res)* $(all(feature=$curr, feature=$rest),)*]);
};
($($f:literal),*$(,)?) => {
check_at_most_one!(@amo [$($f)*] [$($f)*] []);
};
}
check_at_most_one!(
"arch-avr",
"arch-cortex-m",
"arch-riscv32",
"arch-std",
"arch-wasm",
"arch-spin",
);
#[cfg(feature = "_arch")]
#[cfg_attr(feature = "arch-avr", path = "arch/avr.rs")]
#[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")]
#[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")]
#[cfg_attr(feature = "arch-std", path = "arch/std.rs")]
#[cfg_attr(feature = "arch-wasm", path = "arch/wasm.rs")]
#[cfg_attr(feature = "arch-spin", path = "arch/spin.rs")]
mod arch;
#[cfg(feature = "_arch")]
#[allow(unused_imports)] // don't warn if the module is empty.
pub use arch::*;
pub mod raw;
mod spawner;
pub use spawner::*;
mod config {
#![allow(unused)]
include!(concat!(env!("OUT_DIR"), "/config.rs"));
}
/// Implementation details for embassy macros.
/// Do not use. Used for macros and HALs only. Not covered by semver guarantees.
#[doc(hidden)]
#[cfg(not(feature = "nightly"))]
pub mod _export {
use core::alloc::Layout;
use core::cell::{Cell, UnsafeCell};
use core::future::Future;
use core::mem::MaybeUninit;
use core::ptr::null_mut;
use critical_section::{CriticalSection, Mutex};
use crate::raw::TaskPool;
struct Arena<const N: usize> {
buf: UnsafeCell<MaybeUninit<[u8; N]>>,
ptr: Mutex<Cell<*mut u8>>,
}
unsafe impl<const N: usize> Sync for Arena<N> {}
unsafe impl<const N: usize> Send for Arena<N> {}
impl<const N: usize> Arena<N> {
const fn new() -> Self {
Self {
buf: UnsafeCell::new(MaybeUninit::uninit()),
ptr: Mutex::new(Cell::new(null_mut())),
}
}
fn alloc<T>(&'static self, cs: CriticalSection) -> &'static mut MaybeUninit<T> {
let layout = Layout::new::<T>();
let start = self.buf.get().cast::<u8>();
let end = unsafe { start.add(N) };
let mut ptr = self.ptr.borrow(cs).get();
if ptr.is_null() {
ptr = self.buf.get().cast::<u8>();
}
let bytes_left = (end as usize) - (ptr as usize);
let align_offset = (ptr as usize).next_multiple_of(layout.align()) - (ptr as usize);
if align_offset + layout.size() > bytes_left {
panic!("embassy-executor: task arena is full. You must increase the arena size, see the documentation for details: https://docs.embassy.dev/embassy-executor/");
}
let res = unsafe { ptr.add(align_offset) };
let ptr = unsafe { ptr.add(align_offset + layout.size()) };
self.ptr.borrow(cs).set(ptr);
unsafe { &mut *(res as *mut MaybeUninit<T>) }
}
}
static ARENA: Arena<{ crate::config::TASK_ARENA_SIZE }> = Arena::new();
pub struct TaskPoolRef {
// type-erased `&'static mut TaskPool<F, N>`
// Needed because statics can't have generics.
ptr: Mutex<Cell<*mut ()>>,
}
unsafe impl Sync for TaskPoolRef {}
unsafe impl Send for TaskPoolRef {}
impl TaskPoolRef {
pub const fn new() -> Self {
Self {
ptr: Mutex::new(Cell::new(null_mut())),
}
}
/// Get the pool for this ref, allocating it from the arena the first time.
///
/// safety: for a given TaskPoolRef instance, must always call with the exact
/// same generic params.
pub unsafe fn get<F: Future, const N: usize>(&'static self) -> &'static TaskPool<F, N> {
critical_section::with(|cs| {
let ptr = self.ptr.borrow(cs);
if ptr.get().is_null() {
let pool = ARENA.alloc::<TaskPool<F, N>>(cs);
pool.write(TaskPool::new());
ptr.set(pool as *mut _ as _);
}
unsafe { &*(ptr.get() as *const _) }
})
}
}
}

View File

@ -0,0 +1,71 @@
use core::task::{RawWaker, RawWakerVTable, Waker};
use super::{wake_task, TaskHeader, TaskRef};
static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake, drop);
unsafe fn clone(p: *const ()) -> RawWaker {
RawWaker::new(p, &VTABLE)
}
unsafe fn wake(p: *const ()) {
wake_task(TaskRef::from_ptr(p as *const TaskHeader))
}
unsafe fn drop(_: *const ()) {
// nop
}
pub(crate) unsafe fn from_task(p: TaskRef) -> Waker {
Waker::from_raw(RawWaker::new(p.as_ptr() as _, &VTABLE))
}
/// Get a task pointer from a waker.
///
/// This can be used as an optimization in wait queues to store task pointers
/// (1 word) instead of full Wakers (2 words). This saves a bit of RAM and helps
/// avoid dynamic dispatch.
///
/// You can use the returned task pointer to wake the task with [`wake_task`](super::wake_task).
///
/// # Panics
///
/// Panics if the waker is not created by the Embassy executor.
pub fn task_from_waker(waker: &Waker) -> TaskRef {
let (vtable, data) = {
#[cfg(not(feature = "nightly"))]
{
struct WakerHack {
data: *const (),
vtable: &'static RawWakerVTable,
}
// safety: OK because WakerHack has the same layout as Waker.
// This is not really guaranteed because the structs are `repr(Rust)`, it is
// indeed the case in the current implementation.
// TODO use waker_getters when stable. https://github.com/rust-lang/rust/issues/96992
let hack: &WakerHack = unsafe { core::mem::transmute(waker) };
(hack.vtable, hack.data)
}
#[cfg(feature = "nightly")]
{
#[cfg(not(at_least_2024_09_06))]
{
let raw_waker = waker.as_raw();
(raw_waker.vtable(), raw_waker.data())
}
#[cfg(at_least_2024_09_06)]
{
(waker.vtable(), waker.data())
}
}
};
if vtable != &VTABLE {
panic!("Found waker not created by the Embassy executor. `embassy_time::Timer` only works with the Embassy executor.")
}
// safety: our wakers are always created with `TaskRef::as_ptr`
unsafe { TaskRef::from_ptr(data as *const TaskHeader) }
}

View File

@ -0,0 +1,580 @@
/// Peripheral Access Crate
#[allow(unused_imports)]
#[rustfmt::skip]
pub mod pac {
// The nRF5340 has a secure and non-secure (NS) mode.
// To avoid cfg spam, we remove _ns or _s suffixes here.
#[cfg(feature="rt")]
pub use nrf_pac::NVIC_PRIO_BITS;
pub use nrf_pac::{common, shared};
#[cfg(feature="rt")]
#[doc(no_inline)]
pub use nrf_pac::interrupt;
#[doc(no_inline)]
pub use nrf_pac::{
Interrupt,
cache_s as cache,
cachedata_s as cachedata,
cacheinfo_s as cacheinfo,
clock_ns as clock,
comp_ns as comp,
cryptocell_s as cryptocell,
cti_s as cti,
ctrlap_ns as ctrlap,
dcnf_ns as dcnf,
dppic_ns as dppic,
egu_ns as egu,
ficr_s as ficr,
fpu_ns as fpu,
gpiote_s as gpiote,
i2s_ns as i2s,
ipc_ns as ipc,
kmu_ns as kmu,
lpcomp_ns as lpcomp,
mutex_ns as mutex,
nfct_ns as nfct,
nvmc_ns as nvmc,
oscillators_ns as oscillators,
gpio_ns as gpio,
pdm_ns as pdm,
power_ns as power,
pwm_ns as pwm,
qdec_ns as qdec,
qspi_ns as qspi,
regulators_ns as regulators,
reset_ns as reset,
rtc_ns as rtc,
saadc_ns as saadc,
spim_ns as spim,
spis_ns as spis,
spu_s as spu,
tad_s as tad,
timer_ns as timer,
twim_ns as twim,
twis_ns as twis,
uarte_ns as uarte,
uicr_s as uicr,
usbd_ns as usbd,
usbregulator_ns as usbregulator,
vmc_ns as vmc,
wdt_ns as wdt,
};
/// Non-Secure mode (NS) peripherals
pub mod ns {
#[cfg(feature = "nrf5340-app-ns")]
#[doc(no_inline)]
pub use nrf_pac::{
CLOCK_NS as CLOCK,
COMP_NS as COMP,
CTRLAP_NS as CTRLAP,
DCNF_NS as DCNF,
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,
I2S0_NS as I2S0,
IPC_NS as IPC,
KMU_NS as KMU,
LPCOMP_NS as LPCOMP,
MUTEX_NS as MUTEX,
NFCT_NS as NFCT,
NVMC_NS as NVMC,
OSCILLATORS_NS as OSCILLATORS,
P0_NS as P0,
P1_NS as P1,
PDM0_NS as PDM0,
POWER_NS as POWER,
PWM0_NS as PWM0,
PWM1_NS as PWM1,
PWM2_NS as PWM2,
PWM3_NS as PWM3,
QDEC0_NS as QDEC0,
QDEC1_NS as QDEC1,
QSPI_NS as QSPI,
REGULATORS_NS as REGULATORS,
RESET_NS as RESET,
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,
SPIM4_NS as SPIM4,
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,
USBD_NS as USBD,
USBREGULATOR_NS as USBREGULATOR,
VMC_NS as VMC,
WDT0_NS as WDT0,
WDT1_NS as WDT1,
};
}
/// Secure mode (S) peripherals
pub mod s {
#[cfg(feature = "nrf5340-app-s")]
#[doc(no_inline)]
pub use nrf_pac::{
CACHEDATA_S as CACHEDATA,
CACHEINFO_S as CACHEINFO,
CACHE_S as CACHE,
CLOCK_S as CLOCK,
COMP_S as COMP,
CRYPTOCELL_S as CRYPTOCELL,
CTI_S as CTI,
CTRLAP_S as CTRLAP,
DCNF_S as DCNF,
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_S as FPU,
GPIOTE0_S as GPIOTE0,
I2S0_S as I2S0,
IPC_S as IPC,
KMU_S as KMU,
LPCOMP_S as LPCOMP,
MUTEX_S as MUTEX,
NFCT_S as NFCT,
NVMC_S as NVMC,
OSCILLATORS_S as OSCILLATORS,
P0_S as P0,
P1_S as P1,
PDM0_S as PDM0,
POWER_S as POWER,
PWM0_S as PWM0,
PWM1_S as PWM1,
PWM2_S as PWM2,
PWM3_S as PWM3,
QDEC0_S as QDEC0,
QDEC1_S as QDEC1,
QSPI_S as QSPI,
REGULATORS_S as REGULATORS,
RESET_S as RESET,
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,
SPIM4_S as SPIM4,
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,
USBD_S as USBD,
USBREGULATOR_S as USBREGULATOR,
VMC_S as VMC,
WDT0_S as WDT0,
WDT1_S as WDT1,
};
}
#[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 << 16) - 1;
pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
pub const FLASH_SIZE: usize = 1024 * 1024;
embassy_hal_internal::peripherals! {
// USB
USBD,
// 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,
// QSPI
QSPI,
// PDM
PDM0,
// QDEC
QDEC0,
QDEC1,
// 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_CH16,
PPI_CH17,
PPI_CH18,
PPI_CH19,
PPI_CH20,
PPI_CH21,
PPI_CH22,
PPI_CH23,
PPI_CH24,
PPI_CH25,
PPI_CH26,
PPI_CH27,
PPI_CH28,
PPI_CH29,
PPI_CH30,
PPI_CH31,
PPI_GROUP0,
PPI_GROUP1,
PPI_GROUP2,
PPI_GROUP3,
PPI_GROUP4,
PPI_GROUP5,
// GPIO port 0
P0_00,
P0_01,
#[cfg(feature = "nfc-pins-as-gpio")]
P0_02,
#[cfg(feature = "nfc-pins-as-gpio")]
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,
// GPIO port 1
P1_00,
P1_01,
P1_02,
P1_03,
P1_04,
P1_05,
P1_06,
P1_07,
P1_08,
P1_09,
P1_10,
P1_11,
P1_12,
P1_13,
P1_14,
P1_15,
// EGU
EGU0,
EGU1,
EGU2,
EGU3,
EGU4,
EGU5,
}
impl_usb!(USBD, USBD, USBD);
impl_uarte!(SERIAL0, UARTE0, SERIAL0);
impl_uarte!(SERIAL1, UARTE1, SERIAL1);
impl_uarte!(SERIAL2, UARTE2, SERIAL2);
impl_uarte!(SERIAL3, UARTE3, SERIAL3);
impl_spim!(SERIAL0, SPIM0, SERIAL0);
impl_spim!(SERIAL1, SPIM1, SERIAL1);
impl_spim!(SERIAL2, SPIM2, SERIAL2);
impl_spim!(SERIAL3, SPIM3, SERIAL3);
impl_spis!(SERIAL0, SPIS0, SERIAL0);
impl_spis!(SERIAL1, SPIS1, SERIAL1);
impl_spis!(SERIAL2, SPIS2, SERIAL2);
impl_spis!(SERIAL3, SPIS3, SERIAL3);
impl_twim!(SERIAL0, TWIM0, SERIAL0);
impl_twim!(SERIAL1, TWIM1, SERIAL1);
impl_twim!(SERIAL2, TWIM2, SERIAL2);
impl_twim!(SERIAL3, TWIM3, SERIAL3);
impl_twis!(SERIAL0, TWIS0, SERIAL0);
impl_twis!(SERIAL1, TWIS1, SERIAL1);
impl_twis!(SERIAL2, TWIS2, SERIAL2);
impl_twis!(SERIAL3, TWIS3, SERIAL3);
impl_pwm!(PWM0, PWM0, PWM0);
impl_pwm!(PWM1, PWM1, PWM1);
impl_pwm!(PWM2, PWM2, PWM2);
impl_pwm!(PWM3, PWM3, PWM3);
impl_timer!(TIMER0, TIMER0, TIMER0);
impl_timer!(TIMER1, TIMER1, TIMER1);
impl_timer!(TIMER2, TIMER2, TIMER2);
impl_qspi!(QSPI, QSPI, QSPI);
impl_pdm!(PDM0, PDM0, PDM0);
impl_qdec!(QDEC0, QDEC0, QDEC0);
impl_qdec!(QDEC1, QDEC1, QDEC1);
impl_pin!(P0_00, 0, 0);
impl_pin!(P0_01, 0, 1);
#[cfg(feature = "nfc-pins-as-gpio")]
impl_pin!(P0_02, 0, 2);
#[cfg(feature = "nfc-pins-as-gpio")]
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_pin!(P1_00, 1, 0);
impl_pin!(P1_01, 1, 1);
impl_pin!(P1_02, 1, 2);
impl_pin!(P1_03, 1, 3);
impl_pin!(P1_04, 1, 4);
impl_pin!(P1_05, 1, 5);
impl_pin!(P1_06, 1, 6);
impl_pin!(P1_07, 1, 7);
impl_pin!(P1_08, 1, 8);
impl_pin!(P1_09, 1, 9);
impl_pin!(P1_10, 1, 10);
impl_pin!(P1_11, 1, 11);
impl_pin!(P1_12, 1, 12);
impl_pin!(P1_13, 1, 13);
impl_pin!(P1_14, 1, 14);
impl_pin!(P1_15, 1, 15);
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_ppi_channel!(PPI_CH16, 16 => configurable);
impl_ppi_channel!(PPI_CH17, 17 => configurable);
impl_ppi_channel!(PPI_CH18, 18 => configurable);
impl_ppi_channel!(PPI_CH19, 19 => configurable);
impl_ppi_channel!(PPI_CH20, 20 => configurable);
impl_ppi_channel!(PPI_CH21, 21 => configurable);
impl_ppi_channel!(PPI_CH22, 22 => configurable);
impl_ppi_channel!(PPI_CH23, 23 => configurable);
impl_ppi_channel!(PPI_CH24, 24 => configurable);
impl_ppi_channel!(PPI_CH25, 25 => configurable);
impl_ppi_channel!(PPI_CH26, 26 => configurable);
impl_ppi_channel!(PPI_CH27, 27 => configurable);
impl_ppi_channel!(PPI_CH28, 28 => configurable);
impl_ppi_channel!(PPI_CH29, 29 => configurable);
impl_ppi_channel!(PPI_CH30, 30 => configurable);
impl_ppi_channel!(PPI_CH31, 31 => 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!(
FPU,
CACHE,
SPU,
CLOCK_POWER,
SERIAL0,
SERIAL1,
SPIM4,
SERIAL2,
SERIAL3,
GPIOTE0,
SAADC,
TIMER0,
TIMER1,
TIMER2,
RTC0,
RTC1,
WDT0,
WDT1,
COMP_LPCOMP,
EGU0,
EGU1,
EGU2,
EGU3,
EGU4,
EGU5,
PWM0,
PWM1,
PWM2,
PWM3,
PDM0,
I2S0,
IPC,
QSPI,
NFCT,
GPIOTE1,
QDEC0,
QDEC1,
USBD,
USBREGULATOR,
KMU,
CRYPTOCELL,
);

View File

@ -0,0 +1,673 @@
#![no_std]
#![allow(async_fn_in_trait)]
#![cfg_attr(
docsrs,
doc = "<div style='padding:30px;background:#810;color:#fff;text-align:center;'><p>You might want to <a href='https://docs.embassy.dev/embassy-nrf'>browse the `embassy-nrf` documentation on the Embassy website</a> instead.</p><p>The documentation here on `docs.rs` is built for a single chip only (nRF52840 in particular), while on the Embassy website you can pick your exact chip from the top menu. Available peripherals and their APIs change depending on the chip.</p></div>\n\n"
)]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
//! ## Feature flags
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
#[cfg(not(any(
feature = "_nrf51",
feature = "nrf52805",
feature = "nrf52810",
feature = "nrf52811",
feature = "nrf52820",
feature = "nrf52832",
feature = "nrf52833",
feature = "nrf52840",
feature = "nrf5340-app-s",
feature = "nrf5340-app-ns",
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:
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.");
#[cfg(all(feature = "nfc-pins-as-gpio", not(any(feature = "_nrf52", feature = "_nrf5340-app"))))]
compile_error!("feature `nfc-pins-as-gpio` is only valid for nRF52, or nRF53's application core.");
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;
pub(crate) mod util;
#[cfg(feature = "_time-driver")]
mod time_driver;
#[cfg(not(feature = "_nrf51"))]
pub mod buffered_uarte;
pub mod gpio;
#[cfg(feature = "gpiote")]
pub mod gpiote;
// TODO: tested on other chips
#[cfg(not(any(feature = "_nrf91", feature = "_nrf5340-app")))]
pub mod radio;
#[cfg(not(feature = "_nrf51"))]
pub mod egu;
#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
pub mod i2s;
pub mod nvmc;
#[cfg(any(
feature = "nrf52810",
feature = "nrf52811",
feature = "nrf52832",
feature = "nrf52833",
feature = "nrf52840",
feature = "_nrf5340-app",
feature = "_nrf91",
))]
pub mod pdm;
pub mod ppi;
#[cfg(not(any(
feature = "_nrf51",
feature = "nrf52805",
feature = "nrf52820",
feature = "_nrf5340-net"
)))]
pub mod pwm;
#[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 = "_nrf91")))]
pub mod rng;
#[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))]
pub mod saadc;
#[cfg(not(feature = "_nrf51"))]
pub mod spim;
#[cfg(not(feature = "_nrf51"))]
pub mod spis;
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))]
pub mod temp;
pub mod timer;
#[cfg(not(feature = "_nrf51"))]
pub mod twim;
#[cfg(not(feature = "_nrf51"))]
pub mod twis;
#[cfg(not(feature = "_nrf51"))]
pub mod uarte;
#[cfg(any(
feature = "_nrf5340-app",
feature = "nrf52820",
feature = "nrf52833",
feature = "nrf52840"
))]
pub mod usb;
#[cfg(not(feature = "_nrf5340"))]
pub mod wdt;
// This mod MUST go last, so that it sees all the `impl_foo!` macros
#[cfg_attr(feature = "_nrf51", path = "chips/nrf51.rs")]
#[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")]
#[cfg_attr(feature = "nrf52810", path = "chips/nrf52810.rs")]
#[cfg_attr(feature = "nrf52811", path = "chips/nrf52811.rs")]
#[cfg_attr(feature = "nrf52820", path = "chips/nrf52820.rs")]
#[cfg_attr(feature = "nrf52832", path = "chips/nrf52832.rs")]
#[cfg_attr(feature = "nrf52833", path = "chips/nrf52833.rs")]
#[cfg_attr(feature = "nrf52840", path = "chips/nrf52840.rs")]
#[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.
///
/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
/// prove at compile-time that the right interrupts have been bound.
///
/// Example of how to bind one interrupt:
///
/// ```rust,ignore
/// use embassy_nrf::{bind_interrupts, spim, peripherals};
///
/// bind_interrupts!(struct Irqs {
/// SPIM3 => spim::InterruptHandler<peripherals::SPI3>;
/// });
/// ```
///
/// Example of how to bind multiple interrupts in a single macro invocation:
///
/// ```rust,ignore
/// use embassy_nrf::{bind_interrupts, spim, twim, peripherals};
///
/// bind_interrupts!(struct Irqs {
/// SPIM3 => spim::InterruptHandler<peripherals::SPI3>;
/// SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twim::InterruptHandler<peripherals::TWISPI0>;
/// });
/// ```
// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
#[macro_export]
macro_rules! bind_interrupts {
($vis:vis struct $name:ident {
$(
$(#[cfg($cond_irq:meta)])?
$irq:ident => $(
$(#[cfg($cond_handler:meta)])?
$handler:ty
),*;
)*
}) => {
#[derive(Copy, Clone)]
$vis struct $name;
$(
#[allow(non_snake_case)]
#[no_mangle]
$(#[cfg($cond_irq)])?
unsafe extern "C" fn $irq() {
$(
$(#[cfg($cond_handler)])?
<$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
$(#[cfg($cond_handler)])?
unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
)*
}
)*
};
}
// Reexports
#[cfg(feature = "unstable-pac")]
pub use chip::pac;
#[cfg(not(feature = "unstable-pac"))]
pub(crate) use chip::pac;
pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE};
pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
pub use crate::chip::interrupt;
#[cfg(feature = "rt")]
pub use crate::pac::NVIC_PRIO_BITS;
pub mod config {
//! Configuration options used when initializing the HAL.
/// High frequency clock source.
pub enum HfclkSource {
/// Internal source
Internal,
/// External source from xtal.
ExternalXtal,
}
/// Low frequency clock source
pub enum LfclkSource {
/// Internal RC oscillator
InternalRC,
/// Synthesized from the high frequency clock source.
#[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 = "_nrf91")))]
ExternalLowSwing,
/// External source from xtal with full swing applied.
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))]
ExternalFullSwing,
}
/// SWD access port protection setting.
#[non_exhaustive]
pub enum Debug {
/// Debugging is allowed (APPROTECT is disabled). Default.
Allowed,
/// Debugging is not allowed (APPROTECT is enabled).
Disallowed,
/// APPROTECT is not configured (neither to enable it or disable it).
/// This can be useful if you're already doing it by other means and
/// you don't want embassy-nrf to touch UICR.
NotConfigured,
}
/// Settings for enabling the built in DCDC converters.
#[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")]
pub reg0: bool,
/// Configure the voltage of the first stage DCDC. It is stored in non-volatile memory (UICR.REGOUT0 register); pass None to not touch it.
#[cfg(feature = "nrf52840")]
pub reg0_voltage: Option<Reg0Voltage>,
/// Config for the second stage DCDC (VDD -> DEC4), if disabled LDO will be used.
pub reg1: bool,
}
/// Output voltage setting for REG0 regulator stage.
#[cfg(feature = "nrf52840")]
pub enum Reg0Voltage {
/// 1.8 V
_1V8 = 0,
/// 2.1 V
_2V1 = 1,
/// 2.4 V
_2V4 = 2,
/// 2.7 V
_2V7 = 3,
/// 3.0 V
_3V0 = 4,
/// 3.3 V
_3v3 = 5,
//ERASED = 7, means 1.8V
}
/// Settings for enabling the built in DCDC converters.
#[cfg(feature = "_nrf5340-app")]
pub struct DcdcConfig {
/// Config for the high voltage stage, if disabled LDO will be used.
pub regh: bool,
/// Config for the main rail, if disabled LDO will be used.
pub regmain: bool,
/// Config for the radio rail, if disabled LDO will be used.
pub regradio: bool,
}
/// Settings for enabling the built in DCDC converter.
#[cfg(feature = "_nrf91")]
pub struct DcdcConfig {
/// Config for the main rail, if disabled LDO will be used.
pub regmain: bool,
}
/// Configuration for peripherals. Default configuration should work on any nRF chip.
#[non_exhaustive]
pub struct Config {
/// High frequency clock source.
pub hfclk_source: HfclkSource,
/// Low frequency clock source.
pub lfclk_source: LfclkSource,
#[cfg(not(feature = "_nrf5340-net"))]
/// DCDC configuration.
pub dcdc: DcdcConfig,
/// GPIOTE interrupt priority. Should be lower priority than softdevice if used.
#[cfg(feature = "gpiote")]
pub gpiote_interrupt_priority: crate::interrupt::Priority,
/// Time driver interrupt priority. Should be lower priority than softdevice if used.
#[cfg(feature = "_time-driver")]
pub time_interrupt_priority: crate::interrupt::Priority,
/// Enable or disable the debug port.
pub debug: Debug,
}
impl Default for Config {
fn default() -> Self {
Self {
// There are hobby nrf52 boards out there without external XTALs...
// Default everything to internal so it Just Works. User can enable external
// xtals if they know they have them.
hfclk_source: HfclkSource::Internal,
lfclk_source: LfclkSource::InternalRC,
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))]
dcdc: DcdcConfig {
#[cfg(feature = "nrf52840")]
reg0: false,
#[cfg(feature = "nrf52840")]
reg0_voltage: None,
reg1: false,
},
#[cfg(feature = "_nrf5340-app")]
dcdc: DcdcConfig {
regh: false,
regmain: false,
regradio: false,
},
#[cfg(feature = "_nrf91")]
dcdc: DcdcConfig { regmain: false },
#[cfg(feature = "gpiote")]
gpiote_interrupt_priority: crate::interrupt::Priority::P0,
#[cfg(feature = "_time-driver")]
time_interrupt_priority: crate::interrupt::Priority::P0,
// In NS mode, default to NotConfigured, assuming the S firmware will do it.
#[cfg(feature = "_ns")]
debug: Debug::NotConfigured,
#[cfg(not(feature = "_ns"))]
debug: Debug::Allowed,
}
}
}
}
#[cfg(feature = "_nrf91")]
#[allow(unused)]
mod consts {
pub const UICR_APPROTECT: *mut u32 = 0x00FF8000 as *mut u32;
pub const UICR_SECUREAPPROTECT: *mut u32 = 0x00FF802C as *mut u32;
pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
}
#[cfg(feature = "_nrf5340-app")]
#[allow(unused)]
mod consts {
pub const UICR_APPROTECT: *mut u32 = 0x00FF8000 as *mut u32;
pub const UICR_SECUREAPPROTECT: *mut u32 = 0x00FF801C as *mut u32;
pub const UICR_NFCPINS: *mut u32 = 0x00FF8028 as *mut u32;
pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
pub const APPROTECT_DISABLED: u32 = 0x50FA50FA;
}
#[cfg(feature = "_nrf5340-net")]
#[allow(unused)]
mod consts {
pub const UICR_APPROTECT: *mut u32 = 0x01FF8000 as *mut u32;
pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
pub const APPROTECT_DISABLED: u32 = 0x50FA50FA;
}
#[cfg(feature = "_nrf52")]
#[allow(unused)]
mod consts {
pub const UICR_PSELRESET1: *mut u32 = 0x10001200 as *mut u32;
pub const UICR_PSELRESET2: *mut u32 = 0x10001204 as *mut u32;
pub const UICR_NFCPINS: *mut u32 = 0x1000120C as *mut u32;
pub const UICR_APPROTECT: *mut u32 = 0x10001208 as *mut u32;
pub const UICR_REGOUT0: *mut u32 = 0x10001304 as *mut u32;
pub const APPROTECT_ENABLED: u32 = 0x0000_0000;
pub const APPROTECT_DISABLED: u32 = 0x0000_005a;
}
#[cfg(not(feature = "_nrf51"))]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
enum WriteResult {
/// Word was written successfully, needs reset.
Written,
/// Word was already set to the value we wanted to write, nothing was done.
Noop,
/// Word is already set to something else, we couldn't write the desired value.
Failed,
}
#[cfg(not(feature = "_nrf51"))]
unsafe fn uicr_write(address: *mut u32, value: u32) -> WriteResult {
uicr_write_masked(address, value, 0xFFFF_FFFF)
}
#[cfg(not(feature = "_nrf51"))]
unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteResult {
let curr_val = address.read_volatile();
if curr_val & mask == value & mask {
return WriteResult::Noop;
}
// We can only change `1` bits to `0` bits.
if curr_val & value & mask != value & mask {
return WriteResult::Failed;
}
let nvmc = pac::NVMC;
nvmc.config().write(|w| w.set_wen(pac::nvmc::vals::Wen::WEN));
while !nvmc.ready().read().ready() {}
address.write_volatile(value | !mask);
while !nvmc.ready().read().ready() {}
nvmc.config().write(|_| {});
while !nvmc.ready().read().ready() {}
WriteResult::Written
}
/// Initialize the `embassy-nrf` HAL with the provided configuration.
///
/// This returns the peripheral singletons that can be used for creating drivers.
///
/// This should only be called once at startup, otherwise it panics.
pub fn init(config: config::Config) -> Peripherals {
// Do this first, so that it panics if user is calling `init` a second time
// before doing anything important.
let peripherals = Peripherals::take();
#[allow(unused_mut)]
let mut needs_reset = false;
// Setup debug protection.
#[cfg(not(feature = "_nrf51"))]
match config.debug {
config::Debug::Allowed => {
#[cfg(feature = "_nrf52")]
unsafe {
let variant = (0x1000_0104 as *mut u32).read_volatile();
// Get the letter for the build code (b'A' .. b'F')
let build_code = (variant >> 8) as u8;
if build_code >= chip::APPROTECT_MIN_BUILD_CODE {
// Chips with a certain chip type-specific build code or higher have an
// improved APPROTECT ("hardware and software controlled access port protection")
// which needs explicit action by the firmware to keep it unlocked
// See https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/working-with-the-nrf52-series-improved-approtect
// UICR.APPROTECT = SwDisabled
let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED);
needs_reset |= res == WriteResult::Written;
// APPROTECT.DISABLE = SwDisabled
(0x4000_0558 as *mut u32).write_volatile(consts::APPROTECT_DISABLED);
} else {
// nothing to do on older chips, debug is allowed by default.
}
}
#[cfg(feature = "_nrf5340")]
unsafe {
let p = pac::CTRLAP;
let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED);
needs_reset |= res == WriteResult::Written;
p.approtect().disable().write_value(consts::APPROTECT_DISABLED);
#[cfg(feature = "_nrf5340-app")]
{
let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_DISABLED);
needs_reset |= res == WriteResult::Written;
p.secureapprotect().disable().write_value(consts::APPROTECT_DISABLED);
}
}
// nothing to do on the nrf9160, debug is allowed by default.
}
config::Debug::Disallowed => unsafe {
// UICR.APPROTECT = Enabled
let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_ENABLED);
needs_reset |= res == WriteResult::Written;
#[cfg(any(feature = "_nrf5340-app", feature = "_nrf91"))]
{
let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_ENABLED);
needs_reset |= res == WriteResult::Written;
}
},
config::Debug::NotConfigured => {}
}
#[cfg(feature = "_nrf52")]
unsafe {
let value = if cfg!(feature = "reset-pin-as-gpio") {
!0
} else {
chip::RESET_PIN
};
let res1 = uicr_write(consts::UICR_PSELRESET1, value);
let res2 = uicr_write(consts::UICR_PSELRESET2, value);
needs_reset |= res1 == WriteResult::Written || res2 == WriteResult::Written;
if res1 == WriteResult::Failed || res2 == WriteResult::Failed {
#[cfg(not(feature = "reset-pin-as-gpio"))]
warn!(
"You have requested enabling chip reset functionality on the reset pin, by not enabling the Cargo feature `reset-pin-as-gpio`.\n\
However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`."
);
#[cfg(feature = "reset-pin-as-gpio")]
warn!(
"You have requested using the reset pin as GPIO, by enabling the Cargo feature `reset-pin-as-gpio`.\n\
However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`."
);
}
}
#[cfg(any(feature = "_nrf52", feature = "_nrf5340-app"))]
unsafe {
let value = if cfg!(feature = "nfc-pins-as-gpio") { 0 } else { 1 };
let res = uicr_write_masked(consts::UICR_NFCPINS, value, 1);
needs_reset |= res == WriteResult::Written;
if res == WriteResult::Failed {
// with nfc-pins-as-gpio, this can never fail because we're writing all zero bits.
#[cfg(not(feature = "nfc-pins-as-gpio"))]
warn!(
"You have requested to use P0.09 and P0.10 pins for NFC, by not enabling the Cargo feature `nfc-pins-as-gpio`.\n\
However, UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`."
);
}
}
#[cfg(feature = "nrf52840")]
unsafe {
if let Some(value) = config.dcdc.reg0_voltage {
let value = value as u32;
let res = uicr_write_masked(consts::UICR_REGOUT0, value, 0b00000000_00000000_00000000_00000111);
needs_reset |= res == WriteResult::Written;
if res == WriteResult::Failed {
warn!(
"Failed to set regulator voltage, as UICR is already programmed to some other setting, and can't be changed without erasing it.\n\
To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`."
);
}
}
}
if needs_reset {
cortex_m::peripheral::SCB::sys_reset();
}
let r = pac::CLOCK;
// Start HFCLK.
match config.hfclk_source {
config::HfclkSource::Internal => {}
config::HfclkSource::ExternalXtal => {
// Datasheet says this is likely to take 0.36ms
r.events_hfclkstarted().write_value(0);
r.tasks_hfclkstart().write_value(1);
while r.events_hfclkstarted().read() == 0 {}
}
}
// Configure LFCLK.
#[cfg(not(any(feature = "_nrf51", feature = "_nrf5340", feature = "_nrf91")))]
match config.lfclk_source {
config::LfclkSource::InternalRC => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::RC)),
config::LfclkSource::Synthesized => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::SYNTH)),
config::LfclkSource::ExternalXtal => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::XTAL)),
config::LfclkSource::ExternalLowSwing => r.lfclksrc().write(|w| {
w.set_src(pac::clock::vals::Lfclksrc::XTAL);
w.set_external(true);
w.set_bypass(false);
}),
config::LfclkSource::ExternalFullSwing => r.lfclksrc().write(|w| {
w.set_src(pac::clock::vals::Lfclksrc::XTAL);
w.set_external(true);
w.set_bypass(true);
}),
}
#[cfg(feature = "_nrf91")]
match config.lfclk_source {
config::LfclkSource::InternalRC => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFRC)),
config::LfclkSource::ExternalXtal => r.lfclksrc().write(|w| w.set_src(pac::clock::vals::Lfclksrc::LFXO)),
}
// Start LFCLK.
// Datasheet says this could take 100us from synth source
// 600us from rc source, 0.25s from an external source.
r.events_lfclkstarted().write_value(0);
r.tasks_lfclkstart().write_value(1);
while r.events_lfclkstarted().read() == 0 {}
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))]
{
// Setup DCDCs.
#[cfg(feature = "nrf52840")]
if config.dcdc.reg0 {
pac::POWER.dcdcen0().write(|w| w.set_dcdcen(true));
}
if config.dcdc.reg1 {
pac::POWER.dcdcen().write(|w| w.set_dcdcen(true));
}
}
#[cfg(feature = "_nrf91")]
{
// Setup DCDC.
if config.dcdc.regmain {
pac::REGULATORS.dcdcen().write(|w| w.set_dcdcen(true));
}
}
#[cfg(feature = "_nrf5340-app")]
{
// Setup DCDC.
let reg = pac::REGULATORS;
if config.dcdc.regh {
reg.vregh().dcdcen().write(|w| w.set_dcdcen(true));
}
if config.dcdc.regmain {
reg.vregmain().dcdcen().write(|w| w.set_dcdcen(true));
}
if config.dcdc.regradio {
reg.vregradio().dcdcen().write(|w| w.set_dcdcen(true));
}
}
// Init GPIOTE
#[cfg(feature = "gpiote")]
gpiote::init(config.gpiote_interrupt_priority);
// init RTC time driver
#[cfg(feature = "_time-driver")]
time_driver::init(config.time_interrupt_priority);
// Disable UARTE (enabled by default for some reason)
#[cfg(feature = "_nrf91")]
{
use pac::uarte::vals::Enable;
pac::UARTE0.enable().write(|w| w.set_enable(Enable::DISABLED));
pac::UARTE1.enable().write(|w| w.set_enable(Enable::DISABLED));
}
peripherals
}

View File

@ -0,0 +1,151 @@
[package]
name = "embassy-rp"
version = "0.2.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Embassy Hardware Abstraction Layer (HAL) for the Raspberry Pi RP2040 microcontroller"
keywords = ["embedded", "async", "raspberry-pi", "rp2040", "embedded-hal"]
categories = ["embedded", "hardware-support", "no-std", "asynchronous"]
repository = "https://github.com/embassy-rs/embassy"
documentation = "https://docs.embassy.dev/embassy-rp"
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-rp-v$VERSION/embassy-rp/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-rp/src/"
features = ["defmt", "unstable-pac", "time-driver"]
flavors = [
{ name = "rp2040", target = "thumbv6m-none-eabi", features = ["rp2040"] },
{ name = "rp235xa", target = "thumbv8m.main-none-eabihf", features = ["rp235xa"] },
{ name = "rp235xb", target = "thumbv8m.main-none-eabihf", features = ["rp235xb"] },
]
[package.metadata.docs.rs]
features = ["defmt", "unstable-pac", "time-driver"]
[features]
default = [ "rt" ]
## Enable the rt feature of [`rp-pac`](https://docs.rs/rp-pac). This brings in the [`cortex-m-rt`](https://docs.rs/cortex-m-rt) crate, which adds startup code and minimal runtime initialization.
rt = [ "rp-pac/rt" ]
## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers.
defmt = ["dep:defmt", "embassy-usb-driver/defmt", "embassy-hal-internal/defmt"]
## Configure the [`critical-section`](https://docs.rs/critical-section) crate to use an implementation that is safe for multicore use on rp2040.
critical-section-impl = ["critical-section/restore-state-u8"]
## Reexport the PAC for the currently enabled chip at `embassy_rp::pac`.
## This is unstable because semver-minor (non-breaking) releases of `embassy-rp` may major-bump (breaking) the PAC version.
## If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC.
## There are no plans to make this stable.
unstable-pac = []
## Enable the timer for use with `embassy-time` with a 1MHz tick rate.
time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-1_000_000"]
## Enable ROM function cache. This will store the address of a ROM function when first used, improving performance of subsequent calls.
rom-func-cache = []
## Enable implementations of some compiler intrinsics using functions in the rp2040 Mask ROM.
## These should be as fast or faster than the implementations in compiler-builtins. They also save code space and reduce memory contention.
## Compiler intrinsics are used automatically, you do not need to change your code to get performance improvements from this feature.
intrinsics = []
## Enable intrinsics based on extra ROM functions added in the v2 version of the rp2040 Mask ROM.
## This version added a lot more floating point operations - many f64 functions and a few f32 functions were added in ROM v2.
rom-v2-intrinsics = []
## Allow using QSPI pins as GPIO pins. This is mostly not what you want (because your flash is attached via QSPI pins)
## and adds code and memory overhead when this feature is enabled.
qspi-as-gpio = []
## Indicate code is running from RAM.
## Set this if all code is in RAM, and the cores never access memory-mapped flash memory through XIP.
## This allows the flash driver to not force pausing execution on both cores when doing flash operations.
run-from-ram = []
#! ### boot2 flash chip support
#! RP2040's internal bootloader is only able to run code from the first 256 bytes of flash.
#! A 2nd stage bootloader (boot2) is required to run larger programs from external flash.
#! Select from existing boot2 implementations via the following features. If none are selected,
#! boot2-w25q080 will be used (w25q080 is the flash chip used on the pico).
#! Each implementation uses flash commands and timings specific to a QSPI flash chip family for better performance.
## Use boot2 with support for Renesas/Dialog AT25SF128a SPI flash.
boot2-at25sf128a = []
## Use boot2 with support for Gigadevice GD25Q64C SPI flash.
boot2-gd25q64cs = []
## Use boot2 that only uses generic flash commands - these are supported by all SPI flash, but are slower.
boot2-generic-03h = []
## Use boot2 with support for ISSI IS25LP080 SPI flash.
boot2-is25lp080 = []
## Use boot2 that copies the entire program to RAM before booting. This uses generic flash commands to perform the copy.
boot2-ram-memcpy = []
## Use boot2 with support for Winbond W25Q080 SPI flash.
boot2-w25q080 = []
## Use boot2 with support for Winbond W25X10CL SPI flash.
boot2-w25x10cl = []
## Have embassy not provide the boot2 so you can use your own.
## Place your own in the ".boot2" section like:
## ```
## #[link_section = ".boot2"]
## #[used]
## static BOOT2: [u8; 256] = [0; 256]; // Provide your own with e.g. include_bytes!
## ```
boot2-none = []
## Configure the hal for use with the rp2040
rp2040 = ["rp-pac/rp2040"]
_rp235x = ["rp-pac/rp235x"]
## Configure the hal for use with the rp235xA
rp235xa = ["_rp235x"]
## Configure the hal for use with the rp235xB
rp235xb = ["_rp235x"]
# hack around cortex-m peripherals being wrong when running tests.
_test = []
## Add a binary-info header block containing picotool-compatible metadata.
##
## Takes up a little flash space, but picotool can then report the name of your
## program and other details.
binary-info = ["rt", "dep:rp-binary-info", "rp-binary-info?/binary-info"]
[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.2", path = "../embassy-time" }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
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 }
log = { version = "0.4.14", optional = true }
nb = "1.1.0"
cfg-if = "1.0.0"
cortex-m-rt = ">=0.6.15,<0.8"
cortex-m = "0.7.6"
critical-section = "1.2.0"
chrono = { version = "0.4", default-features = false, optional = true }
embedded-io = { version = "0.6.1" }
embedded-io-async = { version = "0.6.1" }
embedded-storage = { version = "0.3" }
embedded-storage-async = { version = "0.4.1" }
rand_core = "0.6.4"
fixed = "1.28.0"
rp-pac = { git = "https://github.com/embassy-rs/rp-pac.git", rev = "a7f42d25517f7124ad3b4ed492dec8b0f50a0e6c", feature = ["rt"] }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-hal-nb = { version = "1.0" }
pio-proc = {version= "0.2" }
pio = {version= "0.2.1" }
rp2040-boot2 = "0.3"
document-features = "0.2.10"
sha2-const-stable = "0.1"
rp-binary-info = { version = "0.1.0", optional = true }
smart-leds = "0.4.0"
[dev-dependencies]
embassy-executor = { version = "0.6.2", path = "../embassy-executor", features = ["arch-std", "executor-thread"] }
static_cell = { version = "2" }

View File

@ -0,0 +1,691 @@
#![no_std]
#![allow(async_fn_in_trait)]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
//! ## Feature flags
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;
#[cfg(feature = "binary-info")]
pub use rp_binary_info as binary_info;
#[cfg(feature = "critical-section-impl")]
mod critical_section_impl;
#[cfg(feature = "rp2040")]
mod intrinsics;
pub mod adc;
#[cfg(feature = "_rp235x")]
pub mod block;
#[cfg(feature = "rp2040")]
pub mod bootsel;
pub mod clocks;
pub mod dma;
pub mod flash;
#[cfg(feature = "rp2040")]
mod float;
pub mod gpio;
pub mod i2c;
pub mod i2c_slave;
pub mod multicore;
#[cfg(feature = "_rp235x")]
pub mod otp;
pub mod pio_programs;
pub mod pwm;
mod reset;
pub mod rom_data;
#[cfg(feature = "rp2040")]
pub mod rtc;
pub mod spi;
#[cfg(feature = "time-driver")]
pub mod time_driver;
#[cfg(feature = "_rp235x")]
pub mod trng;
pub mod uart;
pub mod usb;
pub mod watchdog;
// PIO
pub mod pio;
pub(crate) mod relocate;
// Reexports
pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
#[cfg(feature = "unstable-pac")]
pub use rp_pac as pac;
#[cfg(not(feature = "unstable-pac"))]
pub(crate) use rp_pac as pac;
#[cfg(feature = "rt")]
pub use crate::pac::NVIC_PRIO_BITS;
#[cfg(feature = "rp2040")]
embassy_hal_internal::interrupt_mod!(
TIMER_IRQ_0,
TIMER_IRQ_1,
TIMER_IRQ_2,
TIMER_IRQ_3,
PWM_IRQ_WRAP,
USBCTRL_IRQ,
XIP_IRQ,
PIO0_IRQ_0,
PIO0_IRQ_1,
PIO1_IRQ_0,
PIO1_IRQ_1,
DMA_IRQ_0,
DMA_IRQ_1,
IO_IRQ_BANK0,
IO_IRQ_QSPI,
SIO_IRQ_PROC0,
SIO_IRQ_PROC1,
CLOCKS_IRQ,
SPI0_IRQ,
SPI1_IRQ,
UART0_IRQ,
UART1_IRQ,
ADC_IRQ_FIFO,
I2C0_IRQ,
I2C1_IRQ,
RTC_IRQ,
SWI_IRQ_0,
SWI_IRQ_1,
SWI_IRQ_2,
SWI_IRQ_3,
SWI_IRQ_4,
SWI_IRQ_5,
);
#[cfg(feature = "_rp235x")]
embassy_hal_internal::interrupt_mod!(
TIMER0_IRQ_0,
TIMER0_IRQ_1,
TIMER0_IRQ_2,
TIMER0_IRQ_3,
TIMER1_IRQ_0,
TIMER1_IRQ_1,
TIMER1_IRQ_2,
TIMER1_IRQ_3,
PWM_IRQ_WRAP_0,
PWM_IRQ_WRAP_1,
DMA_IRQ_0,
DMA_IRQ_1,
USBCTRL_IRQ,
PIO0_IRQ_0,
PIO0_IRQ_1,
PIO1_IRQ_0,
PIO1_IRQ_1,
PIO2_IRQ_0,
PIO2_IRQ_1,
IO_IRQ_BANK0,
IO_IRQ_BANK0_NS,
IO_IRQ_QSPI,
IO_IRQ_QSPI_NS,
SIO_IRQ_FIFO,
SIO_IRQ_BELL,
SIO_IRQ_FIFO_NS,
SIO_IRQ_BELL_NS,
CLOCKS_IRQ,
SPI0_IRQ,
SPI1_IRQ,
UART0_IRQ,
UART1_IRQ,
ADC_IRQ_FIFO,
I2C0_IRQ,
I2C1_IRQ,
TRNG_IRQ,
PLL_SYS_IRQ,
PLL_USB_IRQ,
SWI_IRQ_0,
SWI_IRQ_1,
SWI_IRQ_2,
SWI_IRQ_3,
SWI_IRQ_4,
SWI_IRQ_5,
);
/// Macro to bind interrupts to handlers.
///
/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
/// prove at compile-time that the right interrupts have been bound.
///
/// Example of how to bind one interrupt:
///
/// ```rust,ignore
/// use embassy_rp::{bind_interrupts, usb, peripherals};
///
/// bind_interrupts!(struct Irqs {
/// USBCTRL_IRQ => usb::InterruptHandler<peripherals::USB>;
/// });
/// ```
///
// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
#[macro_export]
macro_rules! bind_interrupts {
($vis:vis struct $name:ident {
$(
$(#[cfg($cond_irq:meta)])?
$irq:ident => $(
$(#[cfg($cond_handler:meta)])?
$handler:ty
),*;
)*
}) => {
#[derive(Copy, Clone)]
$vis struct $name;
$(
#[allow(non_snake_case)]
#[no_mangle]
$(#[cfg($cond_irq)])?
unsafe extern "C" fn $irq() {
$(
$(#[cfg($cond_handler)])?
<$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
$(#[cfg($cond_handler)])?
unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
)*
}
)*
};
}
#[cfg(feature = "rp2040")]
embassy_hal_internal::peripherals! {
PIN_0,
PIN_1,
PIN_2,
PIN_3,
PIN_4,
PIN_5,
PIN_6,
PIN_7,
PIN_8,
PIN_9,
PIN_10,
PIN_11,
PIN_12,
PIN_13,
PIN_14,
PIN_15,
PIN_16,
PIN_17,
PIN_18,
PIN_19,
PIN_20,
PIN_21,
PIN_22,
PIN_23,
PIN_24,
PIN_25,
PIN_26,
PIN_27,
PIN_28,
PIN_29,
PIN_QSPI_SCLK,
PIN_QSPI_SS,
PIN_QSPI_SD0,
PIN_QSPI_SD1,
PIN_QSPI_SD2,
PIN_QSPI_SD3,
UART0,
UART1,
SPI0,
SPI1,
I2C0,
I2C1,
DMA_CH0,
DMA_CH1,
DMA_CH2,
DMA_CH3,
DMA_CH4,
DMA_CH5,
DMA_CH6,
DMA_CH7,
DMA_CH8,
DMA_CH9,
DMA_CH10,
DMA_CH11,
PWM_SLICE0,
PWM_SLICE1,
PWM_SLICE2,
PWM_SLICE3,
PWM_SLICE4,
PWM_SLICE5,
PWM_SLICE6,
PWM_SLICE7,
USB,
RTC,
FLASH,
ADC,
ADC_TEMP_SENSOR,
CORE1,
PIO0,
PIO1,
WATCHDOG,
BOOTSEL,
}
#[cfg(feature = "_rp235x")]
embassy_hal_internal::peripherals! {
PIN_0,
PIN_1,
PIN_2,
PIN_3,
PIN_4,
PIN_5,
PIN_6,
PIN_7,
PIN_8,
PIN_9,
PIN_10,
PIN_11,
PIN_12,
PIN_13,
PIN_14,
PIN_15,
PIN_16,
PIN_17,
PIN_18,
PIN_19,
PIN_20,
PIN_21,
PIN_22,
PIN_23,
PIN_24,
PIN_25,
PIN_26,
PIN_27,
PIN_28,
PIN_29,
#[cfg(feature = "rp235xb")]
PIN_30,
#[cfg(feature = "rp235xb")]
PIN_31,
#[cfg(feature = "rp235xb")]
PIN_32,
#[cfg(feature = "rp235xb")]
PIN_33,
#[cfg(feature = "rp235xb")]
PIN_34,
#[cfg(feature = "rp235xb")]
PIN_35,
#[cfg(feature = "rp235xb")]
PIN_36,
#[cfg(feature = "rp235xb")]
PIN_37,
#[cfg(feature = "rp235xb")]
PIN_38,
#[cfg(feature = "rp235xb")]
PIN_39,
#[cfg(feature = "rp235xb")]
PIN_40,
#[cfg(feature = "rp235xb")]
PIN_41,
#[cfg(feature = "rp235xb")]
PIN_42,
#[cfg(feature = "rp235xb")]
PIN_43,
#[cfg(feature = "rp235xb")]
PIN_44,
#[cfg(feature = "rp235xb")]
PIN_45,
#[cfg(feature = "rp235xb")]
PIN_46,
#[cfg(feature = "rp235xb")]
PIN_47,
PIN_QSPI_SCLK,
PIN_QSPI_SS,
PIN_QSPI_SD0,
PIN_QSPI_SD1,
PIN_QSPI_SD2,
PIN_QSPI_SD3,
UART0,
UART1,
SPI0,
SPI1,
I2C0,
I2C1,
DMA_CH0,
DMA_CH1,
DMA_CH2,
DMA_CH3,
DMA_CH4,
DMA_CH5,
DMA_CH6,
DMA_CH7,
DMA_CH8,
DMA_CH9,
DMA_CH10,
DMA_CH11,
DMA_CH12,
DMA_CH13,
DMA_CH14,
DMA_CH15,
PWM_SLICE0,
PWM_SLICE1,
PWM_SLICE2,
PWM_SLICE3,
PWM_SLICE4,
PWM_SLICE5,
PWM_SLICE6,
PWM_SLICE7,
PWM_SLICE8,
PWM_SLICE9,
PWM_SLICE10,
PWM_SLICE11,
USB,
RTC,
FLASH,
ADC,
ADC_TEMP_SENSOR,
CORE1,
PIO0,
PIO1,
PIO2,
WATCHDOG,
BOOTSEL,
TRNG
}
#[cfg(all(not(feature = "boot2-none"), feature = "rp2040"))]
macro_rules! select_bootloader {
( $( $feature:literal => $loader:ident, )+ default => $default:ident ) => {
$(
#[cfg(feature = $feature)]
#[link_section = ".boot2"]
#[used]
static BOOT2: [u8; 256] = rp2040_boot2::$loader;
)*
#[cfg(not(any( $( feature = $feature),* )))]
#[link_section = ".boot2"]
#[used]
static BOOT2: [u8; 256] = rp2040_boot2::$default;
}
}
#[cfg(all(not(feature = "boot2-none"), feature = "rp2040"))]
select_bootloader! {
"boot2-at25sf128a" => BOOT_LOADER_AT25SF128A,
"boot2-gd25q64cs" => BOOT_LOADER_GD25Q64CS,
"boot2-generic-03h" => BOOT_LOADER_GENERIC_03H,
"boot2-is25lp080" => BOOT_LOADER_IS25LP080,
"boot2-ram-memcpy" => BOOT_LOADER_RAM_MEMCPY,
"boot2-w25q080" => BOOT_LOADER_W25Q080,
"boot2-w25x10cl" => BOOT_LOADER_W25X10CL,
default => BOOT_LOADER_W25Q080
}
/// Installs a stack guard for the CORE0 stack in MPU region 0.
/// Will fail if the MPU is already configured. This function requires
/// a `_stack_end` symbol to be defined by the linker script, and expects
/// `_stack_end` to be located at the lowest address (largest depth) of
/// the stack.
///
/// This method can *only* set up stack guards on the currently
/// executing core. Stack guards for CORE1 are set up automatically,
/// only CORE0 should ever use this.
///
/// # Usage
///
/// ```no_run
/// use embassy_rp::install_core0_stack_guard;
/// use embassy_executor::{Executor, Spawner};
///
/// #[embassy_executor::main]
/// async fn main(_spawner: Spawner) {
/// // set up by the linker as follows:
/// //
/// // MEMORY {
/// // STACK0: ORIGIN = 0x20040000, LENGTH = 4K
/// // }
/// //
/// // _stack_end = ORIGIN(STACK0);
/// // _stack_start = _stack_end + LENGTH(STACK0);
/// //
/// install_core0_stack_guard().expect("MPU already configured");
/// let p = embassy_rp::init(Default::default());
///
/// // ...
/// }
/// ```
pub fn install_core0_stack_guard() -> Result<(), ()> {
extern "C" {
static mut _stack_end: usize;
}
unsafe { install_stack_guard(core::ptr::addr_of_mut!(_stack_end)) }
}
#[cfg(all(feature = "rp2040", not(feature = "_test")))]
#[inline(always)]
unsafe fn install_stack_guard(stack_bottom: *mut usize) -> Result<(), ()> {
let core = unsafe { cortex_m::Peripherals::steal() };
// Fail if MPU is already configured
if core.MPU.ctrl.read() != 0 {
return Err(());
}
// The minimum we can protect is 32 bytes on a 32 byte boundary, so round up which will
// just shorten the valid stack range a tad.
let addr = (stack_bottom as u32 + 31) & !31;
// Mask is 1 bit per 32 bytes of the 256 byte range... clear the bit for the segment we want
let subregion_select = 0xff ^ (1 << ((addr >> 5) & 7));
unsafe {
core.MPU.ctrl.write(5); // enable mpu with background default map
core.MPU.rbar.write((addr & !0xff) | (1 << 4)); // set address and update RNR
core.MPU.rasr.write(
1 // enable region
| (0x7 << 1) // size 2^(7 + 1) = 256
| (subregion_select << 8)
| 0x10000000, // XN = disable instruction fetch; no other bits means no permissions
);
}
Ok(())
}
#[cfg(all(feature = "_rp235x", not(feature = "_test")))]
#[inline(always)]
unsafe fn install_stack_guard(stack_bottom: *mut usize) -> Result<(), ()> {
let core = unsafe { cortex_m::Peripherals::steal() };
// Fail if MPU is already configured
if core.MPU.ctrl.read() != 0 {
return Err(());
}
unsafe {
core.MPU.ctrl.write(5); // enable mpu with background default map
core.MPU.rbar.write(stack_bottom as u32 & !0xff); // set address
core.MPU.rlar.write(1); // enable region
}
Ok(())
}
// This is to hack around cortex_m defaulting to ARMv7 when building tests,
// so the compile fails when we try to use ARMv8 peripherals.
#[cfg(feature = "_test")]
#[inline(always)]
unsafe fn install_stack_guard(_stack_bottom: *mut usize) -> Result<(), ()> {
Ok(())
}
/// HAL configuration for RP.
pub mod config {
use crate::clocks::ClockConfig;
/// HAL configuration passed when initializing.
#[non_exhaustive]
pub struct Config {
/// Clock configuration.
pub clocks: ClockConfig,
}
impl Default for Config {
fn default() -> Self {
Self {
clocks: ClockConfig::crystal(12_000_000),
}
}
}
impl Config {
/// Create a new configuration with the provided clock config.
pub fn new(clocks: ClockConfig) -> Self {
Self { clocks }
}
}
}
/// Initialize the `embassy-rp` HAL with the provided configuration.
///
/// This returns the peripheral singletons that can be used for creating drivers.
///
/// This should only be called once at startup, otherwise it panics.
pub fn init(config: config::Config) -> Peripherals {
// Do this first, so that it panics if user is calling `init` a second time
// before doing anything important.
let peripherals = Peripherals::take();
unsafe {
clocks::init(config.clocks);
#[cfg(feature = "time-driver")]
time_driver::init();
dma::init();
gpio::init();
}
peripherals
}
#[cfg(all(feature = "rt", feature = "rp2040"))]
#[cortex_m_rt::pre_init]
unsafe fn pre_init() {
// SIO does not get reset when core0 is reset with either `scb::sys_reset()` or with SWD.
// Since we're using SIO spinlock 31 for the critical-section impl, this causes random
// hangs if we reset in the middle of a CS, because the next boot sees the spinlock
// as locked and waits forever.
//
// See https://github.com/embassy-rs/embassy/issues/1736
// and https://github.com/rp-rs/rp-hal/issues/292
// and https://matrix.to/#/!vhKMWjizPZBgKeknOo:matrix.org/$VfOkQgyf1PjmaXZbtycFzrCje1RorAXd8BQFHTl4d5M
//
// According to Raspberry Pi, this is considered Working As Intended, and not an errata,
// even though this behavior is different from every other ARM chip (sys_reset usually resets
// the *system* as its name implies, not just the current core).
//
// To fix this, reset SIO on boot. We must do this in pre_init because it's unsound to do it
// in `embassy_rp::init`, since the user could've acquired a CS by then. pre_init is guaranteed
// to run before any user code.
//
// A similar thing could happen with PROC1. It is unclear whether it's possible for PROC1
// to stay unreset through a PROC0 reset, so we reset it anyway just in case.
//
// Important info from PSM logic (from Luke Wren in above Matrix thread)
//
// The logic is, each PSM stage is reset if either of the following is true:
// - The previous stage is in reset and FRCE_ON is false
// - FRCE_OFF is true
//
// The PSM order is SIO -> PROC0 -> PROC1.
// So, we have to force-on PROC0 to prevent it from getting reset when resetting SIO.
pac::PSM.frce_on().write_and_wait(|w| {
w.set_proc0(true);
});
// Then reset SIO and PROC1.
pac::PSM.frce_off().write_and_wait(|w| {
w.set_sio(true);
w.set_proc1(true);
});
// clear force_off first, force_on second. The other way around would reset PROC0.
pac::PSM.frce_off().write_and_wait(|_| {});
pac::PSM.frce_on().write_and_wait(|_| {});
}
/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes.
#[allow(unused)]
trait RegExt<T: Copy> {
#[allow(unused)]
fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
fn write_and_wait<R>(&self, f: impl FnOnce(&mut T) -> R) -> R
where
T: PartialEq;
}
impl<T: Default + Copy, A: pac::common::Write> RegExt<T> for pac::common::Reg<T, A> {
fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
let mut val = Default::default();
let res = f(&mut val);
unsafe {
let ptr = (self.as_ptr() as *mut u8).add(0x1000) as *mut T;
ptr.write_volatile(val);
}
res
}
fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
let mut val = Default::default();
let res = f(&mut val);
unsafe {
let ptr = (self.as_ptr() as *mut u8).add(0x2000) as *mut T;
ptr.write_volatile(val);
}
res
}
fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
let mut val = Default::default();
let res = f(&mut val);
unsafe {
let ptr = (self.as_ptr() as *mut u8).add(0x3000) as *mut T;
ptr.write_volatile(val);
}
res
}
fn write_and_wait<R>(&self, f: impl FnOnce(&mut T) -> R) -> R
where
T: PartialEq,
{
let mut val = Default::default();
let res = f(&mut val);
unsafe {
self.as_ptr().write_volatile(val);
while self.as_ptr().read_volatile() != val {}
}
res
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,541 @@
#![cfg_attr(not(test), no_std)]
#![allow(async_fn_in_trait)]
#![cfg_attr(
docsrs,
doc = "<div style='padding:30px;background:#810;color:#fff;text-align:center;'><p>You might want to <a href='https://docs.embassy.dev/embassy-stm32'>browse the `embassy-stm32` documentation on the Embassy website</a> instead.</p><p>The documentation here on `docs.rs` is built for a single chip only (stm32h7, stm32h7rs55 in particular), while on the Embassy website you can pick your exact chip from the top menu. Available peripherals and their APIs change depending on the chip.</p></div>\n\n"
)]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
//! ## Feature flags
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
// This must go FIRST so that all the other modules see its macros.
mod fmt;
include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
// Utilities
mod macros;
pub mod time;
/// Operating modes for peripherals.
pub mod mode {
trait SealedMode {}
/// Operating mode for a peripheral.
#[allow(private_bounds)]
pub trait Mode: SealedMode {}
macro_rules! impl_mode {
($name:ident) => {
impl SealedMode for $name {}
impl Mode for $name {}
};
}
/// Blocking mode.
pub struct Blocking;
/// Async mode.
pub struct Async;
impl_mode!(Blocking);
impl_mode!(Async);
}
// Always-present hardware
pub mod dma;
pub mod gpio;
pub mod rcc;
#[cfg(feature = "_time-driver")]
mod time_driver;
pub mod timer;
// Sometimes-present hardware
#[cfg(adc)]
pub mod adc;
#[cfg(can)]
pub mod can;
// FIXME: Cordic driver cause stm32u5a5zj crash
#[cfg(all(cordic, not(any(stm32u5a5, stm32u5a9))))]
pub mod cordic;
#[cfg(crc)]
pub mod crc;
#[cfg(cryp)]
pub mod cryp;
#[cfg(dac)]
pub mod dac;
#[cfg(dcmi)]
pub mod dcmi;
#[cfg(dsihost)]
pub mod dsihost;
#[cfg(eth)]
pub mod eth;
#[cfg(feature = "exti")]
pub mod exti;
pub mod flash;
#[cfg(fmc)]
pub mod fmc;
#[cfg(hash)]
pub mod hash;
#[cfg(hrtim)]
pub mod hrtim;
#[cfg(hsem)]
pub mod hsem;
#[cfg(i2c)]
pub mod i2c;
#[cfg(any(all(spi_v1, rcc_f4), spi_v3))]
pub mod i2s;
#[cfg(stm32wb)]
pub mod ipcc;
#[cfg(feature = "low-power")]
pub mod low_power;
#[cfg(lptim)]
pub mod lptim;
#[cfg(ltdc)]
pub mod ltdc;
#[cfg(opamp)]
pub mod opamp;
#[cfg(octospi)]
pub mod ospi;
#[cfg(quadspi)]
pub mod qspi;
#[cfg(rng)]
pub mod rng;
#[cfg(all(rtc, not(rtc_v1)))]
pub mod rtc;
#[cfg(sai)]
pub mod sai;
#[cfg(sdmmc)]
pub mod sdmmc;
#[cfg(spi)]
pub mod spi;
#[cfg(tsc)]
pub mod tsc;
#[cfg(ucpd)]
pub mod ucpd;
#[cfg(uid)]
pub mod uid;
#[cfg(usart)]
pub mod usart;
#[cfg(any(usb, otg))]
pub mod usb;
#[cfg(iwdg)]
pub mod wdg;
// This must go last, so that it sees all the impl_foo! macros defined earlier.
pub(crate) mod _generated {
#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(non_snake_case)]
#![allow(missing_docs)]
include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
}
pub use crate::_generated::interrupt;
/// Macro to bind interrupts to handlers.
///
/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
/// prove at compile-time that the right interrupts have been bound.
///
/// Example of how to bind one interrupt:
///
/// ```rust,ignore
/// use embassy_stm32::{bind_interrupts, usb, peripherals};
///
/// bind_interrupts!(struct Irqs {
/// OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
/// });
/// ```
///
/// Example of how to bind multiple interrupts, and multiple handlers to each interrupt, in a single macro invocation:
///
/// ```rust,ignore
/// use embassy_stm32::{bind_interrupts, i2c, peripherals};
///
/// bind_interrupts!(struct Irqs {
/// I2C1 => i2c::EventInterruptHandler<peripherals::I2C1>, i2c::ErrorInterruptHandler<peripherals::I2C1>;
/// I2C2_3 => i2c::EventInterruptHandler<peripherals::I2C2>, i2c::ErrorInterruptHandler<peripherals::I2C2>,
/// i2c::EventInterruptHandler<peripherals::I2C3>, i2c::ErrorInterruptHandler<peripherals::I2C3>;
/// });
/// ```
// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
#[macro_export]
macro_rules! bind_interrupts {
($vis:vis struct $name:ident {
$(
$(#[cfg($cond_irq:meta)])?
$irq:ident => $(
$(#[cfg($cond_handler:meta)])?
$handler:ty
),*;
)*
}) => {
#[derive(Copy, Clone)]
$vis struct $name;
$(
#[allow(non_snake_case)]
#[no_mangle]
$(#[cfg($cond_irq)])?
unsafe extern "C" fn $irq() {
$(
$(#[cfg($cond_handler)])?
<$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
$(#[cfg($cond_handler)])?
unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
)*
}
)*
};
}
// Reexports
pub use _generated::{peripherals, Peripherals};
pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
#[cfg(feature = "unstable-pac")]
pub use stm32_metapac as pac;
#[cfg(not(feature = "unstable-pac"))]
pub(crate) use stm32_metapac as pac;
use crate::interrupt::Priority;
#[cfg(feature = "rt")]
pub use crate::pac::NVIC_PRIO_BITS;
/// `embassy-stm32` global configuration.
#[non_exhaustive]
#[derive(Clone, Copy)]
pub struct Config {
/// RCC config.
pub rcc: rcc::Config,
/// Enable debug during sleep and stop.
///
/// May increase power consumption. Defaults to true.
#[cfg(dbgmcu)]
pub enable_debug_during_sleep: bool,
/// On low-power boards (eg. `stm32l4`, `stm32l5` and `stm32u5`),
/// some GPIO pins are powered by an auxiliary, independent power supply (`VDDIO2`),
/// which needs to be enabled before these pins can be used.
///
/// May increase power consumption. Defaults to true.
#[cfg(any(stm32l4, stm32l5, stm32u5))]
pub enable_independent_io_supply: bool,
/// BDMA interrupt priority.
///
/// Defaults to P0 (highest).
#[cfg(bdma)]
pub bdma_interrupt_priority: Priority,
/// DMA interrupt priority.
///
/// Defaults to P0 (highest).
#[cfg(dma)]
pub dma_interrupt_priority: Priority,
/// GPDMA interrupt priority.
///
/// Defaults to P0 (highest).
#[cfg(gpdma)]
pub gpdma_interrupt_priority: Priority,
/// Enables UCPD1 dead battery functionality.
///
/// Defaults to false (disabled).
#[cfg(peri_ucpd1)]
pub enable_ucpd1_dead_battery: bool,
/// Enables UCPD2 dead battery functionality.
///
/// Defaults to false (disabled).
#[cfg(peri_ucpd2)]
pub enable_ucpd2_dead_battery: bool,
}
impl Default for Config {
fn default() -> Self {
Self {
rcc: Default::default(),
#[cfg(dbgmcu)]
enable_debug_during_sleep: true,
#[cfg(any(stm32l4, stm32l5, stm32u5))]
enable_independent_io_supply: true,
#[cfg(bdma)]
bdma_interrupt_priority: Priority::P0,
#[cfg(dma)]
dma_interrupt_priority: Priority::P0,
#[cfg(gpdma)]
gpdma_interrupt_priority: Priority::P0,
#[cfg(peri_ucpd1)]
enable_ucpd1_dead_battery: false,
#[cfg(peri_ucpd2)]
enable_ucpd2_dead_battery: false,
}
}
}
/// Initialize the `embassy-stm32` HAL with the provided configuration.
///
/// This returns the peripheral singletons that can be used for creating drivers.
///
/// This should only be called once at startup, otherwise it panics.
#[cfg(not(feature = "_dual-core"))]
pub fn init(config: Config) -> Peripherals {
init_hw(config)
}
#[cfg(feature = "_dual-core")]
mod dual_core {
use core::cell::UnsafeCell;
use core::mem::MaybeUninit;
use core::sync::atomic::{AtomicUsize, Ordering};
use rcc::Clocks;
use super::*;
/// Object containing data that embassy needs to share between cores.
///
/// It cannot be initialized by the user. The intended use is:
///
/// ```
/// use core::mem::MaybeUninit;
/// use embassy_stm32::{init_secondary, SharedData};
///
/// #[link_section = ".ram_d3"]
/// static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
///
/// init_secondary(&SHARED_DATA);
/// ```
///
/// This static must be placed in the same position for both cores. How and where this is done is left to the user.
pub struct SharedData {
init_flag: AtomicUsize,
clocks: UnsafeCell<MaybeUninit<Clocks>>,
config: UnsafeCell<MaybeUninit<Config>>,
}
unsafe impl Sync for SharedData {}
const INIT_DONE_FLAG: usize = 0xca11ab1e;
/// Initialize the `embassy-stm32` HAL with the provided configuration.
/// This function does the actual initialization of the hardware, in contrast to [init_secondary] or [try_init_secondary].
/// Any core can do the init, but it's important only one core does it.
///
/// This returns the peripheral singletons that can be used for creating drivers.
///
/// This should only be called once at startup, otherwise it panics.
///
/// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs
/// for more information on its requirements.
pub fn init_primary(config: Config, shared_data: &'static MaybeUninit<SharedData>) -> Peripherals {
let shared_data = unsafe { shared_data.assume_init_ref() };
rcc::set_freqs_ptr(shared_data.clocks.get());
let p = init_hw(config);
unsafe { *shared_data.config.get() }.write(config);
shared_data.init_flag.store(INIT_DONE_FLAG, Ordering::SeqCst);
p
}
/// Try to initialize the `embassy-stm32` HAL based on the init done by the other core using [init_primary].
///
/// This returns the peripheral singletons that can be used for creating drivers if the other core is done with its init.
/// If the other core is not done yet, this will return `None`.
///
/// This should only be called once at startup, otherwise it may panic.
///
/// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs
/// for more information on its requirements.
pub fn try_init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Option<Peripherals> {
let shared_data = unsafe { shared_data.assume_init_ref() };
if shared_data.init_flag.load(Ordering::SeqCst) != INIT_DONE_FLAG {
return None;
}
// Separate load and store to support the CM0 of the STM32WL
shared_data.init_flag.store(0, Ordering::SeqCst);
Some(init_secondary_hw(shared_data))
}
/// Initialize the `embassy-stm32` HAL based on the init done by the other core using [init_primary].
///
/// This returns the peripheral singletons that can be used for creating drivers when the other core is done with its init.
/// If the other core is not done yet, this will spinloop wait on it.
///
/// This should only be called once at startup, otherwise it may panic.
///
/// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs
/// for more information on its requirements.
pub fn init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Peripherals {
loop {
if let Some(p) = try_init_secondary(shared_data) {
return p;
}
}
}
fn init_secondary_hw(shared_data: &'static SharedData) -> Peripherals {
rcc::set_freqs_ptr(shared_data.clocks.get());
let config = unsafe { (*shared_data.config.get()).assume_init() };
// We use different timers on the different cores, so we have to still initialize one here
critical_section::with(|cs| {
unsafe {
dma::init(
cs,
#[cfg(bdma)]
config.bdma_interrupt_priority,
#[cfg(dma)]
config.dma_interrupt_priority,
#[cfg(gpdma)]
config.gpdma_interrupt_priority,
)
}
#[cfg(feature = "_time-driver")]
// must be after rcc init
time_driver::init(cs);
});
Peripherals::take()
}
}
#[cfg(feature = "_dual-core")]
pub use dual_core::*;
fn init_hw(config: Config) -> Peripherals {
critical_section::with(|cs| {
let p = Peripherals::take_with_cs(cs);
#[cfg(dbgmcu)]
crate::pac::DBGMCU.cr().modify(|cr| {
#[cfg(dbgmcu_h5)]
{
cr.set_stop(config.enable_debug_during_sleep);
cr.set_standby(config.enable_debug_during_sleep);
}
#[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba, dbgmcu_l5))]
{
cr.set_dbg_stop(config.enable_debug_during_sleep);
cr.set_dbg_standby(config.enable_debug_during_sleep);
}
#[cfg(any(
dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1,
dbgmcu_l4, dbgmcu_wb, dbgmcu_wl
))]
{
cr.set_dbg_sleep(config.enable_debug_during_sleep);
cr.set_dbg_stop(config.enable_debug_during_sleep);
cr.set_dbg_standby(config.enable_debug_during_sleep);
}
#[cfg(dbgmcu_h7)]
{
cr.set_d1dbgcken(config.enable_debug_during_sleep);
cr.set_d3dbgcken(config.enable_debug_during_sleep);
cr.set_dbgsleep_d1(config.enable_debug_during_sleep);
cr.set_dbgstby_d1(config.enable_debug_during_sleep);
cr.set_dbgstop_d1(config.enable_debug_during_sleep);
}
});
#[cfg(not(any(stm32f1, stm32wb, stm32wl)))]
rcc::enable_and_reset_with_cs::<peripherals::SYSCFG>(cs);
#[cfg(not(any(stm32h5, stm32h7, stm32h7rs, stm32wb, stm32wl)))]
rcc::enable_and_reset_with_cs::<peripherals::PWR>(cs);
#[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7, stm32h7rs)))]
rcc::enable_and_reset_with_cs::<peripherals::FLASH>(cs);
// Enable the VDDIO2 power supply on chips that have it.
// Note that this requires the PWR peripheral to be enabled first.
#[cfg(any(stm32l4, stm32l5))]
{
crate::pac::PWR.cr2().modify(|w| {
// The official documentation states that we should ideally enable VDDIO2
// through the PVME2 bit, but it looks like this isn't required,
// and CubeMX itself skips this step.
w.set_iosv(config.enable_independent_io_supply);
});
}
#[cfg(stm32u5)]
{
crate::pac::PWR.svmcr().modify(|w| {
w.set_io2sv(config.enable_independent_io_supply);
});
}
// dead battery functionality is still present on these
// chips despite them not having UCPD- disable it
#[cfg(any(stm32g070, stm32g0b0))]
{
crate::pac::SYSCFG.cfgr1().modify(|w| {
w.set_ucpd1_strobe(true);
w.set_ucpd2_strobe(true);
});
}
unsafe {
#[cfg(ucpd)]
ucpd::init(
cs,
#[cfg(peri_ucpd1)]
config.enable_ucpd1_dead_battery,
#[cfg(peri_ucpd2)]
config.enable_ucpd2_dead_battery,
);
#[cfg(feature = "_split-pins-enabled")]
crate::pac::SYSCFG.pmcr().modify(|pmcr| {
#[cfg(feature = "split-pa0")]
pmcr.set_pa0so(true);
#[cfg(feature = "split-pa1")]
pmcr.set_pa1so(true);
#[cfg(feature = "split-pc2")]
pmcr.set_pc2so(true);
#[cfg(feature = "split-pc3")]
pmcr.set_pc3so(true);
});
gpio::init(cs);
dma::init(
cs,
#[cfg(bdma)]
config.bdma_interrupt_priority,
#[cfg(dma)]
config.dma_interrupt_priority,
#[cfg(gpdma)]
config.gpdma_interrupt_priority,
);
#[cfg(feature = "exti")]
exti::init(cs);
rcc::init(config.rcc);
// must be after rcc init
#[cfg(feature = "_time-driver")]
time_driver::init(cs);
#[cfg(feature = "low-power")]
{
crate::rcc::REFCOUNT_STOP2 = 0;
crate::rcc::REFCOUNT_STOP1 = 0;
}
}
p
})
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,434 @@
[package]
name = "embassy-time"
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"
documentation = "https://docs.embassy.dev/embassy-time"
readme = "README.md"
license = "MIT OR Apache-2.0"
categories = [
"embedded",
"no-std",
"concurrency",
"asynchronous",
]
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-time-v$VERSION/embassy-time/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-time/src/"
features = ["defmt", "std"]
target = "x86_64-unknown-linux-gnu"
[package.metadata.docs.rs]
features = ["defmt", "std"]
[features]
std = ["tick-hz-1_000_000", "critical-section/std"]
wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-timer", "tick-hz-1_000_000"]
## Display the time since startup next to defmt log messages.
## At most 1 `defmt-timestamp-uptime-*` feature can be used.
## `defmt-timestamp-uptime` is provided for backwards compatibility (provides the same format as `uptime-us`).
## To use this you must have a time driver provided.
defmt-timestamp-uptime = ["defmt"]
defmt-timestamp-uptime-s = ["defmt"]
defmt-timestamp-uptime-ms = ["defmt"]
defmt-timestamp-uptime-us = ["defmt"]
defmt-timestamp-uptime-ts = ["defmt"]
defmt-timestamp-uptime-tms = ["defmt"]
defmt-timestamp-uptime-tus = ["defmt"]
## Create a `MockDriver` that can be manually advanced for testing purposes.
mock-driver = ["tick-hz-1_000_000"]
#! ### Generic Queue
## Create a global, generic queue that can be used with any executor.
## To use this you must have a time driver provided.
generic-queue = []
#! The following features set how many timers are used for the generic queue. At most one
#! `generic-queue-*` feature can be enabled. If none is enabled, a default of 64 timers is used.
#!
#! When using embassy-time from libraries, you should *not* enable any `generic-queue-*` feature, to allow the
#! end user to pick.
## Generic Queue with 8 timers
generic-queue-8 = ["generic-queue"]
## Generic Queue with 16 timers
generic-queue-16 = ["generic-queue"]
## Generic Queue with 32 timers
generic-queue-32 = ["generic-queue"]
## Generic Queue with 64 timers
generic-queue-64 = ["generic-queue"]
## Generic Queue with 128 timers
generic-queue-128 = ["generic-queue"]
#! ### Tick Rate
#!
#! At most 1 `tick-*` feature can be enabled. If none is enabled, a default of 1MHz is used.
#!
#! If the time driver in use supports using arbitrary tick rates, you can enable one `tick-*`
#! feature from your binary crate to set the tick rate. The driver will use configured tick rate.
#! If the time driver supports a fixed tick rate, it will enable one feature itself, so you should
#! not enable one. Check the time driver documentation for details.
#!
#! When using embassy-time from libraries, you should *not* enable any `tick-*` feature, to allow the
#! end user or the driver to pick.
#! <details>
#! <summary>Available tick rates:</summary>
#! <!-- Next line must be left empty for the features to render correctly! -->
#!
# BEGIN TICKS
# Generated by gen_tick.py. DO NOT EDIT.
## 1Hz Tick Rate
tick-hz-1 = ["embassy-time-driver/tick-hz-1"]
## 2Hz Tick Rate
tick-hz-2 = ["embassy-time-driver/tick-hz-2"]
## 4Hz Tick Rate
tick-hz-4 = ["embassy-time-driver/tick-hz-4"]
## 8Hz Tick Rate
tick-hz-8 = ["embassy-time-driver/tick-hz-8"]
## 10Hz Tick Rate
tick-hz-10 = ["embassy-time-driver/tick-hz-10"]
## 16Hz Tick Rate
tick-hz-16 = ["embassy-time-driver/tick-hz-16"]
## 32Hz Tick Rate
tick-hz-32 = ["embassy-time-driver/tick-hz-32"]
## 64Hz Tick Rate
tick-hz-64 = ["embassy-time-driver/tick-hz-64"]
## 100Hz Tick Rate
tick-hz-100 = ["embassy-time-driver/tick-hz-100"]
## 128Hz Tick Rate
tick-hz-128 = ["embassy-time-driver/tick-hz-128"]
## 256Hz Tick Rate
tick-hz-256 = ["embassy-time-driver/tick-hz-256"]
## 512Hz Tick Rate
tick-hz-512 = ["embassy-time-driver/tick-hz-512"]
## 1.0kHz Tick Rate
tick-hz-1_000 = ["embassy-time-driver/tick-hz-1_000"]
## 1.024kHz Tick Rate
tick-hz-1_024 = ["embassy-time-driver/tick-hz-1_024"]
## 2.0kHz Tick Rate
tick-hz-2_000 = ["embassy-time-driver/tick-hz-2_000"]
## 2.048kHz Tick Rate
tick-hz-2_048 = ["embassy-time-driver/tick-hz-2_048"]
## 4.0kHz Tick Rate
tick-hz-4_000 = ["embassy-time-driver/tick-hz-4_000"]
## 4.096kHz Tick Rate
tick-hz-4_096 = ["embassy-time-driver/tick-hz-4_096"]
## 8.0kHz Tick Rate
tick-hz-8_000 = ["embassy-time-driver/tick-hz-8_000"]
## 8.192kHz Tick Rate
tick-hz-8_192 = ["embassy-time-driver/tick-hz-8_192"]
## 10.0kHz Tick Rate
tick-hz-10_000 = ["embassy-time-driver/tick-hz-10_000"]
## 16.0kHz Tick Rate
tick-hz-16_000 = ["embassy-time-driver/tick-hz-16_000"]
## 16.384kHz Tick Rate
tick-hz-16_384 = ["embassy-time-driver/tick-hz-16_384"]
## 20.0kHz Tick Rate
tick-hz-20_000 = ["embassy-time-driver/tick-hz-20_000"]
## 32.0kHz Tick Rate
tick-hz-32_000 = ["embassy-time-driver/tick-hz-32_000"]
## 32.768kHz Tick Rate
tick-hz-32_768 = ["embassy-time-driver/tick-hz-32_768"]
## 40.0kHz Tick Rate
tick-hz-40_000 = ["embassy-time-driver/tick-hz-40_000"]
## 64.0kHz Tick Rate
tick-hz-64_000 = ["embassy-time-driver/tick-hz-64_000"]
## 65.536kHz Tick Rate
tick-hz-65_536 = ["embassy-time-driver/tick-hz-65_536"]
## 80.0kHz Tick Rate
tick-hz-80_000 = ["embassy-time-driver/tick-hz-80_000"]
## 100.0kHz Tick Rate
tick-hz-100_000 = ["embassy-time-driver/tick-hz-100_000"]
## 128.0kHz Tick Rate
tick-hz-128_000 = ["embassy-time-driver/tick-hz-128_000"]
## 131.072kHz Tick Rate
tick-hz-131_072 = ["embassy-time-driver/tick-hz-131_072"]
## 160.0kHz Tick Rate
tick-hz-160_000 = ["embassy-time-driver/tick-hz-160_000"]
## 256.0kHz Tick Rate
tick-hz-256_000 = ["embassy-time-driver/tick-hz-256_000"]
## 262.144kHz Tick Rate
tick-hz-262_144 = ["embassy-time-driver/tick-hz-262_144"]
## 320.0kHz Tick Rate
tick-hz-320_000 = ["embassy-time-driver/tick-hz-320_000"]
## 512.0kHz Tick Rate
tick-hz-512_000 = ["embassy-time-driver/tick-hz-512_000"]
## 524.288kHz Tick Rate
tick-hz-524_288 = ["embassy-time-driver/tick-hz-524_288"]
## 640.0kHz Tick Rate
tick-hz-640_000 = ["embassy-time-driver/tick-hz-640_000"]
## 1.0MHz Tick Rate
tick-hz-1_000_000 = ["embassy-time-driver/tick-hz-1_000_000"]
## 1.024MHz Tick Rate
tick-hz-1_024_000 = ["embassy-time-driver/tick-hz-1_024_000"]
## 1.048576MHz Tick Rate
tick-hz-1_048_576 = ["embassy-time-driver/tick-hz-1_048_576"]
## 1.28MHz Tick Rate
tick-hz-1_280_000 = ["embassy-time-driver/tick-hz-1_280_000"]
## 2.0MHz Tick Rate
tick-hz-2_000_000 = ["embassy-time-driver/tick-hz-2_000_000"]
## 2.048MHz Tick Rate
tick-hz-2_048_000 = ["embassy-time-driver/tick-hz-2_048_000"]
## 2.097152MHz Tick Rate
tick-hz-2_097_152 = ["embassy-time-driver/tick-hz-2_097_152"]
## 2.56MHz Tick Rate
tick-hz-2_560_000 = ["embassy-time-driver/tick-hz-2_560_000"]
## 3.0MHz Tick Rate
tick-hz-3_000_000 = ["embassy-time-driver/tick-hz-3_000_000"]
## 4.0MHz Tick Rate
tick-hz-4_000_000 = ["embassy-time-driver/tick-hz-4_000_000"]
## 4.096MHz Tick Rate
tick-hz-4_096_000 = ["embassy-time-driver/tick-hz-4_096_000"]
## 4.194304MHz Tick Rate
tick-hz-4_194_304 = ["embassy-time-driver/tick-hz-4_194_304"]
## 5.12MHz Tick Rate
tick-hz-5_120_000 = ["embassy-time-driver/tick-hz-5_120_000"]
## 6.0MHz Tick Rate
tick-hz-6_000_000 = ["embassy-time-driver/tick-hz-6_000_000"]
## 8.0MHz Tick Rate
tick-hz-8_000_000 = ["embassy-time-driver/tick-hz-8_000_000"]
## 8.192MHz Tick Rate
tick-hz-8_192_000 = ["embassy-time-driver/tick-hz-8_192_000"]
## 8.388608MHz Tick Rate
tick-hz-8_388_608 = ["embassy-time-driver/tick-hz-8_388_608"]
## 9.0MHz Tick Rate
tick-hz-9_000_000 = ["embassy-time-driver/tick-hz-9_000_000"]
## 10.0MHz Tick Rate
tick-hz-10_000_000 = ["embassy-time-driver/tick-hz-10_000_000"]
## 10.24MHz Tick Rate
tick-hz-10_240_000 = ["embassy-time-driver/tick-hz-10_240_000"]
## 12.0MHz Tick Rate
tick-hz-12_000_000 = ["embassy-time-driver/tick-hz-12_000_000"]
## 16.0MHz Tick Rate
tick-hz-16_000_000 = ["embassy-time-driver/tick-hz-16_000_000"]
## 16.384MHz Tick Rate
tick-hz-16_384_000 = ["embassy-time-driver/tick-hz-16_384_000"]
## 16.777216MHz Tick Rate
tick-hz-16_777_216 = ["embassy-time-driver/tick-hz-16_777_216"]
## 18.0MHz Tick Rate
tick-hz-18_000_000 = ["embassy-time-driver/tick-hz-18_000_000"]
## 20.0MHz Tick Rate
tick-hz-20_000_000 = ["embassy-time-driver/tick-hz-20_000_000"]
## 20.48MHz Tick Rate
tick-hz-20_480_000 = ["embassy-time-driver/tick-hz-20_480_000"]
## 24.0MHz Tick Rate
tick-hz-24_000_000 = ["embassy-time-driver/tick-hz-24_000_000"]
## 30.0MHz Tick Rate
tick-hz-30_000_000 = ["embassy-time-driver/tick-hz-30_000_000"]
## 32.0MHz Tick Rate
tick-hz-32_000_000 = ["embassy-time-driver/tick-hz-32_000_000"]
## 32.768MHz Tick Rate
tick-hz-32_768_000 = ["embassy-time-driver/tick-hz-32_768_000"]
## 36.0MHz Tick Rate
tick-hz-36_000_000 = ["embassy-time-driver/tick-hz-36_000_000"]
## 40.0MHz Tick Rate
tick-hz-40_000_000 = ["embassy-time-driver/tick-hz-40_000_000"]
## 40.96MHz Tick Rate
tick-hz-40_960_000 = ["embassy-time-driver/tick-hz-40_960_000"]
## 48.0MHz Tick Rate
tick-hz-48_000_000 = ["embassy-time-driver/tick-hz-48_000_000"]
## 50.0MHz Tick Rate
tick-hz-50_000_000 = ["embassy-time-driver/tick-hz-50_000_000"]
## 60.0MHz Tick Rate
tick-hz-60_000_000 = ["embassy-time-driver/tick-hz-60_000_000"]
## 64.0MHz Tick Rate
tick-hz-64_000_000 = ["embassy-time-driver/tick-hz-64_000_000"]
## 65.536MHz Tick Rate
tick-hz-65_536_000 = ["embassy-time-driver/tick-hz-65_536_000"]
## 70.0MHz Tick Rate
tick-hz-70_000_000 = ["embassy-time-driver/tick-hz-70_000_000"]
## 72.0MHz Tick Rate
tick-hz-72_000_000 = ["embassy-time-driver/tick-hz-72_000_000"]
## 80.0MHz Tick Rate
tick-hz-80_000_000 = ["embassy-time-driver/tick-hz-80_000_000"]
## 81.92MHz Tick Rate
tick-hz-81_920_000 = ["embassy-time-driver/tick-hz-81_920_000"]
## 90.0MHz Tick Rate
tick-hz-90_000_000 = ["embassy-time-driver/tick-hz-90_000_000"]
## 96.0MHz Tick Rate
tick-hz-96_000_000 = ["embassy-time-driver/tick-hz-96_000_000"]
## 100.0MHz Tick Rate
tick-hz-100_000_000 = ["embassy-time-driver/tick-hz-100_000_000"]
## 110.0MHz Tick Rate
tick-hz-110_000_000 = ["embassy-time-driver/tick-hz-110_000_000"]
## 120.0MHz Tick Rate
tick-hz-120_000_000 = ["embassy-time-driver/tick-hz-120_000_000"]
## 128.0MHz Tick Rate
tick-hz-128_000_000 = ["embassy-time-driver/tick-hz-128_000_000"]
## 130.0MHz Tick Rate
tick-hz-130_000_000 = ["embassy-time-driver/tick-hz-130_000_000"]
## 131.072MHz Tick Rate
tick-hz-131_072_000 = ["embassy-time-driver/tick-hz-131_072_000"]
## 140.0MHz Tick Rate
tick-hz-140_000_000 = ["embassy-time-driver/tick-hz-140_000_000"]
## 144.0MHz Tick Rate
tick-hz-144_000_000 = ["embassy-time-driver/tick-hz-144_000_000"]
## 150.0MHz Tick Rate
tick-hz-150_000_000 = ["embassy-time-driver/tick-hz-150_000_000"]
## 160.0MHz Tick Rate
tick-hz-160_000_000 = ["embassy-time-driver/tick-hz-160_000_000"]
## 163.84MHz Tick Rate
tick-hz-163_840_000 = ["embassy-time-driver/tick-hz-163_840_000"]
## 170.0MHz Tick Rate
tick-hz-170_000_000 = ["embassy-time-driver/tick-hz-170_000_000"]
## 180.0MHz Tick Rate
tick-hz-180_000_000 = ["embassy-time-driver/tick-hz-180_000_000"]
## 190.0MHz Tick Rate
tick-hz-190_000_000 = ["embassy-time-driver/tick-hz-190_000_000"]
## 192.0MHz Tick Rate
tick-hz-192_000_000 = ["embassy-time-driver/tick-hz-192_000_000"]
## 200.0MHz Tick Rate
tick-hz-200_000_000 = ["embassy-time-driver/tick-hz-200_000_000"]
## 210.0MHz Tick Rate
tick-hz-210_000_000 = ["embassy-time-driver/tick-hz-210_000_000"]
## 220.0MHz Tick Rate
tick-hz-220_000_000 = ["embassy-time-driver/tick-hz-220_000_000"]
## 230.0MHz Tick Rate
tick-hz-230_000_000 = ["embassy-time-driver/tick-hz-230_000_000"]
## 240.0MHz Tick Rate
tick-hz-240_000_000 = ["embassy-time-driver/tick-hz-240_000_000"]
## 250.0MHz Tick Rate
tick-hz-250_000_000 = ["embassy-time-driver/tick-hz-250_000_000"]
## 256.0MHz Tick Rate
tick-hz-256_000_000 = ["embassy-time-driver/tick-hz-256_000_000"]
## 260.0MHz Tick Rate
tick-hz-260_000_000 = ["embassy-time-driver/tick-hz-260_000_000"]
## 262.144MHz Tick Rate
tick-hz-262_144_000 = ["embassy-time-driver/tick-hz-262_144_000"]
## 270.0MHz Tick Rate
tick-hz-270_000_000 = ["embassy-time-driver/tick-hz-270_000_000"]
## 280.0MHz Tick Rate
tick-hz-280_000_000 = ["embassy-time-driver/tick-hz-280_000_000"]
## 288.0MHz Tick Rate
tick-hz-288_000_000 = ["embassy-time-driver/tick-hz-288_000_000"]
## 290.0MHz Tick Rate
tick-hz-290_000_000 = ["embassy-time-driver/tick-hz-290_000_000"]
## 300.0MHz Tick Rate
tick-hz-300_000_000 = ["embassy-time-driver/tick-hz-300_000_000"]
## 320.0MHz Tick Rate
tick-hz-320_000_000 = ["embassy-time-driver/tick-hz-320_000_000"]
## 327.68MHz Tick Rate
tick-hz-327_680_000 = ["embassy-time-driver/tick-hz-327_680_000"]
## 340.0MHz Tick Rate
tick-hz-340_000_000 = ["embassy-time-driver/tick-hz-340_000_000"]
## 360.0MHz Tick Rate
tick-hz-360_000_000 = ["embassy-time-driver/tick-hz-360_000_000"]
## 380.0MHz Tick Rate
tick-hz-380_000_000 = ["embassy-time-driver/tick-hz-380_000_000"]
## 384.0MHz Tick Rate
tick-hz-384_000_000 = ["embassy-time-driver/tick-hz-384_000_000"]
## 400.0MHz Tick Rate
tick-hz-400_000_000 = ["embassy-time-driver/tick-hz-400_000_000"]
## 420.0MHz Tick Rate
tick-hz-420_000_000 = ["embassy-time-driver/tick-hz-420_000_000"]
## 440.0MHz Tick Rate
tick-hz-440_000_000 = ["embassy-time-driver/tick-hz-440_000_000"]
## 460.0MHz Tick Rate
tick-hz-460_000_000 = ["embassy-time-driver/tick-hz-460_000_000"]
## 480.0MHz Tick Rate
tick-hz-480_000_000 = ["embassy-time-driver/tick-hz-480_000_000"]
## 500.0MHz Tick Rate
tick-hz-500_000_000 = ["embassy-time-driver/tick-hz-500_000_000"]
## 512.0MHz Tick Rate
tick-hz-512_000_000 = ["embassy-time-driver/tick-hz-512_000_000"]
## 520.0MHz Tick Rate
tick-hz-520_000_000 = ["embassy-time-driver/tick-hz-520_000_000"]
## 524.288MHz Tick Rate
tick-hz-524_288_000 = ["embassy-time-driver/tick-hz-524_288_000"]
## 540.0MHz Tick Rate
tick-hz-540_000_000 = ["embassy-time-driver/tick-hz-540_000_000"]
## 560.0MHz Tick Rate
tick-hz-560_000_000 = ["embassy-time-driver/tick-hz-560_000_000"]
## 576.0MHz Tick Rate
tick-hz-576_000_000 = ["embassy-time-driver/tick-hz-576_000_000"]
## 580.0MHz Tick Rate
tick-hz-580_000_000 = ["embassy-time-driver/tick-hz-580_000_000"]
## 600.0MHz Tick Rate
tick-hz-600_000_000 = ["embassy-time-driver/tick-hz-600_000_000"]
## 620.0MHz Tick Rate
tick-hz-620_000_000 = ["embassy-time-driver/tick-hz-620_000_000"]
## 640.0MHz Tick Rate
tick-hz-640_000_000 = ["embassy-time-driver/tick-hz-640_000_000"]
## 655.36MHz Tick Rate
tick-hz-655_360_000 = ["embassy-time-driver/tick-hz-655_360_000"]
## 660.0MHz Tick Rate
tick-hz-660_000_000 = ["embassy-time-driver/tick-hz-660_000_000"]
## 680.0MHz Tick Rate
tick-hz-680_000_000 = ["embassy-time-driver/tick-hz-680_000_000"]
## 700.0MHz Tick Rate
tick-hz-700_000_000 = ["embassy-time-driver/tick-hz-700_000_000"]
## 720.0MHz Tick Rate
tick-hz-720_000_000 = ["embassy-time-driver/tick-hz-720_000_000"]
## 740.0MHz Tick Rate
tick-hz-740_000_000 = ["embassy-time-driver/tick-hz-740_000_000"]
## 760.0MHz Tick Rate
tick-hz-760_000_000 = ["embassy-time-driver/tick-hz-760_000_000"]
## 768.0MHz Tick Rate
tick-hz-768_000_000 = ["embassy-time-driver/tick-hz-768_000_000"]
## 780.0MHz Tick Rate
tick-hz-780_000_000 = ["embassy-time-driver/tick-hz-780_000_000"]
## 800.0MHz Tick Rate
tick-hz-800_000_000 = ["embassy-time-driver/tick-hz-800_000_000"]
## 820.0MHz Tick Rate
tick-hz-820_000_000 = ["embassy-time-driver/tick-hz-820_000_000"]
## 840.0MHz Tick Rate
tick-hz-840_000_000 = ["embassy-time-driver/tick-hz-840_000_000"]
## 860.0MHz Tick Rate
tick-hz-860_000_000 = ["embassy-time-driver/tick-hz-860_000_000"]
## 880.0MHz Tick Rate
tick-hz-880_000_000 = ["embassy-time-driver/tick-hz-880_000_000"]
## 900.0MHz Tick Rate
tick-hz-900_000_000 = ["embassy-time-driver/tick-hz-900_000_000"]
## 920.0MHz Tick Rate
tick-hz-920_000_000 = ["embassy-time-driver/tick-hz-920_000_000"]
## 940.0MHz Tick Rate
tick-hz-940_000_000 = ["embassy-time-driver/tick-hz-940_000_000"]
## 960.0MHz Tick Rate
tick-hz-960_000_000 = ["embassy-time-driver/tick-hz-960_000_000"]
## 980.0MHz Tick Rate
tick-hz-980_000_000 = ["embassy-time-driver/tick-hz-980_000_000"]
## 1.0GHz Tick Rate
tick-hz-1_000_000_000 = ["embassy-time-driver/tick-hz-1_000_000_000"]
## 1.31072GHz Tick Rate
tick-hz-1_310_720_000 = ["embassy-time-driver/tick-hz-1_310_720_000"]
## 2.62144GHz Tick Rate
tick-hz-2_621_440_000 = ["embassy-time-driver/tick-hz-2_621_440_000"]
## 5.24288GHz Tick Rate
tick-hz-5_242_880_000 = ["embassy-time-driver/tick-hz-5_242_880_000"]
# END TICKS
#! </details>
[dependencies]
embassy-time-driver = { version = "0.1.0", path = "../embassy-time-driver" }
embassy-time-queue-driver = { version = "0.1.0", path = "../embassy-time-queue-driver" }
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" }
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
futures-util = { version = "0.3.17", default-features = false }
critical-section = "1.1"
cfg-if = "1.0.0"
heapless = "0.8"
document-features = "0.2.7"
# WASM dependencies
wasm-bindgen = { version = "0.2.81", optional = true }
js-sys = { version = "0.3", optional = true }
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.6.2", path = "../embassy-executor" }

View File

@ -0,0 +1,34 @@
[package]
edition = "2021"
name = "embassy-boot-nrf-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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 }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
ed25519-dalek = ["embassy-boot/ed25519-dalek"]
ed25519-salty = ["embassy-boot/ed25519-salty"]
skip-include = []
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-nrf/defmt",
"embassy-boot-nrf/defmt",
"embassy-sync/defmt",
]

View File

@ -0,0 +1,36 @@
[package]
edition = "2021"
name = "embassy-boot-rp-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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", "rp2040"] }
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"
panic-probe = { version = "0.3", features = ["print-defmt"], optional = true }
panic-reset = { version = "0.1.1", optional = true }
embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-storage = "0.3.1"
[features]
default = ["panic-reset"]
debug = [
"embassy-rp/defmt",
"embassy-boot-rp/defmt",
"embassy-sync/defmt",
"panic-probe"
]
skip-include = []
[profile.release]
debug = true

View File

@ -0,0 +1,31 @@
[package]
edition = "2021"
name = "embassy-boot-stm32f3-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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.2.0", path = "../../../../embassy-embedded-hal" }
defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-stm32/defmt",
"embassy-boot-stm32/defmt",
"embassy-sync/defmt",
]
skip-include = []

View File

@ -0,0 +1,32 @@
[package]
edition = "2021"
name = "embassy-boot-stm32f7-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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.2.0", path = "../../../../embassy-embedded-hal" }
defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
embedded-storage = "0.3.1"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-stm32/defmt",
"embassy-boot-stm32/defmt",
"embassy-sync/defmt",
]
skip-include = []

View File

@ -0,0 +1,32 @@
[package]
edition = "2021"
name = "embassy-boot-stm32h7-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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.2.0", path = "../../../../embassy-embedded-hal" }
defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
embedded-storage = "0.3.1"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-stm32/defmt",
"embassy-boot-stm32/defmt",
"embassy-sync/defmt",
]
skip-include = []

View File

@ -0,0 +1,31 @@
[package]
edition = "2021"
name = "embassy-boot-stm32l0-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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.2.0", path = "../../../../embassy-embedded-hal" }
defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-stm32/defmt",
"embassy-boot-stm32/defmt",
"embassy-sync/defmt",
]
skip-include = []

View File

@ -0,0 +1,31 @@
[package]
edition = "2021"
name = "embassy-boot-stm32l1-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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.2.0", path = "../../../../embassy-embedded-hal" }
defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-stm32/defmt",
"embassy-boot-stm32/defmt",
"embassy-sync/defmt",
]
skip-include = []

View File

@ -0,0 +1,31 @@
[package]
edition = "2021"
name = "embassy-boot-stm32l4-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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.2.0", path = "../../../../embassy-embedded-hal" }
defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-stm32/defmt",
"embassy-boot-stm32/defmt",
"embassy-sync/defmt",
]
skip-include = []

View File

@ -0,0 +1,32 @@
[package]
edition = "2021"
name = "embassy-boot-stm32wb-dfu-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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.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 }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-stm32/defmt",
"embassy-boot-stm32/defmt",
"embassy-sync/defmt",
]

View File

@ -0,0 +1,31 @@
[package]
edition = "2021"
name = "embassy-boot-stm32wl-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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.2.0", path = "../../../../embassy-embedded-hal" }
defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
[features]
defmt = [
"dep:defmt",
"dep:defmt-rtt",
"embassy-stm32/defmt",
"embassy-boot-stm32/defmt",
"embassy-sync/defmt",
]
skip-include = []

View File

@ -0,0 +1,22 @@
[package]
edition = "2021"
name = "embassy-nxp-lpc55s69-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["rt"] }
embassy-executor = { version = "0.6.2", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt"] }
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt"] }
panic-halt = "0.2.0"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = {version = "0.7.0"}
defmt = "0.3"
defmt-rtt = "0.4"
panic-probe = { version = "0.3.2", features = ["print-defmt"] }
panic-semihosting = "0.6.0"
[profile.release]
debug = 2

View File

@ -0,0 +1,37 @@
[package]
edition = "2021"
name = "embassy-nrf-rtos-trace-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[features]
default = ["log"]
log = [
"dep:log",
"embassy-sync/log",
"embassy-executor/log",
"embassy-time/log",
"embassy-nrf/log",
]
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../embassy-sync" }
embassy-executor = { version = "0.6.2", 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"
panic-probe = { version = "0.3" }
rand = { version = "0.8.4", default-features = false }
serde = { version = "1.0.136", default-features = false }
rtos-trace = "0.1.3"
systemview-target = { version = "0.1.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] }
log = { version = "0.4.17", optional = true }
[[bin]]
name = "rtos_trace"
[profile.release]
debug = 2

View File

@ -0,0 +1,20 @@
[package]
edition = "2021"
name = "embassy-nrf51-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-executor = { version = "0.6.2", 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"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7"
panic-probe = { version = "0.3", features = ["print-defmt"] }
[profile.release]
debug = 2

View File

@ -0,0 +1,24 @@
[package]
edition = "2021"
name = "embassy-nrf52810-examples"
version = "0.1.0"
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.6.2", 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"
fixed = "1.10.0"
static_cell = { version = "2" }
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

View File

@ -0,0 +1,39 @@
[package]
edition = "2021"
name = "embassy-nrf52840-examples"
version = "0.1.0"
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.6.2", 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.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"] }
embassy-net-enc28j60 = { version = "0.1.0", path = "../../embassy-net-enc28j60", features = ["defmt"] }
defmt = "0.3"
defmt-rtt = "0.4"
fixed = "1.10.0"
static_cell = { version = "2" }
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"] }
rand = { version = "0.8.4", default-features = false }
embedded-storage = "0.3.1"
usbd-hid = "0.8.1"
serde = { version = "1.0.136", default-features = false }
embedded-hal = { version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-hal-bus = { version = "0.1", features = ["async"] }
num-integer = { version = "0.1.45", default-features = false }
microfft = "0.5.0"
[profile.release]
debug = 2

View File

@ -0,0 +1,30 @@
[package]
edition = "2021"
name = "embassy-nrf5340-examples"
version = "0.1.0"
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.6.2", 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.3.0", path = "../../embassy-usb", features = ["defmt"] }
embedded-io-async = { version = "0.6.1" }
defmt = "0.3"
defmt-rtt = "0.4"
static_cell = "2"
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"] }
rand = { version = "0.8.4", default-features = false }
embedded-storage = "0.3.1"
usbd-hid = "0.8.1"
serde = { version = "1.0.136", default-features = false }
[profile.release]
debug = 2

View File

@ -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.2", 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

View File

@ -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.2", 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

View File

@ -0,0 +1,26 @@
[package]
edition = "2021"
name = "embassy-nrf9160-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-executor = { version = "0.6.2", 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"] }
embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] }
embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] }
defmt = "0.3"
defmt-rtt = "0.4"
heapless = "0.8"
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"] }
static_cell = { version = "2" }
embedded-io = "0.6.1"
embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
[profile.release]
debug = 2

View File

@ -0,0 +1,82 @@
[package]
edition = "2021"
name = "embassy-rp-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
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.6.2", 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", "rp2040"] }
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", "proto-ipv4", "proto-ipv6", "multicast"] }
embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
embassy-usb-logger = { version = "0.2.0", path = "../../embassy-usb-logger" }
cyw43 = { version = "0.2.0", path = "../../cyw43", features = ["defmt", "firmware-logs", "bluetooth"] }
cyw43-pio = { version = "0.2.0", path = "../../cyw43-pio", features = ["defmt"] }
defmt = "0.3"
defmt-rtt = "0.4"
fixed = "1.23.1"
fixed-macro = "1.2"
# for web request example
reqwless = { version = "0.13.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"
critical-section = "1.1"
panic-probe = { version = "0.3", features = ["print-defmt"] }
display-interface-spi = "0.5.0"
embedded-graphics = "0.8.1"
mipidsi = "0.8.0"
display-interface = "0.5.0"
byte-slice-cast = { version = "1.2.0", default-features = false }
smart-leds = "0.4.0"
heapless = "0.8"
usbd-hid = "0.8.1"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = "1.0"
embedded-hal-bus = { version = "0.1", features = ["async"] }
embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
embedded-storage = { version = "0.3" }
static_cell = "2.1"
portable-atomic = { version = "1.5", features = ["critical-section"] }
log = "0.4"
pio-proc = "0.2"
pio = "0.2.1"
rand = { version = "0.8.5", default-features = false }
embedded-sdmmc = "0.7.0"
bt-hci = { version = "0.1.0", default-features = false, features = ["defmt"] }
trouble-host = { version = "0.1.0", features = ["defmt", "gatt"] }
[profile.release]
debug = 2
lto = true
opt-level = 'z'
[profile.dev]
debug = 2
lto = true
opt-level = "z"
[patch.crates-io]
trouble-host = { git = "https://github.com/embassy-rs/trouble.git", rev = "4b8c0f499b34e46ca23a56e2d1640ede371722cf" }
embassy-executor = { path = "../../embassy-executor" }
embassy-sync = { path = "../../embassy-sync" }
embassy-futures = { path = "../../embassy-futures" }
embassy-time = { path = "../../embassy-time" }
embassy-time-driver = { path = "../../embassy-time-driver" }
embassy-embedded-hal = { path = "../../embassy-embedded-hal" }

View File

@ -0,0 +1,80 @@
[package]
edition = "2021"
name = "embassy-rp2350-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
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.6.2", 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", "rp235xa", "binary-info"] }
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" }
embassy-usb-logger = { version = "0.2.0", path = "../../embassy-usb-logger" }
cyw43 = { version = "0.2.0", path = "../../cyw43", features = ["defmt", "firmware-logs", "bluetooth"] }
cyw43-pio = { version = "0.2.0", path = "../../cyw43-pio", features = ["defmt"] }
defmt = "0.3"
defmt-rtt = "0.4"
fixed = "1.23.1"
fixed-macro = "1.2"
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" }
# for TB6612FNG example
tb6612fng = "1.0.0"
#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"
critical-section = "1.1"
panic-probe = { version = "0.3", features = ["print-defmt"] }
display-interface-spi = "0.5.0"
embedded-graphics = "0.8.1"
mipidsi = "0.8.0"
display-interface = "0.5.0"
byte-slice-cast = { version = "1.2.0", default-features = false }
smart-leds = "0.3.0"
heapless = "0.8"
usbd-hid = "0.8.1"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = "1.0"
embedded-hal-bus = { version = "0.1", features = ["async"] }
embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
embedded-storage = { version = "0.3" }
static_cell = "2.1"
portable-atomic = { version = "1.5", features = ["critical-section"] }
log = "0.4"
pio-proc = "0.2"
pio = "0.2.1"
rand = { version = "0.8.5", default-features = false }
embedded-sdmmc = "0.7.0"
bt-hci = { version = "0.1.0", default-features = false, features = ["defmt"] }
trouble-host = { version = "0.1.0", features = ["defmt", "gatt"] }
[profile.release]
debug = 2
[profile.dev]
lto = true
opt-level = "z"
[patch.crates-io]
trouble-host = { git = "https://github.com/embassy-rs/trouble.git", rev = "4b8c0f499b34e46ca23a56e2d1640ede371722cf" }
embassy-executor = { path = "../../embassy-executor" }
embassy-sync = { path = "../../embassy-sync" }
embassy-futures = { path = "../../embassy-futures" }
embassy-time = { path = "../../embassy-time" }
embassy-time-driver = { path = "../../embassy-time-driver" }
embassy-embedded-hal = { path = "../../embassy-embedded-hal" }

View File

@ -0,0 +1,29 @@
[package]
edition = "2021"
name = "embassy-std-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["log"] }
embassy-executor = { version = "0.6.2", 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"]}
embedded-io-async = { version = "0.6.1" }
embedded-io-adapters = { version = "0.6.1", features = ["futures-03"] }
critical-section = { version = "1.1", features = ["std"] }
async-io = "1.6.0"
env_logger = "0.9.0"
futures = { version = "0.3.17" }
log = "0.4.14"
nix = "0.26.2"
clap = { version = "3.0.0-beta.5", features = ["derive"] }
rand_core = { version = "0.6.3", features = ["std"] }
heapless = { version = "0.8", default-features = false }
static_cell = "2"
[profile.release]
debug = 2

View File

@ -0,0 +1,24 @@
[package]
edition = "2021"
name = "embassy-stm32c0-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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"
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
[profile.release]
debug = 2

View File

@ -0,0 +1,22 @@
[package]
name = "embassy-stm32f0-examples"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
[dependencies]
# Change stm32f091rc to your chip name, if necessary.
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
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.6.2", 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"] }
[profile.release]
debug = 2

View File

@ -0,0 +1,31 @@
[package]
edition = "2021"
name = "embassy-stm32f1-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
static_cell = "2.0.0"
[profile.dev]
opt-level = "s"
[profile.release]
debug = 2

View File

@ -0,0 +1,25 @@
[package]
edition = "2021"
name = "embassy-stm32f2-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
[profile.release]
debug = 2

View File

@ -0,0 +1,29 @@
[package]
edition = "2021"
name = "embassy-stm32f3-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.1"
static_cell = "2"
[profile.release]
debug = 2

View File

@ -0,0 +1,25 @@
[package]
edition = "2021"
name = "embassy-stm32f334-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.6.2", 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.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.1"
static_cell = "2"

View File

@ -0,0 +1,38 @@
[package]
edition = "2021"
name = "embassy-stm32f4-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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" }
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"
embedded-hal = "0.2.6"
embedded-hal-bus = { version = "0.2", features = ["async"] }
embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures-util = { version = "0.3.30", default-features = false }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.1"
micromath = "2.0.0"
usbd-hid = "0.8.1"
static_cell = "2"
chrono = { version = "^0.4", default-features = false}
[profile.release]
debug = 2

View File

@ -0,0 +1,22 @@
[package]
edition = "2021"
name = "embassy-stm32f469-examples"
version = "0.1.0"
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.6.2", 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"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "1.0.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
[profile.release]
debug = 2

View File

@ -0,0 +1,36 @@
[package]
edition = "2021"
name = "embassy-stm32f7-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
rand_core = "0.6.3"
critical-section = "1.1"
embedded-storage = "0.3.1"
static_cell = "2"
sha2 = { version = "0.10.8", default-features = false }
hmac = "0.12.1"
aes-gcm = {version = "0.10.3", default-features = false, features = ["aes", "heapless"] }
[profile.release]
debug = 2

View File

@ -0,0 +1,29 @@
[package]
edition = "2021"
name = "embassy-stm32g0-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
embedded-io-async = { version = "0.6.1" }
[profile.release]
debug = 2

View File

@ -0,0 +1,29 @@
[package]
edition = "2021"
name = "embassy-stm32g4-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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.8.1"
defmt = "0.3"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
embedded-can = { version = "0.4" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
static_cell = "2.0.0"
[profile.release]
debug = 2

View File

@ -0,0 +1,72 @@
[package]
edition = "2021"
name = "embassy-stm32h5-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-io-async = { version = "0.6.1" }
embedded-nal-async = "0.8.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.1"
static_cell = "2"
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,75 @@
[package]
edition = "2021"
name = "embassy-stm32h7-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.2.0", path = "../../embassy-embedded-hal" }
embassy-executor = { version = "0.6.2", 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.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-nal-async = "0.8.0"
embedded-io-async = { version = "0.6.1" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.1"
static_cell = "2"
chrono = { version = "^0.4", default-features = false }
grounded = "0.2.0"
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,61 @@
[package]
edition = "2021"
name = "embassy-stm32h735-examples"
version = "0.1.0"
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.2.0", path = "../../embassy-embedded-hal" }
embassy-executor = { version = "0.6.2", 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"
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"] }
heapless = { version = "0.8", default-features = false }
embedded-graphics = { version = "0.8.1" }
tinybmp = { version = "0.5" }
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,75 @@
[package]
edition = "2021"
name = "embassy-stm32h755cm4-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# Change stm32h755zi-cm4 to your chip name, if necessary.
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "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.2.0", path = "../../embassy-embedded-hal" }
embassy-executor = { version = "0.6.2", 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-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-nal-async = "0.8.0"
embedded-io-async = { version = "0.6.1" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.1"
static_cell = "2"
chrono = { version = "^0.4", default-features = false }
grounded = "0.2.0"
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,75 @@
[package]
edition = "2021"
name = "embassy-stm32h755cm7-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# Change stm32h743bi to your chip name, if necessary.
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] }
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-embedded-hal = { version = "0.2.0", path = "../../embassy-embedded-hal" }
embassy-executor = { version = "0.6.2", 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-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
embassy-usb = { version = "0.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-nal-async = "0.8.0"
embedded-io-async = { version = "0.6.1" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.1"
static_cell = "2"
chrono = { version = "^0.4", default-features = false }
grounded = "0.2.0"
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,74 @@
[package]
edition = "2021"
name = "embassy-stm32h7b0-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "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.2.0", path = "../../embassy-embedded-hal" }
embassy-executor = { version = "0.6.2", 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.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-nal-async = "0.8.0"
embedded-io-async = { version = "0.6.1" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.1"
static_cell = "2"
chrono = { version = "^0.4", default-features = false }
grounded = "0.2.0"
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,73 @@
[package]
edition = "2021"
name = "embassy-stm32h7rs-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-nal-async = "0.8.0"
embedded-io-async = { version = "0.6.1" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.1"
static_cell = "2"
chrono = { version = "^0.4", default-features = false }
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 3 # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

View File

@ -0,0 +1,30 @@
[package]
edition = "2021"
name = "embassy-stm32l0-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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"
embedded-storage = "0.3.1"
embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
embedded-hal = "0.2.6"
static_cell = { version = "2" }
portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
[profile.release]
debug = 2

View File

@ -0,0 +1,26 @@
[package]
edition = "2021"
name = "embassy-stm32l1-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.6.2", 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.3.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
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"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
embedded-storage = "0.3.1"
[profile.release]
debug = 2

View File

@ -0,0 +1,39 @@
[package]
edition = "2021"
name = "embassy-stm32l4-examples"
version = "0.1.1"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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" }
embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
embedded-io = { version = "0.6.0", features = ["defmt-03"] }
defmt = "0.3"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-hal-bus = { version = "0.1", features = ["async"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
chrono = { version = "^0.4", default-features = false }
rand = { version = "0.8.5", default-features = false }
static_cell = "2"
micromath = "2.0.0"
[profile.release]
debug = 2

View File

@ -0,0 +1,35 @@
[package]
edition = "2021"
name = "embassy-stm32l5-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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.8.1"
defmt = "0.3"
defmt-rtt = "0.4"
panic-probe = { version = "0.3", features = ["print-defmt"] }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
heapless = { version = "0.8", default-features = false }
rand_core = { version = "0.6.3", default-features = false }
embedded-io-async = { version = "0.6.1" }
static_cell = "2"
[profile.release]
debug = 2
[[bin]]
name = "stop"
default-features = ["embassy-stm32/low-power"]

View File

@ -0,0 +1,29 @@
[package]
edition = "2021"
name = "embassy-stm32u0-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
micromath = "2.0.0"
chrono = { version = "0.4.38", default-features = false }
[profile.release]
debug = 2

View File

@ -0,0 +1,34 @@
[package]
edition = "2021"
name = "embassy-stm32u5-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# Change stm32u5g9zj to your chip name, if necessary.
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] }
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.6.2", 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"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
embedded-graphics = { version = "0.8.1" }
tinybmp = { version = "0.6.0" }
micromath = "2.0.0"
[features]
## Use secure registers when TrustZone is enabled
trustzone-secure = ["embassy-stm32/trustzone-secure"]
[profile.release]
debug = 2

View File

@ -0,0 +1,56 @@
[package]
edition = "2021"
name = "embassy-stm32wb-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# Change stm32wb55rg to your chip name in both dependencies, if necessary.
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.6.2", 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"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
static_cell = "2"
[features]
default = ["ble", "mac"]
mac = ["embassy-stm32-wpan/mac", "dep:embassy-net"]
ble = ["embassy-stm32-wpan/ble"]
[[bin]]
name = "tl_mbox_ble"
required-features = ["ble"]
[[bin]]
name = "tl_mbox_mac"
required-features = ["mac"]
[[bin]]
name = "mac_ffd"
required-features = ["mac"]
[[bin]]
name = "mac_ffd_net"
required-features = ["mac"]
[[bin]]
name = "eddystone_beacon"
required-features = ["ble"]
[[bin]]
name = "gatt_server"
required-features = ["ble"]
[profile.release]
debug = 2

View File

@ -0,0 +1,25 @@
[package]
edition = "2021"
name = "embassy-stm32wba-examples"
version = "0.1.0"
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.6.2", 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"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
static_cell = "2"
[profile.release]
debug = 2

View File

@ -0,0 +1,27 @@
[package]
edition = "2021"
name = "embassy-stm32wl-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
# 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.6.2", 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"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
embedded-storage = "0.3.1"
panic-probe = { version = "0.3", features = ["print-defmt"] }
heapless = { version = "0.8", default-features = false }
chrono = { version = "^0.4", default-features = false }
[profile.release]
debug = 2

View File

@ -0,0 +1,21 @@
[package]
edition = "2021"
name = "embassy-wasm-example"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[lib]
crate-type = ["cdylib"]
[dependencies]
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["log"] }
embassy-executor = { version = "0.6.2", 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"
web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] }
log = "0.4.11"
[profile.release]
debug = 2

View File

@ -0,0 +1,114 @@
[package]
edition = "2021"
name = "embassy-nrf-examples"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
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.6.2", 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"] }
embassy-net-enc28j60 = { version = "0.1.0", path = "../../embassy-net-enc28j60", features = ["defmt"] }
embedded-hal-async = { version = "1.0" }
embedded-hal-bus = { version = "0.1", features = ["async"] }
static_cell = "2"
perf-client = { path = "../perf-client" }
defmt = "0.3"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
portable-atomic = { version = "1.6.0" }
[features]
nrf51422 = ["embassy-nrf/nrf51", "portable-atomic/unsafe-assume-single-core"]
nrf52832 = ["embassy-nrf/nrf52832", "easydma"]
nrf52833 = ["embassy-nrf/nrf52833", "easydma", "two-uarts"]
nrf52840 = ["embassy-nrf/nrf52840", "easydma", "two-uarts"]
nrf5340 = ["embassy-nrf/nrf5340-app-s", "easydma", "two-uarts"]
nrf9160 = ["embassy-nrf/nrf9160-s", "easydma", "two-uarts"]
easydma = []
two-uarts = []
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = "fat"
opt-level = 's'
overflow-checks = false
# BEGIN TESTS
# Generated by gen_test.py. DO NOT EDIT.
[[bin]]
name = "buffered_uart"
path = "src/bin/buffered_uart.rs"
required-features = [ "easydma",]
[[bin]]
name = "buffered_uart_full"
path = "src/bin/buffered_uart_full.rs"
required-features = [ "easydma",]
[[bin]]
name = "buffered_uart_halves"
path = "src/bin/buffered_uart_halves.rs"
required-features = [ "two-uarts",]
[[bin]]
name = "buffered_uart_spam"
path = "src/bin/buffered_uart_spam.rs"
required-features = [ "two-uarts",]
[[bin]]
name = "ethernet_enc28j60_perf"
path = "src/bin/ethernet_enc28j60_perf.rs"
required-features = [ "nrf52840",]
[[bin]]
name = "gpio"
path = "src/bin/gpio.rs"
required-features = []
[[bin]]
name = "gpiote"
path = "src/bin/gpiote.rs"
required-features = []
[[bin]]
name = "spim"
path = "src/bin/spim.rs"
required-features = [ "easydma",]
[[bin]]
name = "timer"
path = "src/bin/timer.rs"
required-features = []
[[bin]]
name = "uart_halves"
path = "src/bin/uart_halves.rs"
required-features = [ "two-uarts",]
[[bin]]
name = "uart_split"
path = "src/bin/uart_split.rs"
required-features = [ "easydma",]
[[bin]]
name = "wifi_esp_hosted_perf"
path = "src/bin/wifi_esp_hosted_perf.rs"
required-features = [ "nrf52840",]
# END TESTS

View File

@ -0,0 +1,46 @@
[package]
edition = "2021"
name = "embassy-riscv-tests"
version = "0.1.0"
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.6.2", 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"
riscv = { version = "0.11.1", features = ["critical-section-single-hart"] }
[profile.dev]
debug = 2
debug-assertions = true
opt-level = 's'
overflow-checks = true
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = "fat"
opt-level = 's'
overflow-checks = false
# do not optimize proc-macro crates = faster builds from scratch
[profile.dev.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
[profile.release.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false

View File

@ -0,0 +1,68 @@
[package]
edition = "2021"
name = "embassy-rp-tests"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
teleprobe-meta = "1.1"
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.6.2", 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", "rp2040"] }
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.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" }
defmt = "0.3.0"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6" }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-hal-bus = { version = "0.1", features = ["async"] }
panic-probe = { version = "0.3.0", features = ["print-defmt"] }
embedded-io-async = { version = "0.6.1" }
embedded-storage = { version = "0.3" }
static_cell = "2"
portable-atomic = { version = "1.5", features = ["critical-section"] }
pio = "0.2"
pio-proc = "0.2"
rand = { version = "0.8.5", default-features = false }
[profile.dev]
debug = 2
debug-assertions = true
opt-level = 's'
overflow-checks = true
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = "fat"
opt-level = 's'
overflow-checks = false
# do not optimize proc-macro crates = faster builds from scratch
[profile.dev.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
[profile.release.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false

View File

@ -0,0 +1,235 @@
[package]
edition = "2021"
name = "embassy-stm32-tests"
version = "0.1.0"
license = "MIT OR Apache-2.0"
autobins = false
[features]
stm32c031c6 = ["embassy-stm32/stm32c031c6", "cm0", "not-gpdma"]
stm32f103c8 = ["embassy-stm32/stm32f103c8", "spi-v1", "not-gpdma"]
stm32f207zg = ["embassy-stm32/stm32f207zg", "spi-v1", "chrono", "not-gpdma", "eth", "rng"]
stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"]
stm32f429zi = ["embassy-stm32/stm32f429zi", "spi-v1", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"]
stm32f446re = ["embassy-stm32/stm32f446re", "spi-v1", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"]
stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"]
stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac", "ucpd"]
stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan", "cordic"]
stm32h563zi = ["embassy-stm32/stm32h563zi", "spi-v345", "chrono", "eth", "rng", "fdcan", "hash", "cordic", "stop"]
stm32h753zi = ["embassy-stm32/stm32h753zi", "spi-v345", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"]
stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "spi-v345", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan", "hash", "cryp"]
stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "spi-v345", "not-gpdma", "rng", "fdcan"]
stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"]
stm32l152re = ["embassy-stm32/stm32l152re", "spi-v1", "chrono", "not-gpdma"]
stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"]
stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma", "rng", "hash"]
stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma", "rng"]
stm32l552ze = ["embassy-stm32/stm32l552ze", "not-gpdma", "rng", "hash"]
stm32u585ai = ["embassy-stm32/stm32u585ai", "spi-v345", "chrono", "rng", "hash", "cordic"]
stm32u5a5zj = ["embassy-stm32/stm32u5a5zj", "spi-v345", "chrono", "rng", "hash"] # FIXME: cordic test cause it crash
stm32wb55rg = ["embassy-stm32/stm32wb55rg", "chrono", "not-gpdma", "ble", "mac" , "rng"]
stm32wba52cg = ["embassy-stm32/stm32wba52cg", "spi-v345", "chrono", "rng", "hash"]
stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"]
stm32f091rc = ["embassy-stm32/stm32f091rc", "cm0", "not-gpdma", "chrono"]
stm32h503rb = ["embassy-stm32/stm32h503rb", "spi-v345", "rng", "stop"]
stm32h7s3l8 = ["embassy-stm32/stm32h7s3l8", "spi-v345", "rng", "cordic", "hash"] # TODO: fdcan crashes, cryp dma hangs.
stm32u083rc = ["embassy-stm32/stm32u083rc", "cm0", "rng", "chrono"]
spi-v1 = []
spi-v345 = []
cryp = []
hash = []
eth = ["embassy-executor/task-arena-size-16384"]
rng = []
sdmmc = []
stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"]
chrono = ["embassy-stm32/chrono", "dep:chrono"]
can = []
fdcan = []
ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"]
embassy-stm32-wpan = []
not-gpdma = []
dac = []
ucpd = []
cordic = ["dep:num-traits"]
cm0 = ["portable-atomic/unsafe-assume-single-core"]
[dependencies]
teleprobe-meta = "1"
embassy-sync = { version = "0.6.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.6.2", 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"] }
embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] }
perf-client = { path = "../perf-client" }
defmt = "0.3.0"
defmt-rtt = "0.4"
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-hal = "0.2.6"
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-can = { version = "0.4" }
micromath = "2.0.0"
panic-probe = { version = "0.3.0", features = ["print-defmt"] }
rand_core = { version = "0.6", default-features = false }
rand_chacha = { version = "0.3", default-features = false }
static_cell = "2"
portable-atomic = { version = "1.5", features = [] }
chrono = { version = "^0.4", default-features = false, optional = true}
sha2 = { version = "0.10.8", default-features = false }
hmac = "0.12.1"
aes-gcm = {version = "0.10.3", default-features = false, features = ["aes", "heapless"] }
num-traits = {version="0.2", default-features = false,features = ["libm"], optional = true}
# BEGIN TESTS
# Generated by gen_test.py. DO NOT EDIT.
[[bin]]
name = "can"
path = "src/bin/can.rs"
required-features = [ "can",]
[[bin]]
name = "cordic"
path = "src/bin/cordic.rs"
required-features = [ "rng", "cordic",]
[[bin]]
name = "cryp"
path = "src/bin/cryp.rs"
required-features = [ "cryp",]
[[bin]]
name = "dac"
path = "src/bin/dac.rs"
required-features = [ "dac",]
[[bin]]
name = "dac_l1"
path = "src/bin/dac_l1.rs"
required-features = [ "stm32l152re",]
[[bin]]
name = "eth"
path = "src/bin/eth.rs"
required-features = [ "eth",]
[[bin]]
name = "fdcan"
path = "src/bin/fdcan.rs"
required-features = [ "fdcan",]
[[bin]]
name = "gpio"
path = "src/bin/gpio.rs"
required-features = []
[[bin]]
name = "hash"
path = "src/bin/hash.rs"
required-features = [ "hash",]
[[bin]]
name = "rng"
path = "src/bin/rng.rs"
required-features = [ "rng",]
[[bin]]
name = "rtc"
path = "src/bin/rtc.rs"
required-features = [ "chrono",]
[[bin]]
name = "sdmmc"
path = "src/bin/sdmmc.rs"
required-features = [ "sdmmc",]
[[bin]]
name = "spi"
path = "src/bin/spi.rs"
required-features = []
[[bin]]
name = "spi_dma"
path = "src/bin/spi_dma.rs"
required-features = []
[[bin]]
name = "stop"
path = "src/bin/stop.rs"
required-features = [ "stop", "chrono",]
[[bin]]
name = "timer"
path = "src/bin/timer.rs"
required-features = []
[[bin]]
name = "ucpd"
path = "src/bin/ucpd.rs"
required-features = [ "ucpd",]
[[bin]]
name = "usart"
path = "src/bin/usart.rs"
required-features = []
[[bin]]
name = "usart_dma"
path = "src/bin/usart_dma.rs"
required-features = []
[[bin]]
name = "usart_rx_ringbuffered"
path = "src/bin/usart_rx_ringbuffered.rs"
required-features = [ "not-gpdma",]
[[bin]]
name = "wpan_ble"
path = "src/bin/wpan_ble.rs"
required-features = [ "ble",]
[[bin]]
name = "wpan_mac"
path = "src/bin/wpan_mac.rs"
required-features = [ "mac",]
# END TESTS
[profile.dev]
debug = 2
debug-assertions = true
opt-level = 's'
overflow-checks = true
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = "fat"
opt-level = 's'
overflow-checks = false
# do not optimize proc-macro crates = faster builds from scratch
[profile.dev.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
[profile.release.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false

View File

@ -0,0 +1,189 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bincode"
version = "2.0.0-rc.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95"
dependencies = [
"bincode_derive",
"serde",
]
[[package]]
name = "bincode_derive"
version = "2.0.0-rc.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c"
dependencies = [
"virtue",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "defmt"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0"
dependencies = [
"bitflags",
"defmt-macros",
]
[[package]]
name = "defmt-macros"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb"
dependencies = [
"defmt-parser",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "defmt-parser"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f"
dependencies = [
"thiserror",
]
[[package]]
name = "ledisa"
version = "0.1.0"
dependencies = [
"bincode",
"defmt",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "virtue"
version = "0.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314"

View File

@ -0,0 +1,16 @@
[package]
name = "ledisa"
version = "0.1.0"
edition = "2021"
[dependencies]
bincode = { version = "2.0.0-rc.3", default-features = false, features = [
"alloc",
"derive",
] }
defmt = "0.3"
[features]
default = ["std"]
std = []
alloc = []

View File

@ -0,0 +1,32 @@
#![no_std]
extern crate alloc;
use alloc::vec;
use alloc::vec::Vec;
use bincode::{config, Decode, Encode};
#[derive(Copy, Clone, Encode, Decode, PartialEq, Debug)]
pub struct Led {
pub r: u8,
pub g: u8,
pub b: u8,
}
#[derive(Clone, Encode, Decode, PartialEq, Debug)]
pub struct LedStrip {
pub leds: Vec<Led>,
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(size: usize, r: u8, g: u8, b: u8) -> LedStrip {
let led_vec = vec![Led { r, g, b }; size];
// for i in 0..99 {
// led_vec[i] = Led{ r: i as u8 + 2, g: i as u8 + 13, b: i as u8 + 33 };
// }
LedStrip { leds: led_vec }
}
}

View File

@ -0,0 +1 @@
/target

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,400 @@
#![no_std]
#![no_main]
use assign_resources::assign_resources;
use bincode::config::Configuration;
use bincode::Decode;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::{Executor, InterruptExecutor, Spawner};
use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt;
use embassy_rp::interrupt::{InterruptExt, Priority};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::spi::{Phase, Polarity, Spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_time::Timer;
//use embedded_nal_async::TcpConnect;
//use embedded_nal_async::stack::tcp::TcpConnect;
use embedded_nal_async::TcpConnect;
use rand::RngCore;
use smart_leds::RGB8;
use static_cell::StaticCell;
use ws2812_async::{ColorOrder, Ws2812};
use {defmt_rtt as _, panic_probe as _};
use rust_mqtt::{
client::{client::MqttClient, client_config::ClientConfig},
utils::rng_generator::CountingRng,
};
//pub type RGB8 = RGB<u8>;
use {defmt_rtt as _, panic_probe as _};
// after observing somewhat jumpy behavior of the neopixel task, I decided to set the scheduler and orhestrator to high priority
// hight priority runs on interrupt
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
// low priority runs in thread-mode
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
#[global_allocator]
static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new();
extern crate alloc;
#[interrupt]
unsafe fn SWI_IRQ_1() {
EXECUTOR_HIGH.on_interrupt()
}
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
const WIFI_NETWORK: &str = "getlitfam";
const WIFI_PASSWORD: &str = "getitlitmafam";
const CLIENT_ID: &str = "pico-495f6297-b962-4266-9c00-74138ae5a1f1";
const TOPIC: &str = "hello";
const NUM_LEDS: usize = 100;
static CHANNEL: embassy_sync::channel::Channel<ThreadModeRawMutex, LedStrip, 64> =
embassy_sync::channel::Channel::new();
#[embassy_executor::task]
async fn cyw43_task(
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
runner.run().await
}
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
runner.run().await
}
assign_resources! {
led_peripheral: LedPeripheral {
inner_spi: SPI1,
clk_pin: PIN_14, // this is just a dummy pin, the neopixel uses only the mosi pin
mosi_pin: PIN_15,
tx_dma_ch: DMA_CH1,
},
wifi: WifiResources {
pwr_pin: PIN_23,
cs_pin: PIN_25,
pio_sm: PIO0,
dio_pin: PIN_24,
clk_pin: PIN_29,
dma_ch: DMA_CH0,
},
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Main thread!");
let p = embassy_rp::init(Default::default());
let r = split_resources!(p);
interrupt::SWI_IRQ_1.set_priority(Priority::P2);
let executor = EXECUTOR_LOW.init(Executor::new());
executor.run(|spawner| {
// update the RTC
spawner.spawn(run_mqtt(spawner, r.wifi)).unwrap();
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
spawn_core1(
p.CORE1,
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1
.run(|spawner| unwrap!(spawner.spawn(led_ctrl_core1_task(r.led_peripheral))));
},
);
});
}
#[embassy_executor::task]
pub async fn run_mqtt(spawner: Spawner, r: WifiResources) {
let mut rng = RoscRng;
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
info!("init wifi");
let pwr = Output::new(r.pwr_pin, Level::Low);
let cs = Output::new(r.cs_pin, Level::High);
let mut pio = Pio::new(r.pio_sm, Irqs);
let spi = PioSpi::new(
&mut pio.common,
pio.sm0,
pio.irq0,
cs,
r.dio_pin,
r.clk_pin,
r.dma_ch,
);
static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;
control
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
let config = Config::dhcpv4(Default::default());
// Use static IP configuration instead of DHCP
//let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = rng.next_u64();
// Init network stack
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
let (stack, runner) = embassy_net::new(
net_device,
config,
RESOURCES.init(StackResources::new()),
seed,
);
unwrap!(spawner.spawn(net_task(runner)));
loop {
match control
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
.await
{
Ok(_) => break,
Err(err) => {
info!("join failed with status={}", err.status);
}
}
}
// Wait for DHCP, not necessary when using static IP
info!("waiting for DHCP...");
while !stack.is_config_up() {
Timer::after_millis(100).await;
}
info!("DHCP is now up!");
info!("waiting for link up...");
while !stack.is_link_up() {
Timer::after_millis(500).await;
}
info!("Link is up!");
info!("waiting for stack to be up...");
stack.wait_config_up().await;
info!("Stack is up!");
let tcp_state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let tcp_client = TcpClient::new(stack, &tcp_state);
let addr = embedded_nal_async::SocketAddr::new(
embedded_nal_async::Ipv4Addr::new(10, 42, 0, 1).into(),
1883,
);
// let connection = embedded_nal::TcpStream::connect(addr)
// .await
// .map_err(|_| ReasonCode::NetworkError)
// .unwrap();
//let connection = FromTokio::<TcpStream>::new(connection);
let mut config = ClientConfig::new(
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
CountingRng(20000),
);
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0);
config.add_client_id(CLIENT_ID);
config.keep_alive = u16::MAX;
// config.add_username(USERNAME);
// config.add_password(PASSWORD);
config.max_packet_size = 400;
let mut recv_buffer = [0; 400];
let mut write_buffer = [0; 400];
//let r = tcp_client.connect(addr).await;
let r;
loop {
match tcp_client.connect(addr).await {
Ok(rp) => {
info!("Attempting to connect to mqtt broker");
r = rp;
break;
}
Err(err) => {
info!("Failed to join broker: {}. Trying again!", err);
Timer::after_millis(100).await;
}
};
}
let mut client: MqttClient<
'_,
embassy_net::tcp::client::TcpConnection<'_, 1, 1024, 1024>,
5,
CountingRng,
> = MqttClient::<_, 5, _>::new(r, &mut write_buffer, 512, &mut recv_buffer, 512, config);
loop {
match client.connect_to_broker().await {
Ok(_) => {
info!("CAT Connected to broker");
break;
}
Err(err) => {
info!("DOG connect_to_broker failed with status={}", err);
}
}
}
loop {
match client.subscribe_to_topic(TOPIC).await {
Ok(_) => {
info!("CAT subscribed to topic");
break;
}
Err(err) => {
info!("DOG subscribe_to_topic failed with status={}", err);
}
}
}
let mut old_msg = LedStrip::new(0);
loop {
info!("[RECEIVER] Waiting for new message");
let msg = client.receive_message().await;
info!("[RECEIVER] Received msg: {}", msg);
if msg.is_ok() {
let message = msg.unwrap();
info!("[RECEIVER] message has size: {}", message.1.len());
match bincode::decode_from_slice::<LedStrip, Configuration>(
message.1,
bincode::config::standard(),
) {
Ok(decoded) => {
if old_msg != decoded.0 {
CHANNEL.send(decoded.0.clone()).await;
old_msg = decoded.0;
info!("[RECEIVER] Sent message");
}
}
Err(_e) => {
info!("DOG");
}
}
} else {
warn!("[RECEIVER] Could not get message with error: {}", msg.err());
}
//Timer::after(Duration::from_secs(2)).await;
}
}
#[embassy_executor::task]
async fn led_ctrl_core1_task(led_peripheral: LedPeripheral) {
info!("Hello from core 1");
let mut current_ledstrip = LedStrip::new(0);
// Spi configuration for the neopixel
let mut spi_config = embassy_rp::spi::Config::default();
spi_config.frequency = 3_800_000;
spi_config.phase = Phase::CaptureOnFirstTransition;
spi_config.polarity = Polarity::IdleLow;
// let spi = embassy_rp::spi::Spi::new_txonly(led_peripheral.inner_spi, led_peripheral.clk_pin, led_peripheral.mosi_pin, led_peripheral.tx_dma_ch, spi_config);
let spi = Spi::new_txonly(
led_peripheral.inner_spi,
led_peripheral.clk_pin,
led_peripheral.mosi_pin,
led_peripheral.tx_dma_ch,
spi_config,
);
let mut np: Ws2812<_, { 12 * NUM_LEDS }> = Ws2812::new(spi);
np.set_color_order(ColorOrder::GRB);
let mut data = [RGB8::default(); NUM_LEDS];
for led in data.iter_mut().step_by(1) {
led.r = 250; // blue
led.g = 150; // red
led.b = 0; // green
}
//np.write(empty.iter().cloned()).await.ok();
//np.write(data.iter().cloned()).await.ok();
let mut rgb_arr: [RGB8; NUM_LEDS] = [RGB8::new(0, 0, 0); NUM_LEDS];
loop {
let rc = CHANNEL.receive().await;
info!("OCTOPUS yyyy");
if current_ledstrip != rc {
info!("OCTOPUS got a new led strip");
for i in 0..rc.leds.len() {
rgb_arr[i].r = rc.leds[i].r;
rgb_arr[i].g = rc.leds[i].g;
rgb_arr[i].b = rc.leds[i].b;
}
current_ledstrip = rc.clone();
info!("writing led!");
np.write(rgb_arr.iter().cloned()).await.ok();
// Timer::after(Duration::from_millis(0)).await;
}
}
}
#[derive(Debug, Decode, Clone, Copy, PartialEq)]
struct Led {
r: u8,
g: u8,
b: u8,
}
#[derive(Clone, Debug, Decode, PartialEq)]
pub struct LedStrip {
leds: [Led; NUM_LEDS],
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(_r: u8) -> Self {
let arr: [Led; NUM_LEDS] = [Led { r: 0, g: 0, b: 0 }; NUM_LEDS];
LedStrip { leds: arr }
}
}

View File

@ -0,0 +1,400 @@
#![no_std]
#![no_main]
use assign_resources::assign_resources;
use bincode::config::Configuration;
use bincode::Decode;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::{Executor, InterruptExecutor, Spawner};
use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt;
use embassy_rp::interrupt::{InterruptExt, Priority};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::spi::{Phase, Polarity, Spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_time::Timer;
//use embedded_nal_async::TcpConnect;
//use embedded_nal_async::stack::tcp::TcpConnect;
use embedded_nal_async::TcpConnect;
use rand::RngCore;
use smart_leds::RGB8;
use static_cell::StaticCell;
use ws2812_async::{ColorOrder, Ws2812};
use {defmt_rtt as _, panic_probe as _};
use rust_mqtt::{
client::{client::MqttClient, client_config::ClientConfig},
utils::rng_generator::CountingRng,
};
//pub type RGB8 = RGB<u8>;
use {defmt_rtt as _, panic_probe as _};
// after observing somewhat jumpy behavior of the neopixel task, I decided to set the scheduler and orhestrator to high priority
// hight priority runs on interrupt
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
// low priority runs in thread-mode
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
#[global_allocator]
static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new();
extern crate alloc;
#[interrupt]
unsafe fn SWI_IRQ_1() {
EXECUTOR_HIGH.on_interrupt()
}
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
const WIFI_NETWORK: &str = "cat";
const WIFI_PASSWORD: &str = "catcat123cat";
const CLIENT_ID: &str = "pico-495f6297-b962-4266-9c00-74138ae5a1f1";
const TOPIC: &str = "hello";
const NUM_LEDS: usize = 100;
static CHANNEL: embassy_sync::channel::Channel<ThreadModeRawMutex, LedStrip, 64> =
embassy_sync::channel::Channel::new();
#[embassy_executor::task]
async fn cyw43_task(
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
runner.run().await
}
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
runner.run().await
}
assign_resources! {
led_peripheral: LedPeripheral {
inner_spi: SPI1,
clk_pin: PIN_14, // this is just a dummy pin, the neopixel uses only the mosi pin
mosi_pin: PIN_15,
tx_dma_ch: DMA_CH1,
},
wifi: WifiResources {
pwr_pin: PIN_23,
cs_pin: PIN_25,
pio_sm: PIO0,
dio_pin: PIN_24,
clk_pin: PIN_29,
dma_ch: DMA_CH0,
},
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Main thread!");
let p = embassy_rp::init(Default::default());
let r = split_resources!(p);
interrupt::SWI_IRQ_1.set_priority(Priority::P2);
let executor = EXECUTOR_LOW.init(Executor::new());
executor.run(|spawner| {
// update the RTC
spawner.spawn(run_mqtt(spawner, r.wifi)).unwrap();
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
spawn_core1(
p.CORE1,
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1
.run(|spawner| unwrap!(spawner.spawn(led_ctrl_core1_task(r.led_peripheral))));
},
);
});
}
#[embassy_executor::task]
pub async fn run_mqtt(spawner: Spawner, r: WifiResources) {
let mut rng = RoscRng;
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
info!("init wifi");
let pwr = Output::new(r.pwr_pin, Level::Low);
let cs = Output::new(r.cs_pin, Level::High);
let mut pio = Pio::new(r.pio_sm, Irqs);
let spi = PioSpi::new(
&mut pio.common,
pio.sm0,
pio.irq0,
cs,
r.dio_pin,
r.clk_pin,
r.dma_ch,
);
static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;
control
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
let config = Config::dhcpv4(Default::default());
// Use static IP configuration instead of DHCP
//let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = rng.next_u64();
// Init network stack
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
let (stack, runner) = embassy_net::new(
net_device,
config,
RESOURCES.init(StackResources::new()),
seed,
);
unwrap!(spawner.spawn(net_task(runner)));
loop {
match control
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
.await
{
Ok(_) => break,
Err(err) => {
info!("join failed with status={}", err.status);
}
}
}
// Wait for DHCP, not necessary when using static IP
info!("waiting for DHCP...");
while !stack.is_config_up() {
Timer::after_millis(100).await;
}
info!("DHCP is now up!");
info!("waiting for link up...");
while !stack.is_link_up() {
Timer::after_millis(500).await;
}
info!("Link is up!");
info!("waiting for stack to be up...");
stack.wait_config_up().await;
info!("Stack is up!");
let tcp_state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let tcp_client = TcpClient::new(stack, &tcp_state);
let addr = embedded_nal_async::SocketAddr::new(
embedded_nal_async::Ipv4Addr::new(192, 168, 0, 100).into(),
1883,
);
// let connection = embedded_nal::TcpStream::connect(addr)
// .await
// .map_err(|_| ReasonCode::NetworkError)
// .unwrap();
//let connection = FromTokio::<TcpStream>::new(connection);
let mut config = ClientConfig::new(
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
CountingRng(20000),
);
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0);
config.add_client_id(CLIENT_ID);
config.keep_alive = u16::MAX;
// config.add_username(USERNAME);
// config.add_password(PASSWORD);
config.max_packet_size = 400;
let mut recv_buffer = [0; 400];
let mut write_buffer = [0; 400];
//let r = tcp_client.connect(addr).await;
let r;
loop {
match tcp_client.connect(addr).await {
Ok(rp) => {
info!("Attempting to connect to mqtt broker");
r = rp;
break;
}
Err(err) => {
info!("Failed to join broker: {}. Trying again!", err);
Timer::after_millis(100).await;
}
};
}
let mut client: MqttClient<
'_,
embassy_net::tcp::client::TcpConnection<'_, 1, 1024, 1024>,
5,
CountingRng,
> = MqttClient::<_, 5, _>::new(r, &mut write_buffer, 512, &mut recv_buffer, 512, config);
loop {
match client.connect_to_broker().await {
Ok(_) => {
info!("CAT Connected to broker");
break;
}
Err(err) => {
info!("DOG connect_to_broker failed with status={}", err);
}
}
}
loop {
match client.subscribe_to_topic(TOPIC).await {
Ok(_) => {
info!("CAT subscribed to topic");
break;
}
Err(err) => {
info!("DOG subscribe_to_topic failed with status={}", err);
}
}
}
let mut old_msg = LedStrip::new(0);
loop {
info!("[RECEIVER] Waiting for new message");
let msg = client.receive_message().await;
info!("[RECEIVER] Received msg: {}", msg);
if msg.is_ok() {
let message = msg.unwrap();
info!("[RECEIVER] message has size: {}", message.1.len());
match bincode::decode_from_slice::<LedStrip, Configuration>(
message.1,
bincode::config::standard(),
) {
Ok(decoded) => {
if old_msg != decoded.0 {
CHANNEL.send(decoded.0.clone()).await;
old_msg = decoded.0;
info!("[RECEIVER] Sent message");
}
}
Err(_e) => {
info!("DOG");
}
}
} else {
warn!("[RECEIVER] Could not get message with error: {}", msg.err());
}
//Timer::after(Duration::from_secs(2)).await;
}
}
#[embassy_executor::task]
async fn led_ctrl_core1_task(led_peripheral: LedPeripheral) {
info!("Hello from core 1");
let mut current_ledstrip = LedStrip::new(0);
// Spi configuration for the neopixel
let mut spi_config = embassy_rp::spi::Config::default();
spi_config.frequency = 3_800_000;
spi_config.phase = Phase::CaptureOnFirstTransition;
spi_config.polarity = Polarity::IdleLow;
// let spi = embassy_rp::spi::Spi::new_txonly(led_peripheral.inner_spi, led_peripheral.clk_pin, led_peripheral.mosi_pin, led_peripheral.tx_dma_ch, spi_config);
let spi = Spi::new_txonly(
led_peripheral.inner_spi,
led_peripheral.clk_pin,
led_peripheral.mosi_pin,
led_peripheral.tx_dma_ch,
spi_config,
);
let mut np: Ws2812<_, { 12 * NUM_LEDS }> = Ws2812::new(spi);
np.set_color_order(ColorOrder::GRB);
let mut data = [RGB8::default(); NUM_LEDS];
for led in data.iter_mut().step_by(1) {
led.r = 250; // blue
led.g = 150; // red
led.b = 0; // green
}
//np.write(empty.iter().cloned()).await.ok();
//np.write(data.iter().cloned()).await.ok();
let mut rgb_arr: [RGB8; NUM_LEDS] = [RGB8::new(0, 0, 0); NUM_LEDS];
loop {
let rc = CHANNEL.receive().await;
info!("OCTOPUS yyyy");
if current_ledstrip != rc {
info!("OCTOPUS got a new led strip");
for i in 0..rc.leds.len() {
rgb_arr[i].r = rc.leds[i].r;
rgb_arr[i].g = rc.leds[i].g;
rgb_arr[i].b = rc.leds[i].b;
}
current_ledstrip = rc.clone();
info!("writing led!");
np.write(rgb_arr.iter().cloned()).await.ok();
// Timer::after(Duration::from_millis(0)).await;
}
}
}
#[derive(Debug, Decode, Clone, Copy, PartialEq)]
struct Led {
r: u8,
g: u8,
b: u8,
}
#[derive(Clone, Debug, Decode, PartialEq)]
pub struct LedStrip {
leds: [Led; NUM_LEDS],
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(_r: u8) -> Self {
let arr: [Led; NUM_LEDS] = [Led { r: 0, g: 0, b: 0 }; NUM_LEDS];
LedStrip { leds: arr }
}
}

View File

@ -0,0 +1,400 @@
#![no_std]
#![no_main]
use assign_resources::assign_resources;
use bincode::config::Configuration;
use bincode::Decode;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::{Executor, InterruptExecutor, Spawner};
use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt;
use embassy_rp::interrupt::{InterruptExt, Priority};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::spi::{Phase, Polarity, Spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_time::Timer;
//use embedded_nal_async::TcpConnect;
//use embedded_nal_async::stack::tcp::TcpConnect;
use embedded_nal_async::TcpConnect;
use rand::RngCore;
use smart_leds::RGB8;
use static_cell::StaticCell;
use ws2812_async::{ColorOrder, Ws2812};
use {defmt_rtt as _, panic_probe as _};
use rust_mqtt::{
client::{client::MqttClient, client_config::ClientConfig},
utils::rng_generator::CountingRng,
};
//pub type RGB8 = RGB<u8>;
use {defmt_rtt as _, panic_probe as _};
// after observing somewhat jumpy behavior of the neopixel task, I decided to set the scheduler and orhestrator to high priority
// hight priority runs on interrupt
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
// low priority runs in thread-mode
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
#[global_allocator]
static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new();
extern crate alloc;
#[interrupt]
unsafe fn SWI_IRQ_1() {
EXECUTOR_HIGH.on_interrupt()
}
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
const WIFI_NETWORK: &str = "cat";
const WIFI_PASSWORD: &str = "catcat123cat";
const CLIENT_ID: &str = "pico-495f6297-b962-4266-9c00-74138ae5a1f1";
const TOPIC: &str = "hello";
const NUM_LEDS: usize = 100;
static CHANNEL: embassy_sync::channel::Channel<ThreadModeRawMutex, LedStrip, 64> =
embassy_sync::channel::Channel::new();
#[embassy_executor::task]
async fn cyw43_task(
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
runner.run().await
}
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
runner.run().await
}
assign_resources! {
led_peripheral: LedPeripheral {
inner_spi: SPI1,
clk_pin: PIN_14, // this is just a dummy pin, the neopixel uses only the mosi pin
mosi_pin: PIN_15,
tx_dma_ch: DMA_CH1,
},
wifi: WifiResources {
pwr_pin: PIN_23,
cs_pin: PIN_25,
pio_sm: PIO0,
dio_pin: PIN_24,
clk_pin: PIN_29,
dma_ch: DMA_CH0,
},
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Main thread!");
let p = embassy_rp::init(Default::default());
let r = split_resources!(p);
interrupt::SWI_IRQ_1.set_priority(Priority::P2);
let executor = EXECUTOR_LOW.init(Executor::new());
executor.run(|spawner| {
// update the RTC
spawner.spawn(run_mqtt(spawner, r.wifi)).unwrap();
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
spawn_core1(
p.CORE1,
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1
.run(|spawner| unwrap!(spawner.spawn(led_ctrl_core1_task(r.led_peripheral))));
},
);
});
}
#[embassy_executor::task]
pub async fn run_mqtt(spawner: Spawner, r: WifiResources) {
let mut rng = RoscRng;
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
info!("init wifi");
let pwr = Output::new(r.pwr_pin, Level::Low);
let cs = Output::new(r.cs_pin, Level::High);
let mut pio = Pio::new(r.pio_sm, Irqs);
let spi = PioSpi::new(
&mut pio.common,
pio.sm0,
pio.irq0,
cs,
r.dio_pin,
r.clk_pin,
r.dma_ch,
);
static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;
control
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
let config = Config::dhcpv4(Default::default());
// Use static IP configuration instead of DHCP
//let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = rng.next_u64();
// Init network stack
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
let (stack, runner) = embassy_net::new(
net_device,
config,
RESOURCES.init(StackResources::new()),
seed,
);
unwrap!(spawner.spawn(net_task(runner)));
loop {
match control
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
.await
{
Ok(_) => break,
Err(err) => {
info!("join failed with status={}", err.status);
}
}
}
// Wait for DHCP, not necessary when using static IP
info!("waiting for DHCP...");
while !stack.is_config_up() {
Timer::after_millis(100).await;
}
info!("DHCP is now up!");
info!("waiting for link up...");
while !stack.is_link_up() {
Timer::after_millis(500).await;
}
info!("Link is up!");
info!("waiting for stack to be up...");
stack.wait_config_up().await;
info!("Stack is up!");
let tcp_state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let tcp_client = TcpClient::new(stack, &tcp_state);
let addr = embedded_nal_async::SocketAddr::new(
embedded_nal_async::Ipv4Addr::new(192, 168, 0, 100).into(),
1883,
);
// let connection = embedded_nal::TcpStream::connect(addr)
// .await
// .map_err(|_| ReasonCode::NetworkError)
// .unwrap();
//let connection = FromTokio::<TcpStream>::new(connection);
let mut config = ClientConfig::new(
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
CountingRng(20000),
);
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0);
config.add_client_id(CLIENT_ID);
config.keep_alive = u16::MAX;
// config.add_username(USERNAME);
// config.add_password(PASSWORD);
config.max_packet_size = 400;
let mut recv_buffer = [0; 400];
let mut write_buffer = [0; 400];
//let r = tcp_client.connect(addr).await;
let r;
loop {
match tcp_client.connect(addr).await {
Ok(rp) => {
info!("Attempting to connect to mqtt broker");
r = rp;
break;
}
Err(err) => {
info!("Failed to join broker: {}. Trying again!", err);
Timer::after_millis(100).await;
}
};
}
let mut client: MqttClient<
'_,
embassy_net::tcp::client::TcpConnection<'_, 1, 1024, 1024>,
5,
CountingRng,
> = MqttClient::<_, 5, _>::new(r, &mut write_buffer, 512, &mut recv_buffer, 512, config);
loop {
match client.connect_to_broker().await {
Ok(_) => {
info!("CAT Connected to broker");
break;
}
Err(err) => {
info!("DOG connect_to_broker failed with status={}", err);
}
}
}
loop {
match client.subscribe_to_topic(TOPIC).await {
Ok(_) => {
info!("CAT subscribed to topic");
break;
}
Err(err) => {
info!("DOG subscribe_to_topic failed with status={}", err);
}
}
}
let mut old_msg = LedStrip::new(0);
loop {
info!("[RECEIVER] Waiting for new message");
let msg = client.receive_message().await;
info!("[RECEIVER] Received msg: {}", msg);
if msg.is_ok() {
let message = msg.unwrap();
info!("[RECEIVER] message has size: {}", message.1.len());
match bincode::decode_from_slice::<LedStrip, Configuration>(
message.1,
bincode::config::standard(),
) {
Ok(decoded) => {
if old_msg != decoded.0 {
CHANNEL.send(decoded.0.clone()).await;
old_msg = decoded.0;
info!("[RECEIVER] Sent message");
}
}
Err(_e) => {
info!("DOG");
}
}
} else {
warn!("[RECEIVER] Could not get message with error: {}", msg.err());
}
Timer::after(Duration::from_millis(2)).await;
}
}
#[embassy_executor::task]
async fn led_ctrl_core1_task(led_peripheral: LedPeripheral) {
info!("Hello from core 1");
let mut current_ledstrip = LedStrip::new(0);
// Spi configuration for the neopixel
let mut spi_config = embassy_rp::spi::Config::default();
spi_config.frequency = 3_800_000;
spi_config.phase = Phase::CaptureOnFirstTransition;
spi_config.polarity = Polarity::IdleLow;
// let spi = embassy_rp::spi::Spi::new_txonly(led_peripheral.inner_spi, led_peripheral.clk_pin, led_peripheral.mosi_pin, led_peripheral.tx_dma_ch, spi_config);
let spi = Spi::new_txonly(
led_peripheral.inner_spi,
led_peripheral.clk_pin,
led_peripheral.mosi_pin,
led_peripheral.tx_dma_ch,
spi_config,
);
let mut np: Ws2812<_, { 12 * NUM_LEDS }> = Ws2812::new(spi);
np.set_color_order(ColorOrder::GRB);
let mut data = [RGB8::default(); NUM_LEDS];
for led in data.iter_mut().step_by(1) {
led.r = 250; // blue
led.g = 150; // red
led.b = 0; // green
}
//np.write(empty.iter().cloned()).await.ok();
//np.write(data.iter().cloned()).await.ok();
let mut rgb_arr: [RGB8; NUM_LEDS] = [RGB8::new(0, 0, 0); NUM_LEDS];
loop {
let rc = CHANNEL.receive().await;
info!("OCTOPUS yyyy");
if current_ledstrip != rc {
info!("OCTOPUS got a new led strip");
for i in 0..rc.leds.len() {
rgb_arr[i].r = rc.leds[i].r;
rgb_arr[i].g = rc.leds[i].g;
rgb_arr[i].b = rc.leds[i].b;
}
current_ledstrip = rc.clone();
info!("writing led!");
np.write(rgb_arr.iter().cloned()).await.ok();
// Timer::after(Duration::from_millis(0)).await;
}
}
}
#[derive(Debug, Decode, Clone, Copy, PartialEq)]
struct Led {
r: u8,
g: u8,
b: u8,
}
#[derive(Clone, Debug, Decode, PartialEq)]
pub struct LedStrip {
leds: [Led; NUM_LEDS],
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(_r: u8) -> Self {
let arr: [Led; NUM_LEDS] = [Led { r: 0, g: 0, b: 0 }; NUM_LEDS];
LedStrip { leds: arr }
}
}

View File

@ -0,0 +1,400 @@
#![no_std]
#![no_main]
use assign_resources::assign_resources;
use bincode::config::Configuration;
use bincode::Decode;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::{Executor, InterruptExecutor, Spawner};
use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt;
use embassy_rp::interrupt::{InterruptExt, Priority};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::spi::{Phase, Polarity, Spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_time::Timer;
//use embedded_nal_async::TcpConnect;
//use embedded_nal_async::stack::tcp::TcpConnect;
use embedded_nal_async::TcpConnect;
use rand::RngCore;
use smart_leds::RGB8;
use static_cell::StaticCell;
use ws2812_async::{ColorOrder, Ws2812};
use {defmt_rtt as _, panic_probe as _};
use rust_mqtt::{
client::{client::MqttClient, client_config::ClientConfig},
utils::rng_generator::CountingRng,
};
//pub type RGB8 = RGB<u8>;
use {defmt_rtt as _, panic_probe as _};
// after observing somewhat jumpy behavior of the neopixel task, I decided to set the scheduler and orhestrator to high priority
// hight priority runs on interrupt
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
// low priority runs in thread-mode
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
#[global_allocator]
static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new();
extern crate alloc;
#[interrupt]
unsafe fn SWI_IRQ_1() {
EXECUTOR_HIGH.on_interrupt()
}
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
const WIFI_NETWORK: &str = "hey can I uhhh";
const WIFI_PASSWORD: &str = "1%of@dmin";
const CLIENT_ID: &str = "pico-495f6297-b962-4266-9c00-74138ae5a1f1";
const TOPIC: &str = "hello";
const NUM_LEDS: usize = 100;
static CHANNEL: embassy_sync::channel::Channel<ThreadModeRawMutex, LedStrip, 64> =
embassy_sync::channel::Channel::new();
#[embassy_executor::task]
async fn cyw43_task(
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
runner.run().await
}
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
runner.run().await
}
assign_resources! {
led_peripheral: LedPeripheral {
inner_spi: SPI1,
clk_pin: PIN_14, // this is just a dummy pin, the neopixel uses only the mosi pin
mosi_pin: PIN_15,
tx_dma_ch: DMA_CH1,
},
wifi: WifiResources {
pwr_pin: PIN_23,
cs_pin: PIN_25,
pio_sm: PIO0,
dio_pin: PIN_24,
clk_pin: PIN_29,
dma_ch: DMA_CH0,
},
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Main thread!");
let p = embassy_rp::init(Default::default());
let r = split_resources!(p);
interrupt::SWI_IRQ_1.set_priority(Priority::P2);
let executor = EXECUTOR_LOW.init(Executor::new());
executor.run(|spawner| {
// update the RTC
spawner.spawn(run_mqtt(spawner, r.wifi)).unwrap();
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
spawn_core1(
p.CORE1,
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1
.run(|spawner| unwrap!(spawner.spawn(led_ctrl_core1_task(r.led_peripheral))));
},
);
});
}
#[embassy_executor::task]
pub async fn run_mqtt(spawner: Spawner, r: WifiResources) {
let mut rng = RoscRng;
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
info!("init wifi");
let pwr = Output::new(r.pwr_pin, Level::Low);
let cs = Output::new(r.cs_pin, Level::High);
let mut pio = Pio::new(r.pio_sm, Irqs);
let spi = PioSpi::new(
&mut pio.common,
pio.sm0,
pio.irq0,
cs,
r.dio_pin,
r.clk_pin,
r.dma_ch,
);
static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;
control
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
let config = Config::dhcpv4(Default::default());
// Use static IP configuration instead of DHCP
//let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = rng.next_u64();
// Init network stack
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
let (stack, runner) = embassy_net::new(
net_device,
config,
RESOURCES.init(StackResources::new()),
seed,
);
unwrap!(spawner.spawn(net_task(runner)));
loop {
match control
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
.await
{
Ok(_) => break,
Err(err) => {
info!("join failed with status={}", err.status);
}
}
}
// Wait for DHCP, not necessary when using static IP
info!("waiting for DHCP...");
while !stack.is_config_up() {
Timer::after_millis(100).await;
}
info!("DHCP is now up!");
info!("waiting for link up...");
while !stack.is_link_up() {
Timer::after_millis(500).await;
}
info!("Link is up!");
info!("waiting for stack to be up...");
stack.wait_config_up().await;
info!("Stack is up!");
let tcp_state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let tcp_client = TcpClient::new(stack, &tcp_state);
let addr = embedded_nal_async::SocketAddr::new(
embedded_nal_async::Ipv4Addr::new(10, 0, 0, 73).into(),
1883,
);
// let connection = embedded_nal::TcpStream::connect(addr)
// .await
// .map_err(|_| ReasonCode::NetworkError)
// .unwrap();
//let connection = FromTokio::<TcpStream>::new(connection);
let mut config = ClientConfig::new(
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
CountingRng(20000),
);
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0);
config.add_client_id(CLIENT_ID);
config.keep_alive = u16::MAX;
// config.add_username(USERNAME);
// config.add_password(PASSWORD);
config.max_packet_size = 400;
let mut recv_buffer = [0; 400];
let mut write_buffer = [0; 400];
//let r = tcp_client.connect(addr).await;
let r;
loop {
match tcp_client.connect(addr).await {
Ok(rp) => {
info!("Attempting to connect to mqtt broker");
r = rp;
break;
}
Err(err) => {
info!("Failed to join broker: {}. Trying again!", err);
Timer::after_millis(100).await;
}
};
}
let mut client: MqttClient<
'_,
embassy_net::tcp::client::TcpConnection<'_, 1, 1024, 1024>,
5,
CountingRng,
> = MqttClient::<_, 5, _>::new(r, &mut write_buffer, 512, &mut recv_buffer, 512, config);
loop {
match client.connect_to_broker().await {
Ok(_) => {
info!("CAT Connected to broker");
break;
}
Err(err) => {
info!("DOG connect_to_broker failed with status={}", err);
}
}
}
loop {
match client.subscribe_to_topic(TOPIC).await {
Ok(_) => {
info!("CAT subscribed to topic");
break;
}
Err(err) => {
info!("DOG subscribe_to_topic failed with status={}", err);
}
}
}
let mut old_msg = LedStrip::new(0);
loop {
info!("[RECEIVER] Waiting for new message");
let msg = client.receive_message().await;
info!("[RECEIVER] Received msg: {}", msg);
if msg.is_ok() {
let message = msg.unwrap();
info!("[RECEIVER] message has size: {}", message.1.len());
match bincode::decode_from_slice::<LedStrip, Configuration>(
message.1,
bincode::config::standard(),
) {
Ok(decoded) => {
if old_msg != decoded.0 {
CHANNEL.send(decoded.0.clone()).await;
old_msg = decoded.0;
info!("[RECEIVER] Sent message");
}
}
Err(_e) => {
info!("DOG");
}
}
} else {
warn!("[RECEIVER] Could not get message with error: {}", msg.err());
}
//Timer::after(Duration::from_secs(2)).await;
}
}
#[embassy_executor::task]
async fn led_ctrl_core1_task(led_peripheral: LedPeripheral) {
info!("Hello from core 1");
let mut current_ledstrip = LedStrip::new(0);
// Spi configuration for the neopixel
let mut spi_config = embassy_rp::spi::Config::default();
spi_config.frequency = 3_800_000;
spi_config.phase = Phase::CaptureOnFirstTransition;
spi_config.polarity = Polarity::IdleLow;
// let spi = embassy_rp::spi::Spi::new_txonly(led_peripheral.inner_spi, led_peripheral.clk_pin, led_peripheral.mosi_pin, led_peripheral.tx_dma_ch, spi_config);
let spi = Spi::new_txonly(
led_peripheral.inner_spi,
led_peripheral.clk_pin,
led_peripheral.mosi_pin,
led_peripheral.tx_dma_ch,
spi_config,
);
let mut np: Ws2812<_, { 12 * NUM_LEDS }> = Ws2812::new(spi);
np.set_color_order(ColorOrder::GRB);
let mut data = [RGB8::default(); NUM_LEDS];
for led in data.iter_mut().step_by(1) {
led.r = 250; // blue
led.g = 150; // red
led.b = 0; // green
}
//np.write(empty.iter().cloned()).await.ok();
//np.write(data.iter().cloned()).await.ok();
let mut rgb_arr: [RGB8; NUM_LEDS] = [RGB8::new(0, 0, 0); NUM_LEDS];
loop {
let rc = CHANNEL.receive().await;
info!("OCTOPUS yyyy");
if current_ledstrip != rc {
info!("OCTOPUS got a new led strip");
for i in 0..rc.leds.len() {
rgb_arr[i].r = rc.leds[i].r;
rgb_arr[i].g = rc.leds[i].g;
rgb_arr[i].b = rc.leds[i].b;
}
current_ledstrip = rc.clone();
info!("writing led!");
np.write(rgb_arr.iter().cloned()).await.ok();
// Timer::after(Duration::from_millis(0)).await;
}
}
}
#[derive(Debug, Decode, Clone, Copy, PartialEq)]
struct Led {
r: u8,
g: u8,
b: u8,
}
#[derive(Clone, Debug, Decode, PartialEq)]
pub struct LedStrip {
leds: [Led; NUM_LEDS],
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(_r: u8) -> Self {
let arr: [Led; NUM_LEDS] = [Led { r: 0, g: 0, b: 0 }; NUM_LEDS];
LedStrip { leds: arr }
}
}

View File

@ -0,0 +1,400 @@
#![no_std]
#![no_main]
use assign_resources::assign_resources;
use bincode::config::Configuration;
use bincode::Decode;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::{Executor, InterruptExecutor, Spawner};
use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt;
use embassy_rp::interrupt::{InterruptExt, Priority};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::spi::{Phase, Polarity, Spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_time::Timer;
//use embedded_nal_async::TcpConnect;
//use embedded_nal_async::stack::tcp::TcpConnect;
use embedded_nal_async::TcpConnect;
use rand::RngCore;
use smart_leds::RGB8;
use static_cell::StaticCell;
use ws2812_async::{ColorOrder, Ws2812};
use {defmt_rtt as _, panic_probe as _};
use rust_mqtt::{
client::{client::MqttClient, client_config::ClientConfig},
utils::rng_generator::CountingRng,
};
//pub type RGB8 = RGB<u8>;
use {defmt_rtt as _, panic_probe as _};
// after observing somewhat jumpy behavior of the neopixel task, I decided to set the scheduler and orhestrator to high priority
// hight priority runs on interrupt
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
// low priority runs in thread-mode
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
#[global_allocator]
static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new();
extern crate alloc;
#[interrupt]
unsafe fn SWI_IRQ_1() {
EXECUTOR_HIGH.on_interrupt()
}
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
const WIFI_NETWORK: &str = "hey can I uhhh";
const WIFI_PASSWORD: &str = "1%of@dmin";
const CLIENT_ID: &str = "pico-495f6297-b962-4266-9c00-74138ae5a1f1";
const TOPIC: &str = "hello";
const NUM_LEDS: usize = 100;
static CHANNEL: embassy_sync::channel::Channel<ThreadModeRawMutex, LedStrip, 64> =
embassy_sync::channel::Channel::new();
#[embassy_executor::task]
async fn cyw43_task(
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
runner.run().await
}
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
runner.run().await
}
assign_resources! {
led_peripheral: LedPeripheral {
inner_spi: SPI1,
clk_pin: PIN_14, // this is just a dummy pin, the neopixel uses only the mosi pin
mosi_pin: PIN_15,
tx_dma_ch: DMA_CH1,
},
wifi: WifiResources {
pwr_pin: PIN_23,
cs_pin: PIN_25,
pio_sm: PIO0,
dio_pin: PIN_24,
clk_pin: PIN_29,
dma_ch: DMA_CH0,
},
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Main thread!");
let p = embassy_rp::init(Default::default());
let r = split_resources!(p);
interrupt::SWI_IRQ_1.set_priority(Priority::P2);
let executor = EXECUTOR_LOW.init(Executor::new());
executor.run(|spawner| {
// update the RTC
spawner.spawn(run_mqtt(spawner, r.wifi)).unwrap();
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
spawn_core1(
p.CORE1,
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1
.run(|spawner| unwrap!(spawner.spawn(led_ctrl_core1_task(r.led_peripheral))));
},
);
});
}
#[embassy_executor::task]
pub async fn run_mqtt(spawner: Spawner, r: WifiResources) {
let mut rng = RoscRng;
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
info!("init wifi");
let pwr = Output::new(r.pwr_pin, Level::Low);
let cs = Output::new(r.cs_pin, Level::High);
let mut pio = Pio::new(r.pio_sm, Irqs);
let spi = PioSpi::new(
&mut pio.common,
pio.sm0,
pio.irq0,
cs,
r.dio_pin,
r.clk_pin,
r.dma_ch,
);
static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;
control
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
let config = Config::dhcpv4(Default::default());
// Use static IP configuration instead of DHCP
//let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = rng.next_u64();
// Init network stack
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
let (stack, runner) = embassy_net::new(
net_device,
config,
RESOURCES.init(StackResources::new()),
seed,
);
unwrap!(spawner.spawn(net_task(runner)));
loop {
match control
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
.await
{
Ok(_) => break,
Err(err) => {
info!("join failed with status={}", err.status);
}
}
}
// Wait for DHCP, not necessary when using static IP
info!("waiting for DHCP...");
while !stack.is_config_up() {
Timer::after_millis(100).await;
}
info!("DHCP is now up!");
info!("waiting for link up...");
while !stack.is_link_up() {
Timer::after_millis(500).await;
}
info!("Link is up!");
info!("waiting for stack to be up...");
stack.wait_config_up().await;
info!("Stack is up!");
let tcp_state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let tcp_client = TcpClient::new(stack, &tcp_state);
let addr = embedded_nal_async::SocketAddr::new(
embedded_nal_async::Ipv4Addr::new(10, 0, 0, 67).into(),
1883,
);
// let connection = embedded_nal::TcpStream::connect(addr)
// .await
// .map_err(|_| ReasonCode::NetworkError)
// .unwrap();
//let connection = FromTokio::<TcpStream>::new(connection);
let mut config = ClientConfig::new(
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
CountingRng(20000),
);
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0);
config.add_client_id(CLIENT_ID);
config.keep_alive = u16::MAX;
// config.add_username(USERNAME);
// config.add_password(PASSWORD);
config.max_packet_size = 400;
let mut recv_buffer = [0; 400];
let mut write_buffer = [0; 400];
//let r = tcp_client.connect(addr).await;
let r;
loop {
match tcp_client.connect(addr).await {
Ok(rp) => {
info!("Attempting to connect to mqtt broker");
r = rp;
break;
}
Err(err) => {
info!("Failed to join broker: {}. Trying again!", err);
Timer::after_millis(100).await;
}
};
}
let mut client: MqttClient<
'_,
embassy_net::tcp::client::TcpConnection<'_, 1, 1024, 1024>,
5,
CountingRng,
> = MqttClient::<_, 5, _>::new(r, &mut write_buffer, 512, &mut recv_buffer, 512, config);
loop {
match client.connect_to_broker().await {
Ok(_) => {
info!("CAT Connected to broker");
break;
}
Err(err) => {
info!("DOG connect_to_broker failed with status={}", err);
}
}
}
loop {
match client.subscribe_to_topic(TOPIC).await {
Ok(_) => {
info!("CAT subscribed to topic");
break;
}
Err(err) => {
info!("DOG subscribe_to_topic failed with status={}", err);
}
}
}
let mut old_msg = LedStrip::new(0);
loop {
info!("[RECEIVER] Waiting for new message");
let msg = client.receive_message().await;
info!("[RECEIVER] Received msg: {}", msg);
if msg.is_ok() {
let message = msg.unwrap();
info!("[RECEIVER] message has size: {}", message.1.len());
match bincode::decode_from_slice::<LedStrip, Configuration>(
message.1,
bincode::config::standard(),
) {
Ok(decoded) => {
if old_msg != decoded.0 {
CHANNEL.send(decoded.0.clone()).await;
old_msg = decoded.0;
info!("[RECEIVER] Sent message");
}
}
Err(_e) => {
info!("DOG");
}
}
} else {
warn!("[RECEIVER] Could not get message with error: {}", msg.err());
}
//Timer::after(Duration::from_secs(2)).await;
}
}
#[embassy_executor::task]
async fn led_ctrl_core1_task(led_peripheral: LedPeripheral) {
info!("Hello from core 1");
let mut current_ledstrip = LedStrip::new(0);
// Spi configuration for the neopixel
let mut spi_config = embassy_rp::spi::Config::default();
spi_config.frequency = 3_800_000;
spi_config.phase = Phase::CaptureOnFirstTransition;
spi_config.polarity = Polarity::IdleLow;
// let spi = embassy_rp::spi::Spi::new_txonly(led_peripheral.inner_spi, led_peripheral.clk_pin, led_peripheral.mosi_pin, led_peripheral.tx_dma_ch, spi_config);
let spi = Spi::new_txonly(
led_peripheral.inner_spi,
led_peripheral.clk_pin,
led_peripheral.mosi_pin,
led_peripheral.tx_dma_ch,
spi_config,
);
let mut np: Ws2812<_, { 12 * NUM_LEDS }> = Ws2812::new(spi);
np.set_color_order(ColorOrder::GRB);
let mut data = [RGB8::default(); NUM_LEDS];
for led in data.iter_mut().step_by(1) {
led.r = 250; // blue
led.g = 150; // red
led.b = 0; // green
}
//np.write(empty.iter().cloned()).await.ok();
//np.write(data.iter().cloned()).await.ok();
let mut rgb_arr: [RGB8; NUM_LEDS] = [RGB8::new(0, 0, 0); NUM_LEDS];
loop {
let rc = CHANNEL.receive().await;
info!("OCTOPUS yyyy");
if current_ledstrip != rc {
info!("OCTOPUS got a new led strip");
for i in 0..rc.leds.len() {
rgb_arr[i].r = rc.leds[i].r;
rgb_arr[i].g = rc.leds[i].g;
rgb_arr[i].b = rc.leds[i].b;
}
current_ledstrip = rc.clone();
info!("writing led!");
np.write(rgb_arr.iter().cloned()).await.ok();
// Timer::after(Duration::from_millis(0)).await;
}
}
}
#[derive(Debug, Decode, Clone, Copy, PartialEq)]
struct Led {
r: u8,
g: u8,
b: u8,
}
#[derive(Clone, Debug, Decode, PartialEq)]
pub struct LedStrip {
leds: [Led; NUM_LEDS],
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(_r: u8) -> Self {
let arr: [Led; NUM_LEDS] = [Led { r: 0, g: 0, b: 0 }; NUM_LEDS];
LedStrip { leds: arr }
}
}

View File

@ -0,0 +1,400 @@
#![no_std]
#![no_main]
use assign_resources::assign_resources;
use bincode::config::Configuration;
use bincode::Decode;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::{Executor, InterruptExecutor, Spawner};
use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt;
use embassy_rp::interrupt::{InterruptExt, Priority};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::spi::{Phase, Polarity, Spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_time::Timer;
//use embedded_nal_async::TcpConnect;
//use embedded_nal_async::stack::tcp::TcpConnect;
use embedded_nal_async::TcpConnect;
use rand::RngCore;
use smart_leds::RGB8;
use static_cell::StaticCell;
use ws2812_async::{ColorOrder, Ws2812};
use {defmt_rtt as _, panic_probe as _};
use rust_mqtt::{
client::{client::MqttClient, client_config::ClientConfig},
utils::rng_generator::CountingRng,
};
//pub type RGB8 = RGB<u8>;
use {defmt_rtt as _, panic_probe as _};
// after observing somewhat jumpy behavior of the neopixel task, I decided to set the scheduler and orhestrator to high priority
// hight priority runs on interrupt
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
// low priority runs in thread-mode
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
#[global_allocator]
static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new();
extern crate alloc;
#[interrupt]
unsafe fn SWI_IRQ_1() {
EXECUTOR_HIGH.on_interrupt()
}
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
const WIFI_NETWORK: &str = "hey can I uhhh";
const WIFI_PASSWORD: &str = "1%of@dmin";
const CLIENT_ID: &str = "pico-495f6297-b962-4266-9c00-74138ae5a1f1";
const TOPIC: &str = "hello";
const NUM_LEDS: usize = 100;
static CHANNEL: embassy_sync::channel::Channel<ThreadModeRawMutex, LedStrip, 64> =
embassy_sync::channel::Channel::new();
#[embassy_executor::task]
async fn cyw43_task(
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
runner.run().await
}
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
runner.run().await
}
assign_resources! {
led_peripheral: LedPeripheral {
inner_spi: SPI1,
clk_pin: PIN_14, // this is just a dummy pin, the neopixel uses only the mosi pin
mosi_pin: PIN_15,
tx_dma_ch: DMA_CH1,
},
wifi: WifiResources {
pwr_pin: PIN_23,
cs_pin: PIN_25,
pio_sm: PIO0,
dio_pin: PIN_24,
clk_pin: PIN_29,
dma_ch: DMA_CH0,
},
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Main thread!");
let p = embassy_rp::init(Default::default());
let r = split_resources!(p);
interrupt::SWI_IRQ_1.set_priority(Priority::P2);
let executor = EXECUTOR_LOW.init(Executor::new());
executor.run(|spawner| {
// update the RTC
spawner.spawn(run_mqtt(spawner, r.wifi)).unwrap();
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
spawn_core1(
p.CORE1,
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1
.run(|spawner| unwrap!(spawner.spawn(led_ctrl_core1_task(r.led_peripheral))));
},
);
});
}
#[embassy_executor::task]
pub async fn run_mqtt(spawner: Spawner, r: WifiResources) {
let mut rng = RoscRng;
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
info!("init wifi");
let pwr = Output::new(r.pwr_pin, Level::Low);
let cs = Output::new(r.cs_pin, Level::High);
let mut pio = Pio::new(r.pio_sm, Irqs);
let spi = PioSpi::new(
&mut pio.common,
pio.sm0,
pio.irq0,
cs,
r.dio_pin,
r.clk_pin,
r.dma_ch,
);
static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;
control
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
let config = Config::dhcpv4(Default::default());
// Use static IP configuration instead of DHCP
//let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = rng.next_u64();
// Init network stack
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
let (stack, runner) = embassy_net::new(
net_device,
config,
RESOURCES.init(StackResources::new()),
seed,
);
unwrap!(spawner.spawn(net_task(runner)));
loop {
match control
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
.await
{
Ok(_) => break,
Err(err) => {
info!("join failed with status={}", err.status);
}
}
}
// Wait for DHCP, not necessary when using static IP
info!("waiting for DHCP...");
while !stack.is_config_up() {
Timer::after_millis(100).await;
}
info!("DHCP is now up!");
info!("waiting for link up...");
while !stack.is_link_up() {
Timer::after_millis(500).await;
}
info!("Link is up!");
info!("waiting for stack to be up...");
stack.wait_config_up().await;
info!("Stack is up!");
let tcp_state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let tcp_client = TcpClient::new(stack, &tcp_state);
let addr = embedded_nal_async::SocketAddr::new(
embedded_nal_async::Ipv4Addr::new(192, 168, 0, 103).into(),
1883,
);
// let connection = embedded_nal::TcpStream::connect(addr)
// .await
// .map_err(|_| ReasonCode::NetworkError)
// .unwrap();
//let connection = FromTokio::<TcpStream>::new(connection);
let mut config = ClientConfig::new(
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
CountingRng(20000),
);
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0);
config.add_client_id(CLIENT_ID);
config.keep_alive = u16::MAX;
// config.add_username(USERNAME);
// config.add_password(PASSWORD);
config.max_packet_size = 400;
let mut recv_buffer = [0; 400];
let mut write_buffer = [0; 400];
//let r = tcp_client.connect(addr).await;
let r;
loop {
match tcp_client.connect(addr).await {
Ok(rp) => {
info!("Attempting to connect to mqtt broker");
r = rp;
break;
}
Err(err) => {
info!("Failed to join broker: {}. Trying again!", err);
Timer::after_millis(100).await;
}
};
}
let mut client: MqttClient<
'_,
embassy_net::tcp::client::TcpConnection<'_, 1, 1024, 1024>,
5,
CountingRng,
> = MqttClient::<_, 5, _>::new(r, &mut write_buffer, 512, &mut recv_buffer, 512, config);
loop {
match client.connect_to_broker().await {
Ok(_) => {
info!("CAT Connected to broker");
break;
}
Err(err) => {
info!("DOG connect_to_broker failed with status={}", err);
}
}
}
loop {
match client.subscribe_to_topic(TOPIC).await {
Ok(_) => {
info!("CAT subscribed to topic");
break;
}
Err(err) => {
info!("DOG subscribe_to_topic failed with status={}", err);
}
}
}
let mut old_msg = LedStrip::new(0);
loop {
info!("[RECEIVER] Waiting for new message");
let msg = client.receive_message().await;
info!("[RECEIVER] Received msg: {}", msg);
if msg.is_ok() {
let message = msg.unwrap();
info!("[RECEIVER] message has size: {}", message.1.len());
match bincode::decode_from_slice::<LedStrip, Configuration>(
message.1,
bincode::config::standard(),
) {
Ok(decoded) => {
if old_msg != decoded.0 {
CHANNEL.send(decoded.0.clone()).await;
old_msg = decoded.0;
info!("[RECEIVER] Sent message");
}
}
Err(_e) => {
info!("DOG");
}
}
} else {
warn!("[RECEIVER] Could not get message with error: {}", msg.err());
}
//Timer::after(Duration::from_secs(2)).await;
}
}
#[embassy_executor::task]
async fn led_ctrl_core1_task(led_peripheral: LedPeripheral) {
info!("Hello from core 1");
let mut current_ledstrip = LedStrip::new(0);
// Spi configuration for the neopixel
let mut spi_config = embassy_rp::spi::Config::default();
spi_config.frequency = 3_800_000;
spi_config.phase = Phase::CaptureOnFirstTransition;
spi_config.polarity = Polarity::IdleLow;
// let spi = embassy_rp::spi::Spi::new_txonly(led_peripheral.inner_spi, led_peripheral.clk_pin, led_peripheral.mosi_pin, led_peripheral.tx_dma_ch, spi_config);
let spi = Spi::new_txonly(
led_peripheral.inner_spi,
led_peripheral.clk_pin,
led_peripheral.mosi_pin,
led_peripheral.tx_dma_ch,
spi_config,
);
let mut np: Ws2812<_, { 12 * NUM_LEDS }> = Ws2812::new(spi);
np.set_color_order(ColorOrder::GRB);
let mut data = [RGB8::default(); NUM_LEDS];
for led in data.iter_mut().step_by(1) {
led.r = 250; // blue
led.g = 150; // red
led.b = 0; // green
}
//np.write(empty.iter().cloned()).await.ok();
//np.write(data.iter().cloned()).await.ok();
let mut rgb_arr: [RGB8; NUM_LEDS] = [RGB8::new(0, 0, 0); NUM_LEDS];
loop {
let rc = CHANNEL.receive().await;
info!("OCTOPUS yyyy");
if current_ledstrip != rc {
info!("OCTOPUS got a new led strip");
for i in 0..rc.leds.len() {
rgb_arr[i].r = rc.leds[i].r;
rgb_arr[i].g = rc.leds[i].g;
rgb_arr[i].b = rc.leds[i].b;
}
current_ledstrip = rc.clone();
info!("writing led!");
np.write(rgb_arr.iter().cloned()).await.ok();
// Timer::after(Duration::from_millis(0)).await;
}
}
}
#[derive(Debug, Decode, Clone, Copy, PartialEq)]
struct Led {
r: u8,
g: u8,
b: u8,
}
#[derive(Clone, Debug, Decode, PartialEq)]
pub struct LedStrip {
leds: [Led; NUM_LEDS],
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(_r: u8) -> Self {
let arr: [Led; NUM_LEDS] = [Led { r: 0, g: 0, b: 0 }; NUM_LEDS];
LedStrip { leds: arr }
}
}

View File

@ -0,0 +1,400 @@
#![no_std]
#![no_main]
use assign_resources::assign_resources;
use bincode::config::Configuration;
use bincode::Decode;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::{Executor, InterruptExecutor, Spawner};
use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt;
use embassy_rp::interrupt::{InterruptExt, Priority};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::spi::{Phase, Polarity, Spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_time::Timer;
//use embedded_nal_async::TcpConnect;
//use embedded_nal_async::stack::tcp::TcpConnect;
use embedded_nal_async::TcpConnect;
use rand::RngCore;
use smart_leds::RGB8;
use static_cell::StaticCell;
use ws2812_async::{ColorOrder, Ws2812};
use {defmt_rtt as _, panic_probe as _};
use rust_mqtt::{
client::{client::MqttClient, client_config::ClientConfig},
utils::rng_generator::CountingRng,
};
//pub type RGB8 = RGB<u8>;
use {defmt_rtt as _, panic_probe as _};
// after observing somewhat jumpy behavior of the neopixel task, I decided to set the scheduler and orhestrator to high priority
// hight priority runs on interrupt
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
// low priority runs in thread-mode
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
#[global_allocator]
static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new();
extern crate alloc;
#[interrupt]
unsafe fn SWI_IRQ_1() {
EXECUTOR_HIGH.on_interrupt()
}
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
const WIFI_NETWORK: &str = "cat";
const WIFI_PASSWORD: &str = "catcat123cat";
const CLIENT_ID: &str = "pico-495f6297-b962-4266-9c00-74138ae5a1f1";
const TOPIC: &str = "hello";
const NUM_LEDS: usize = 100;
static CHANNEL: embassy_sync::channel::Channel<ThreadModeRawMutex, LedStrip, 64> =
embassy_sync::channel::Channel::new();
#[embassy_executor::task]
async fn cyw43_task(
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
runner.run().await
}
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
runner.run().await
}
assign_resources! {
led_peripheral: LedPeripheral {
inner_spi: SPI1,
clk_pin: PIN_14, // this is just a dummy pin, the neopixel uses only the mosi pin
mosi_pin: PIN_15,
tx_dma_ch: DMA_CH1,
},
wifi: WifiResources {
pwr_pin: PIN_23,
cs_pin: PIN_25,
pio_sm: PIO0,
dio_pin: PIN_24,
clk_pin: PIN_29,
dma_ch: DMA_CH0,
},
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Main thread!");
let p = embassy_rp::init(Default::default());
let r = split_resources!(p);
interrupt::SWI_IRQ_1.set_priority(Priority::P2);
let executor = EXECUTOR_LOW.init(Executor::new());
executor.run(|spawner| {
// update the RTC
spawner.spawn(run_mqtt(spawner, r.wifi)).unwrap();
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
spawn_core1(
p.CORE1,
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1
.run(|spawner| unwrap!(spawner.spawn(led_ctrl_core1_task(r.led_peripheral))));
},
);
});
}
#[embassy_executor::task]
pub async fn run_mqtt(spawner: Spawner, r: WifiResources) {
let mut rng = RoscRng;
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
info!("init wifi");
let pwr = Output::new(r.pwr_pin, Level::Low);
let cs = Output::new(r.cs_pin, Level::High);
let mut pio = Pio::new(r.pio_sm, Irqs);
let spi = PioSpi::new(
&mut pio.common,
pio.sm0,
pio.irq0,
cs,
r.dio_pin,
r.clk_pin,
r.dma_ch,
);
static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;
control
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
let config = Config::dhcpv4(Default::default());
// Use static IP configuration instead of DHCP
//let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = rng.next_u64();
// Init network stack
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
let (stack, runner) = embassy_net::new(
net_device,
config,
RESOURCES.init(StackResources::new()),
seed,
);
unwrap!(spawner.spawn(net_task(runner)));
loop {
match control
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
.await
{
Ok(_) => break,
Err(err) => {
info!("join failed with status={}", err.status);
}
}
}
// Wait for DHCP, not necessary when using static IP
info!("waiting for DHCP...");
while !stack.is_config_up() {
Timer::after_millis(100).await;
}
info!("DHCP is now up!");
info!("waiting for link up...");
while !stack.is_link_up() {
Timer::after_millis(500).await;
}
info!("Link is up!");
info!("waiting for stack to be up...");
stack.wait_config_up().await;
info!("Stack is up!");
let tcp_state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let tcp_client = TcpClient::new(stack, &tcp_state);
let addr = embedded_nal_async::SocketAddr::new(
embedded_nal_async::Ipv4Addr::new(192, 168, 0, 103).into(),
1883,
);
// let connection = embedded_nal::TcpStream::connect(addr)
// .await
// .map_err(|_| ReasonCode::NetworkError)
// .unwrap();
//let connection = FromTokio::<TcpStream>::new(connection);
let mut config = ClientConfig::new(
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
CountingRng(20000),
);
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0);
config.add_client_id(CLIENT_ID);
config.keep_alive = u16::MAX;
// config.add_username(USERNAME);
// config.add_password(PASSWORD);
config.max_packet_size = 400;
let mut recv_buffer = [0; 400];
let mut write_buffer = [0; 400];
//let r = tcp_client.connect(addr).await;
let r;
loop {
match tcp_client.connect(addr).await {
Ok(rp) => {
info!("Attempting to connect to mqtt broker");
r = rp;
break;
}
Err(err) => {
info!("Failed to join broker: {}. Trying again!", err);
Timer::after_millis(100).await;
}
};
}
let mut client: MqttClient<
'_,
embassy_net::tcp::client::TcpConnection<'_, 1, 1024, 1024>,
5,
CountingRng,
> = MqttClient::<_, 5, _>::new(r, &mut write_buffer, 512, &mut recv_buffer, 512, config);
loop {
match client.connect_to_broker().await {
Ok(_) => {
info!("CAT Connected to broker");
break;
}
Err(err) => {
info!("DOG connect_to_broker failed with status={}", err);
}
}
}
loop {
match client.subscribe_to_topic(TOPIC).await {
Ok(_) => {
info!("CAT subscribed to topic");
break;
}
Err(err) => {
info!("DOG subscribe_to_topic failed with status={}", err);
}
}
}
let mut old_msg = LedStrip::new(0);
loop {
info!("[RECEIVER] Waiting for new message");
let msg = client.receive_message().await;
info!("[RECEIVER] Received msg: {}", msg);
if msg.is_ok() {
let message = msg.unwrap();
info!("[RECEIVER] message has size: {}", message.1.len());
match bincode::decode_from_slice::<LedStrip, Configuration>(
message.1,
bincode::config::standard(),
) {
Ok(decoded) => {
if old_msg != decoded.0 {
CHANNEL.send(decoded.0.clone()).await;
old_msg = decoded.0;
info!("[RECEIVER] Sent message");
}
}
Err(_e) => {
info!("DOG");
}
}
} else {
warn!("[RECEIVER] Could not get message with error: {}", msg.err());
}
//Timer::after(Duration::from_secs(2)).await;
}
}
#[embassy_executor::task]
async fn led_ctrl_core1_task(led_peripheral: LedPeripheral) {
info!("Hello from core 1");
let mut current_ledstrip = LedStrip::new(0);
// Spi configuration for the neopixel
let mut spi_config = embassy_rp::spi::Config::default();
spi_config.frequency = 3_800_000;
spi_config.phase = Phase::CaptureOnFirstTransition;
spi_config.polarity = Polarity::IdleLow;
// let spi = embassy_rp::spi::Spi::new_txonly(led_peripheral.inner_spi, led_peripheral.clk_pin, led_peripheral.mosi_pin, led_peripheral.tx_dma_ch, spi_config);
let spi = Spi::new_txonly(
led_peripheral.inner_spi,
led_peripheral.clk_pin,
led_peripheral.mosi_pin,
led_peripheral.tx_dma_ch,
spi_config,
);
let mut np: Ws2812<_, { 12 * NUM_LEDS }> = Ws2812::new(spi);
np.set_color_order(ColorOrder::GRB);
let mut data = [RGB8::default(); NUM_LEDS];
for led in data.iter_mut().step_by(1) {
led.r = 250; // blue
led.g = 150; // red
led.b = 0; // green
}
//np.write(empty.iter().cloned()).await.ok();
//np.write(data.iter().cloned()).await.ok();
let mut rgb_arr: [RGB8; NUM_LEDS] = [RGB8::new(0, 0, 0); NUM_LEDS];
loop {
let rc = CHANNEL.receive().await;
info!("OCTOPUS yyyy");
if current_ledstrip != rc {
info!("OCTOPUS got a new led strip");
for i in 0..rc.leds.len() {
rgb_arr[i].r = rc.leds[i].r;
rgb_arr[i].g = rc.leds[i].g;
rgb_arr[i].b = rc.leds[i].b;
}
current_ledstrip = rc.clone();
info!("writing led!");
np.write(rgb_arr.iter().cloned()).await.ok();
// Timer::after(Duration::from_millis(0)).await;
}
}
}
#[derive(Debug, Decode, Clone, Copy, PartialEq)]
struct Led {
r: u8,
g: u8,
b: u8,
}
#[derive(Clone, Debug, Decode, PartialEq)]
pub struct LedStrip {
leds: [Led; NUM_LEDS],
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(_r: u8) -> Self {
let arr: [Led; NUM_LEDS] = [Led { r: 0, g: 0, b: 0 }; NUM_LEDS];
LedStrip { leds: arr }
}
}

View File

@ -0,0 +1,400 @@
#![no_std]
#![no_main]
use assign_resources::assign_resources;
use bincode::config::Configuration;
use bincode::Decode;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use defmt::*;
use embassy_executor::{Executor, InterruptExecutor, Spawner};
use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::{Config, StackResources};
use embassy_rp::bind_interrupts;
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt;
use embassy_rp::interrupt::{InterruptExt, Priority};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::peripherals;
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::spi::{Phase, Polarity, Spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_time::Timer;
//use embedded_nal_async::TcpConnect;
//use embedded_nal_async::stack::tcp::TcpConnect;
use embedded_nal_async::TcpConnect;
use rand::RngCore;
use smart_leds::RGB8;
use static_cell::StaticCell;
use ws2812_async::{ColorOrder, Ws2812};
use {defmt_rtt as _, panic_probe as _};
use rust_mqtt::{
client::{client::MqttClient, client_config::ClientConfig},
utils::rng_generator::CountingRng,
};
//pub type RGB8 = RGB<u8>;
use {defmt_rtt as _, panic_probe as _};
// after observing somewhat jumpy behavior of the neopixel task, I decided to set the scheduler and orhestrator to high priority
// hight priority runs on interrupt
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
// low priority runs in thread-mode
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
#[global_allocator]
static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new();
extern crate alloc;
#[interrupt]
unsafe fn SWI_IRQ_1() {
EXECUTOR_HIGH.on_interrupt()
}
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
const WIFI_NETWORK: &str = "cat";
const WIFI_PASSWORD: &str = "catcat123cat";
const CLIENT_ID: &str = "pico-495f6297-b962-4266-9c00-74138ae5a1f1";
const TOPIC: &str = "hello";
const NUM_LEDS: usize = 100;
static CHANNEL: embassy_sync::channel::Channel<ThreadModeRawMutex, LedStrip, 64> =
embassy_sync::channel::Channel::new();
#[embassy_executor::task]
async fn cyw43_task(
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
) -> ! {
runner.run().await
}
#[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>) -> ! {
runner.run().await
}
assign_resources! {
led_peripheral: LedPeripheral {
inner_spi: SPI1,
clk_pin: PIN_14, // this is just a dummy pin, the neopixel uses only the mosi pin
mosi_pin: PIN_15,
tx_dma_ch: DMA_CH1,
},
wifi: WifiResources {
pwr_pin: PIN_23,
cs_pin: PIN_25,
pio_sm: PIO0,
dio_pin: PIN_24,
clk_pin: PIN_29,
dma_ch: DMA_CH0,
},
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Main thread!");
let p = embassy_rp::init(Default::default());
let r = split_resources!(p);
interrupt::SWI_IRQ_1.set_priority(Priority::P2);
let executor = EXECUTOR_LOW.init(Executor::new());
executor.run(|spawner| {
// update the RTC
spawner.spawn(run_mqtt(spawner, r.wifi)).unwrap();
static mut CORE1_STACK: Stack<4096> = Stack::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
spawn_core1(
p.CORE1,
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
move || {
let executor1 = EXECUTOR1.init(Executor::new());
executor1
.run(|spawner| unwrap!(spawner.spawn(led_ctrl_core1_task(r.led_peripheral))));
},
);
});
}
#[embassy_executor::task]
pub async fn run_mqtt(spawner: Spawner, r: WifiResources) {
let mut rng = RoscRng;
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
info!("init wifi");
let pwr = Output::new(r.pwr_pin, Level::Low);
let cs = Output::new(r.cs_pin, Level::High);
let mut pio = Pio::new(r.pio_sm, Irqs);
let spi = PioSpi::new(
&mut pio.common,
pio.sm0,
pio.irq0,
cs,
r.dio_pin,
r.clk_pin,
r.dma_ch,
);
static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
unwrap!(spawner.spawn(cyw43_task(runner)));
control.init(clm).await;
control
.set_power_management(cyw43::PowerManagementMode::PowerSave)
.await;
let config = Config::dhcpv4(Default::default());
// Use static IP configuration instead of DHCP
//let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = rng.next_u64();
// Init network stack
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
let (stack, runner) = embassy_net::new(
net_device,
config,
RESOURCES.init(StackResources::new()),
seed,
);
unwrap!(spawner.spawn(net_task(runner)));
loop {
match control
.join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
.await
{
Ok(_) => break,
Err(err) => {
info!("join failed with status={}", err.status);
}
}
}
// Wait for DHCP, not necessary when using static IP
info!("waiting for DHCP...");
while !stack.is_config_up() {
Timer::after_millis(100).await;
}
info!("DHCP is now up!");
info!("waiting for link up...");
while !stack.is_link_up() {
Timer::after_millis(500).await;
}
info!("Link is up!");
info!("waiting for stack to be up...");
stack.wait_config_up().await;
info!("Stack is up!");
let tcp_state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let tcp_client = TcpClient::new(stack, &tcp_state);
let addr = embedded_nal_async::SocketAddr::new(
embedded_nal_async::Ipv4Addr::new(192, 168, 0, 104).into(),
1883,
);
// let connection = embedded_nal::TcpStream::connect(addr)
// .await
// .map_err(|_| ReasonCode::NetworkError)
// .unwrap();
//let connection = FromTokio::<TcpStream>::new(connection);
let mut config = ClientConfig::new(
rust_mqtt::client::client_config::MqttVersion::MQTTv5,
CountingRng(20000),
);
config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS0);
config.add_client_id(CLIENT_ID);
config.keep_alive = u16::MAX;
// config.add_username(USERNAME);
// config.add_password(PASSWORD);
config.max_packet_size = 400;
let mut recv_buffer = [0; 400];
let mut write_buffer = [0; 400];
//let r = tcp_client.connect(addr).await;
let r;
loop {
match tcp_client.connect(addr).await {
Ok(rp) => {
info!("Attempting to connect to mqtt broker");
r = rp;
break;
}
Err(err) => {
info!("Failed to join broker: {}. Trying again!", err);
Timer::after_millis(100).await;
}
};
}
let mut client: MqttClient<
'_,
embassy_net::tcp::client::TcpConnection<'_, 1, 1024, 1024>,
5,
CountingRng,
> = MqttClient::<_, 5, _>::new(r, &mut write_buffer, 512, &mut recv_buffer, 512, config);
loop {
match client.connect_to_broker().await {
Ok(_) => {
info!("CAT Connected to broker");
break;
}
Err(err) => {
info!("DOG connect_to_broker failed with status={}", err);
}
}
}
loop {
match client.subscribe_to_topic(TOPIC).await {
Ok(_) => {
info!("CAT subscribed to topic");
break;
}
Err(err) => {
info!("DOG subscribe_to_topic failed with status={}", err);
}
}
}
let mut old_msg = LedStrip::new(0);
loop {
info!("[RECEIVER] Waiting for new message");
let msg = client.receive_message().await;
info!("[RECEIVER] Received msg: {}", msg);
if msg.is_ok() {
let message = msg.unwrap();
info!("[RECEIVER] message has size: {}", message.1.len());
match bincode::decode_from_slice::<LedStrip, Configuration>(
message.1,
bincode::config::standard(),
) {
Ok(decoded) => {
if old_msg != decoded.0 {
CHANNEL.send(decoded.0.clone()).await;
old_msg = decoded.0;
info!("[RECEIVER] Sent message");
}
}
Err(_e) => {
info!("DOG");
}
}
} else {
warn!("[RECEIVER] Could not get message with error: {}", msg.err());
}
//Timer::after(Duration::from_secs(2)).await;
}
}
#[embassy_executor::task]
async fn led_ctrl_core1_task(led_peripheral: LedPeripheral) {
info!("Hello from core 1");
let mut current_ledstrip = LedStrip::new(0);
// Spi configuration for the neopixel
let mut spi_config = embassy_rp::spi::Config::default();
spi_config.frequency = 3_800_000;
spi_config.phase = Phase::CaptureOnFirstTransition;
spi_config.polarity = Polarity::IdleLow;
// let spi = embassy_rp::spi::Spi::new_txonly(led_peripheral.inner_spi, led_peripheral.clk_pin, led_peripheral.mosi_pin, led_peripheral.tx_dma_ch, spi_config);
let spi = Spi::new_txonly(
led_peripheral.inner_spi,
led_peripheral.clk_pin,
led_peripheral.mosi_pin,
led_peripheral.tx_dma_ch,
spi_config,
);
let mut np: Ws2812<_, { 12 * NUM_LEDS }> = Ws2812::new(spi);
np.set_color_order(ColorOrder::GRB);
let mut data = [RGB8::default(); NUM_LEDS];
for led in data.iter_mut().step_by(1) {
led.r = 250; // blue
led.g = 150; // red
led.b = 0; // green
}
//np.write(empty.iter().cloned()).await.ok();
//np.write(data.iter().cloned()).await.ok();
let mut rgb_arr: [RGB8; NUM_LEDS] = [RGB8::new(0, 0, 0); NUM_LEDS];
loop {
let rc = CHANNEL.receive().await;
info!("OCTOPUS yyyy");
if current_ledstrip != rc {
info!("OCTOPUS got a new led strip");
for i in 0..rc.leds.len() {
rgb_arr[i].r = rc.leds[i].r;
rgb_arr[i].g = rc.leds[i].g;
rgb_arr[i].b = rc.leds[i].b;
}
current_ledstrip = rc.clone();
info!("writing led!");
np.write(rgb_arr.iter().cloned()).await.ok();
// Timer::after(Duration::from_millis(0)).await;
}
}
}
#[derive(Debug, Decode, Clone, Copy, PartialEq)]
struct Led {
r: u8,
g: u8,
b: u8,
}
#[derive(Clone, Debug, Decode, PartialEq)]
pub struct LedStrip {
leds: [Led; NUM_LEDS],
}
impl LedStrip {
// naive inital start with uniform colour on entire strip
pub fn new(_r: u8) -> Self {
let arr: [Led; NUM_LEDS] = [Led { r: 0, g: 0, b: 0 }; NUM_LEDS];
LedStrip { leds: arr }
}
}

Some files were not shown because too many files have changed in this diff Show More