.github
.vscode
cyw43
cyw43-firmware
cyw43-pio
docs
modules
ROOT
examples
images
pages
basic_application.adoc
best_practices.adoc
bootloader.adoc
developer.adoc
developer_stm32.adoc
embassy_in_the_wild.adoc
examples.adoc
faq.adoc
getting_started.adoc
hal.adoc
index.adoc
layer_by_layer.adoc
new_project.adoc
nrf.adoc
project_structure.adoc
runtime.adoc
sharing_peripherals.adoc
stm32.adoc
time_keeping.adoc
nav.adoc
README.md
antora.yml
embassy-boot
embassy-boot-nrf
embassy-boot-rp
embassy-boot-stm32
embassy-embedded-hal
embassy-executor
embassy-executor-macros
embassy-futures
embassy-hal-internal
embassy-net
embassy-net-adin1110
embassy-net-driver
embassy-net-driver-channel
embassy-net-enc28j60
embassy-net-esp-hosted
embassy-net-ppp
embassy-net-tuntap
embassy-net-wiznet
embassy-nrf
embassy-rp
embassy-stm32
embassy-stm32-wpan
embassy-sync
embassy-time
embassy-time-driver
embassy-time-queue-driver
embassy-usb
embassy-usb-dfu
embassy-usb-driver
embassy-usb-logger
examples
tests
.gitattributes
.gitignore
LICENSE-APACHE
LICENSE-MIT
NOTICE.md
README.md
ci-nightly.sh
ci.sh
rust-toolchain-nightly.toml
rust-toolchain.toml
rustfmt.toml
New: delaying_a_task.adoc, copied as-is from the wiki and placed in the navigation until we have a better place for it (or remove/replace it) index: Tweaked the structure, added some content from the wiki, and made some general copy edits to improve clarity. getting_started.adoc: Corrected various out-of-date information, added troubleshooting tips from the wiki, added some new information, various other small edits. basic_application.adoc: Corrected out-of-date information, various clarifications and edits. After these changes, IMO most of the content on the github wiki is no longer necessary and can be removed for clarity. The few sections I didn‘t integrate or copy over were either out of date or unfinished.
82 lines
3.3 KiB
Plaintext
82 lines
3.3 KiB
Plaintext
= A basic Embassy application
|
||
|
||
So you've got one of the xref:examples.adoc[examples] running, but what now? Let's go through a simple Embassy application for the nRF52 DK to understand it better.
|
||
|
||
== Main
|
||
|
||
The full example can be found link:https://github.com/embassy-rs/embassy/tree/master/docs/modules/ROOT/examples/basic[here].
|
||
|
||
NOTE: If you’re using VS Code and rust-analyzer to view and edit the examples, you may need to make some changes to `.vscode/settings.json` to tell it which project we’re working on. Follow the instructions commented in that file to get rust-analyzer working correctly.
|
||
|
||
=== Bare metal
|
||
|
||
The first thing you’ll notice are two attributes at the top of the file. These tells the compiler that program has no access to std, and that there is no main function (because it is not run by an OS).
|
||
|
||
[source,rust]
|
||
----
|
||
include::example$basic/src/main.rs[lines="1..2"]
|
||
----
|
||
|
||
=== Rust Nightly
|
||
|
||
The next declaration is a Rust Unstable feature, which means that Embassy requires Rust Nightly:
|
||
|
||
[source,rust]
|
||
----
|
||
include::example$basic/src/main.rs[lines="3"]
|
||
----
|
||
|
||
=== Dealing with errors
|
||
|
||
Then, what follows are some declarations on how to deal with panics and faults. During development, a good practice is to rely on `defmt-rtt` and `panic-probe` to print diagnostics to the terminal:
|
||
|
||
[source,rust]
|
||
----
|
||
include::example$basic/src/main.rs[lines="10"]
|
||
----
|
||
|
||
=== Task declaration
|
||
|
||
After a bit of import declaration, the tasks run by the application should be declared:
|
||
|
||
[source,rust]
|
||
----
|
||
include::example$basic/src/main.rs[lines="12..20"]
|
||
----
|
||
|
||
An embassy task must be declared `async`, and may NOT take generic arguments. In this case, we are handed the LED that should be blinked and the interval of the blinking.
|
||
|
||
NOTE: Notice that there is no busy waiting going on in this task. It is using the Embassy timer to yield execution, allowing the microcontroller to sleep in between the blinking.
|
||
|
||
=== Main
|
||
|
||
The main entry point of an Embassy application is defined using the `#[embassy_executor::main]` macro. The entry point is passed a `Spawner`, which it can use to spawn other tasks.
|
||
|
||
We then initialize the HAL with a default config, which gives us a `Peripherals` struct we can use to access the MCU’s various peripherals. In this case, we want to configure one of the pins as a GPIO output driving the LED:
|
||
|
||
[source,rust]
|
||
----
|
||
include::example$basic/src/main.rs[lines="22..-1"]
|
||
----
|
||
|
||
What happens when the `blinker` task has been spawned and main returns? Well, the main entry point is actually just like any other task, except that you can only have one and it takes some specific type arguments. The magic lies within the `#[embassy_executor::main]` macro. The macro does the following:
|
||
|
||
. Creates an Embassy Executor
|
||
. Defines a main task for the entry point
|
||
. Runs the executor spawning the main task
|
||
|
||
There is also a way to run the executor without using the macro, in which case you have to create the `Executor` instance yourself.
|
||
|
||
== The Cargo.toml
|
||
|
||
The project definition needs to contain the embassy dependencies:
|
||
|
||
[source,toml]
|
||
----
|
||
include::example$basic/Cargo.toml[lines="9..11"]
|
||
----
|
||
|
||
Depending on your microcontroller, you may need to replace `embassy-nrf` with something else (`embassy-stm32` for STM32. Remember to update feature flags as well).
|
||
|
||
In this particular case, the nrf52840 chip is selected, and the RTC1 peripheral is used as the time driver.
|