aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-12-13 00:07:39 +0000
committerGitHub <[email protected]>2021-12-13 00:07:39 +0000
commit2a4a133b88402a513f1e2cbdd1c5dc29d057b8d5 (patch)
tree717130a0665c4936d2f83f76a011b4424cd6a36d
parent052abc918a987acb35d44dcd91d9db8a8aaf8ece (diff)
parentff82c76935d86b7444e6abc7296c4c3e09261484 (diff)
Merge #533
533: Book poc r=Dirbaio a=lulf This is a Proof of Concept for an embassy book. It's using Antora/Asciidoc. * Asciidoc because it's a single specification with a slightly richer feature set than markdown. * Antora because it allows keeping content in the embassy repo, while book definition in another repo (embassy-book). Using antora also allows for easy embedding of embassy doc in other projects, which I think in turn increases probability of upstream contributions. The sources of content are located in docs/ but could also be in a separate repo. However, keeping it in the embassy repo makes it easier to support one version of the book per embassy version in the future. At present, the book is automatically built every hour from this branch and published at: https://embassy-rs.github.io/embassy-book/embassy/dev/index.html Co-authored-by: Ulf Lilleengen <[email protected]> Co-authored-by: Ulf Lilleengen <[email protected]>
-rwxr-xr-xci.sh1
-rw-r--r--docs/antora.yml5
-rw-r--r--docs/modules/ROOT/examples/basic/.cargo/config.toml6
-rw-r--r--docs/modules/ROOT/examples/basic/Cargo.toml17
-rw-r--r--docs/modules/ROOT/examples/basic/src/main.rs33
l---------docs/modules/ROOT/examples/examples1
-rw-r--r--docs/modules/ROOT/images/embassy_executor.drawio1
-rw-r--r--docs/modules/ROOT/images/embassy_executor.pngbin0 -> 121382 bytes
-rw-r--r--docs/modules/ROOT/images/embassy_irq.drawio1
-rw-r--r--docs/modules/ROOT/images/embassy_irq.pngbin0 -> 134158 bytes
-rw-r--r--docs/modules/ROOT/nav.adoc8
-rw-r--r--docs/modules/ROOT/pages/basic_application.adoc72
-rw-r--r--docs/modules/ROOT/pages/examples.adoc11
-rw-r--r--docs/modules/ROOT/pages/getting_started.adoc59
-rw-r--r--docs/modules/ROOT/pages/hal.adoc9
-rw-r--r--docs/modules/ROOT/pages/index.adoc20
-rw-r--r--docs/modules/ROOT/pages/nrf.adoc25
-rw-r--r--docs/modules/ROOT/pages/runtime.adoc46
-rw-r--r--docs/modules/ROOT/pages/stm32.adoc24
-rw-r--r--docs/modules/ROOT/pages/traits.adoc9
20 files changed, 348 insertions, 0 deletions
diff --git a/ci.sh b/ci.sh
index ab0448721..2259d5b5f 100755
--- a/ci.sh
+++ b/ci.sh
@@ -48,6 +48,7 @@ cargo batch \
48 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt \ 48 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt \
49 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt \ 49 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt \
50 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt \ 50 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt \
51 --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \
51 --- build --release --manifest-path examples/std/Cargo.toml --target x86_64-unknown-linux-gnu --out-dir out/examples/std \ 52 --- build --release --manifest-path examples/std/Cargo.toml --target x86_64-unknown-linux-gnu --out-dir out/examples/std \
52 --- build --release --manifest-path examples/nrf/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf \ 53 --- build --release --manifest-path examples/nrf/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf \
53 --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \ 54 --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \
diff --git a/docs/antora.yml b/docs/antora.yml
new file mode 100644
index 000000000..807c97c3f
--- /dev/null
+++ b/docs/antora.yml
@@ -0,0 +1,5 @@
1name: embassy
2title: Embassy
3version: dev
4nav:
5 - modules/ROOT/nav.adoc
diff --git a/docs/modules/ROOT/examples/basic/.cargo/config.toml b/docs/modules/ROOT/examples/basic/.cargo/config.toml
new file mode 100644
index 000000000..c75b5c539
--- /dev/null
+++ b/docs/modules/ROOT/examples/basic/.cargo/config.toml
@@ -0,0 +1,6 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace nRF82840_xxAA with your chip as listed in `probe-run --list-chips`
3runner = "probe-run --chip nRF52840_xxAA"
4
5[build]
6target = "thumbv7em-none-eabi"
diff --git a/docs/modules/ROOT/examples/basic/Cargo.toml b/docs/modules/ROOT/examples/basic/Cargo.toml
new file mode 100644
index 000000000..0f1c30da3
--- /dev/null
+++ b/docs/modules/ROOT/examples/basic/Cargo.toml
@@ -0,0 +1,17 @@
1[package]
2authors = ["Dario Nieuwenhuis <[email protected]>"]
3edition = "2018"
4name = "embassy-basic-example"
5version = "0.1.0"
6
7[dependencies]
8embassy = { version = "0.1.0", path = "../../../../../embassy", features = ["defmt"] }
9embassy-nrf = { version = "0.1.0", path = "../../../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] }
10
11defmt = "0.3"
12defmt-rtt = "0.3"
13
14cortex-m = "0.7.3"
15cortex-m-rt = "0.7.0"
16embedded-hal = "0.2.6"
17panic-probe = { version = "0.3", features = ["print-defmt"] }
diff --git a/docs/modules/ROOT/examples/basic/src/main.rs b/docs/modules/ROOT/examples/basic/src/main.rs
new file mode 100644
index 000000000..2a9b1facc
--- /dev/null
+++ b/docs/modules/ROOT/examples/basic/src/main.rs
@@ -0,0 +1,33 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt_rtt as _; // global logger
6use panic_probe as _;
7
8use defmt::*;
9
10use embassy::executor::Spawner;
11use embassy::time::{Duration, Timer};
12use embassy_nrf::{
13 gpio::{Level, Output, OutputDrive},
14 peripherals::P0_13,
15 Peripherals,
16};
17use embedded_hal::digital::v2::OutputPin;
18
19#[embassy::task]
20async fn blinker(mut led: Output<'static, P0_13>, interval: Duration) {
21 loop {
22 unwrap!(led.set_high());
23 Timer::after(interval).await;
24 unwrap!(led.set_low());
25 Timer::after(interval).await;
26 }
27}
28
29#[embassy::main]
30async fn main(spawner: Spawner, p: Peripherals) {
31 let led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard);
32 unwrap!(spawner.spawn(blinker(led, Duration::from_millis(300))));
33}
diff --git a/docs/modules/ROOT/examples/examples b/docs/modules/ROOT/examples/examples
new file mode 120000
index 000000000..1929330b0
--- /dev/null
+++ b/docs/modules/ROOT/examples/examples
@@ -0,0 +1 @@
../../../../examples \ No newline at end of file
diff --git a/docs/modules/ROOT/images/embassy_executor.drawio b/docs/modules/ROOT/images/embassy_executor.drawio
new file mode 100644
index 000000000..b76587d97
--- /dev/null
+++ b/docs/modules/ROOT/images/embassy_executor.drawio
@@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2021-12-10T08:37:46.039Z" agent="5.0 (Macintosh)" etag="F30pje_XkDZMiNl31GPU" version="15.9.4" type="device"><diagram id="6eJnfHJiGOpK0Luz4X_S" name="Page-1">7Vnhb6IwFP9r+LgFKFX8OJ13u2S3LLcld98uFQo0Q2qgTt1ff2UUsa0IU5y6XLIs9PX1WX7v1997VQOMpsvvKZpFP6mPY8M2/aUBbg3bHjg9/j83rAoDdPuFIUyJX5isyvBE3rAwmsI6Jz7OJEdGaczITDZ6NEmwxyQbSlO6kN0CGsufOkMh1gxPHop162/is6iwutCs7HeYhFH5yZYpZqaodBaGLEI+XWyYwNgAo5RSVjxNlyMc59iVuBTrvtXMrjeW4oS1WfDAsjuIh89/fv8NyGhxv0zMH1dOEeUVxXPxwuMl9uaMpmLTbFUikdJ54uM8mGWA4SIiDD/NkJfPLnjquS1i01hMZy+YeZEYBCSORzTmMfNAIHA97Hm5E0vpC96YmbjQ4ciCodgVThle1r6utQaRkw/TKWbpiruUC3oC95UyXlRptMrcRBspLP2QYE64Dl2Byx8Evh/AGmpYP6PshVus42HtI+wGW7HueS6eBN1g7djnhnVPw1rDGCf+TS4QfOTFKMuIJ8Na5cDsCmTsa2KjQMx3SOeph5uPLENpiFkT3fSUpThGjLzK+9iGv1j6SAnf4TrVoC+nGlhKCov9i1WbcqQEcpoCFS+oBXqnw/p99mdIX2OIdc3HjzRfqlKF5+0eTXhl47TAGXlDk/cpU2YMikmY5HTiOcWcAcP8UBFeS27ExJT4fr5QZpNUwETkqmw0HMx69h+Q+oOOnlsnc/oRvLCSosqc3T+1zNl6/RZgP3QI9hGgA4OTQ/exEpHQJD+4PsqiNYbtikVb6dex28AGboGmtB2o6I6rpKa/r6KrgZzPVXQAWmSUp+FJDDMcTnkKxpVp+LGeQCJDJ/LUSYPgtmwQnJOyzlTIYu7LOqiIMmzHOp5ntNpwm+UOWf2Ge9b2DdftS/Uf7Ha37V3u/KHYb7cHRq8ezroHAjf87xdG/mrrISrbob3aH7WHEtjz4HBowNtdJaeuTWrsiQp1qC1QV+a12Td7Ug6sw5heutAgyPBxFE+/Up6J4n3ulQheguJB2HDhaat4XHpkmqoFuyPFU+u5ZTVIGNzpfyQN09s4W9awR05xkoRfRMVqbvUXrWL6jfFUKtahJrX9msY+qShZqijt2/zbaj9nH0eU1D7JsT9DZAYaQ2GrL4suR1fcJl2xXXjuQlLeN89ASE56AWwrPTU5/38BbNXeKBfA4yiPY2mUBl9LeRzT2KU85jXouRLuV/bpdIgPqx9sC/fqV28w/gc=</diagram></mxfile> \ No newline at end of file
diff --git a/docs/modules/ROOT/images/embassy_executor.png b/docs/modules/ROOT/images/embassy_executor.png
new file mode 100644
index 000000000..2a83a3adb
--- /dev/null
+++ b/docs/modules/ROOT/images/embassy_executor.png
Binary files differ
diff --git a/docs/modules/ROOT/images/embassy_irq.drawio b/docs/modules/ROOT/images/embassy_irq.drawio
new file mode 100644
index 000000000..aa439a8e6
--- /dev/null
+++ b/docs/modules/ROOT/images/embassy_irq.drawio
@@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2021-12-10T09:18:58.548Z" agent="5.0 (Macintosh)" etag="zuUk3bLZCCXvlBU683Ur" version="15.9.4" type="device"><diagram id="6eJnfHJiGOpK0Luz4X_S" name="Page-1">5VlNc9owEP01HJOxLdsxx0Bokpk0zZRM0p4ywl6wBmMRWWDIr6+EBf4QKQ6tIbQcPOittLLe7j5J0ELdyeKa4Wn4lQYQtSwjWLTQVcuy2rYrnhJYZoDjXWTAiJEgg8wc6JM3UKCh0BkJICl15JRGnEzLoE/jGHxewjBjNC13G9KoPOsUj0AD+j6OdPSZBDzMUM8xcvwGyChcz2wayjLB684KSEIc0LQAoV4LdRmlPPs2WXQhktytecnGfXnHunkxBjGvM+CeJzcOdB5/PL8MSTe9W8TG7ZmdeZnjaKYW3FuAP+OUqZfmyzUTjM7iAKQzs4U6aUg49KfYl9ZUhF5gIZ9EypyMgfuhagxJFHVpJHxKRyjA4A192YkzOoaCxfU9GAyFRV+bWu4cGIdFAVJrvQY6Ac6Wosva6irel5V2mofRXMcmLIRw3Q+rzBltXOfkii+K3w9w7WhcP+JkfOo829Zn49nVeNY4hji4lOIgWn6Ek4T4ZVrzGBgNkpzQGfNhd3VyzEbAd2cWBCUt00PGIMKczMvSto1/NfSBEvHKm1Cji3KokVkJYbYgNaooRRVH9i5H2Yo1R6t02Kxn/wy50DLEPG/JHHUjQXNnIMTPHfFV6DIkIPM19ECl/wwWkxcsepaJeNzhgdgQRUZBQt7wYGUyysmGIzKKZSaK/ACRPB1ZfERsQZfKMCFBIAeWE1FPq99Vg9of1Rvku1KNQq+dNX9UtZa+Fd1KPthsKjPnBseCgwZ3paHng7+1kAeeYztGM7sS8g6oli9P8/YrfvVf3O8/A3Y9f5oTdGZqtDeolrVJrkjZfvJp1dVPuxG5tNrlWIvD7znybNd01NPdUz1Rxa9nn+dOxdNuSky3JpClJZBTW0zvKSfD5SeS09oyWc7I9yvrAHK6dXL0f5X1Vg6cZsq6Un6ovecpCFX0wW7uFLSVHn3DtWXhPuMxnHztoWPWnn7RewBGpiEwLMf2OeY6wwc4yFy2u3avIywjhgMiCCyOWn2Ut756rRD74YxBYcQVYSJEhMpYppDkOr0jSB+7Qx7/VPQ575B/RT6do6qnXRE9ZO2pnm5VhquOGlZP/Q5p1T72XKaYyKXcipm//aOnH/eYCuyd7Oln513FauiyUpFgx9izLqvHo037QHXZ1kKPZF0Wfks48cLymiks0cz/i8iCkf+hg3q/AA==</diagram></mxfile> \ No newline at end of file
diff --git a/docs/modules/ROOT/images/embassy_irq.png b/docs/modules/ROOT/images/embassy_irq.png
new file mode 100644
index 000000000..154d336b6
--- /dev/null
+++ b/docs/modules/ROOT/images/embassy_irq.png
Binary files differ
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
new file mode 100644
index 000000000..98c4ee77f
--- /dev/null
+++ b/docs/modules/ROOT/nav.adoc
@@ -0,0 +1,8 @@
1* xref:runtime.adoc[Runtime]
2* xref:traits.adoc[APIs]
3* xref:hal.adoc[Hardware Abstraction Layer]
4** xref:nrf.adoc[nRF]
5** xref:stm32.adoc[STM32]
6* xref:getting_started.adoc[Getting started]
7** xref:basic_application.adoc[Basic application]
8* xref:examples.adoc[Examples]
diff --git a/docs/modules/ROOT/pages/basic_application.adoc b/docs/modules/ROOT/pages/basic_application.adoc
new file mode 100644
index 000000000..46a375c86
--- /dev/null
+++ b/docs/modules/ROOT/pages/basic_application.adoc
@@ -0,0 +1,72 @@
1= A basic Embassy application
2
3So 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.
4
5== Main
6
7The full example can be found link:https://github.com/embassy-rs/embassy/tree/book-poc/docs/modules/ROOT/examples/basic[here].
8
9=== Rust Nightly
10
11The first thing you'll notice is a few declarations stating that Embassy requires some nightly features:
12
13[source,rust]
14----
15include::example$basic/src/main.rs[lines="1..3"]
16----
17
18=== Dealing with errors
19
20Then, 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:
21
22[source,rust]
23----
24include::example$basic/src/main.rs[lines="5..6"]
25----
26
27=== Task declaration
28
29After a bit of import declaration, the tasks run by the application should be declared:
30
31[source,rust]
32----
33include::example$basic/src/main.rs[lines="18..27"]
34----
35
36An 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.
37
38NOTE: Notice that there is not 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.
39
40=== Main
41
42The main entry point of an Embassy application is defined using the `#[embassy::main]` macro. The entry point is also required to take a `Spawner` and a `Peripherals` argument.
43
44The `Spawner` is the way the main application spawns other tasks. The `Peripherals` type holds all peripherals that the application may use. In this case, we want to configure one of the pins as a GPIO output driving the LED:
45
46[source,rust]
47----
48include::example$basic/src/main.rs[lines="28..-1"]
49----
50
51
52What happens when the `blinker` task have 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::main]` macro. The macro does the following:
53
54. Creates an Embassy Executor instance
55. Initializes the microcontroller to get the `Peripherals`
56. Defines a main task for the entry point
57. Runs the executor spawning the main task
58
59There is also a way to run the executor without using the macro, in which case you have to create the `Executor` instance yourself.
60
61== The Cargo.toml
62
63The project definition needs to contain the embassy dependencies:
64
65[source,toml]
66----
67include::example$basic/Cargo.toml[lines="8..9"]
68----
69
70Depending on your microcontroller, you may need to replace `embassy-nrf` with something else (`embassy-stm32` for STM32. Remember to update feature flags as well).
71
72In this particular case, the nrf52840 chip is selected, and the RTC1 peripheral is used as the time driver.
diff --git a/docs/modules/ROOT/pages/examples.adoc b/docs/modules/ROOT/pages/examples.adoc
new file mode 100644
index 000000000..c852f5205
--- /dev/null
+++ b/docs/modules/ROOT/pages/examples.adoc
@@ -0,0 +1,11 @@
1= Examples
2
3Embassy provides examples for all HALs supported. You can find them in the `examples/` folder.
4
5
6Main loop example
7
8[source,rust]
9----
10include::example$examples/std/src/bin/tick.rs[]
11----
diff --git a/docs/modules/ROOT/pages/getting_started.adoc b/docs/modules/ROOT/pages/getting_started.adoc
new file mode 100644
index 000000000..760fe8601
--- /dev/null
+++ b/docs/modules/ROOT/pages/getting_started.adoc
@@ -0,0 +1,59 @@
1= Getting started
2
3So you want to try Embassy, great! To get started, there are a few tools you need to install:
4
5* link:https://rustup.rs/[rustup] - the Rust toolchain is needed to compile Rust code.
6* link:https://crates.io/crates/probe-run[probe-run] - to flash the firmware on your device. If you already have other tools like `OpenOCD` setup, you can use that as well.
7
8If you don't have any supported board, don't worry: you can also run embassy on your PC using the `std` examples.
9
10== Getting a board with examples
11
12Embassy supports many microcontroller families, but the easiest ways to get started is if you have one of the more common development kits.
13
14=== nRF kits
15
16* link:https://www.nordicsemi.com/Products/Development-hardware/nrf52-dk[nRF52 DK]
17* link:https://www.nordicsemi.com/Products/Development-hardware/nRF9160-DK[nRF9160 DK]
18
19=== STM32 kits
20
21* link:https://www.st.com/en/evaluation-tools/nucleo-h743zi.html[STM32 Nucleo-144 development board with STM32H743ZI MCU]
22* link:https://www.st.com/en/evaluation-tools/nucleo-f429zi.html[STM32 Nucleo-144 development board with STM32F429ZI MCU]
23* link:https://www.st.com/en/evaluation-tools/b-l4s5i-iot01a.html[STM32L4+ Discovery kit IoT node, low-power wireless, BLE, NFC, WiFi]
24* link:https://www.st.com/en/evaluation-tools/b-l072z-lrwan1.html[STM32L0 Discovery kit LoRa, Sigfox, low-power wireless]
25* link:https://www.st.com/en/evaluation-tools/nucleo-wl55jc.html[STM32 Nucleo-64 development board with STM32WL55JCI MCU]
26* link:https://www.st.com/en/evaluation-tools/b-u585i-iot02a.html[Discovery kit for IoT node with STM32U5 series]
27
28
29=== RP2040 kits
30
31* link:https://www.raspberrypi.com/products/raspberry-pi-pico/[Raspberry Pi Pico]
32
33== Running an example
34
35First you need to clone the [github repository];
36
37[source, bash]
38----
39git clone https://github.com/embassy-rs/embassy.git
40cd embassy
41----
42
43You can run an example by opening a terminal and entering the following commands:
44
45[source, bash]
46----
47cd examples/nrf
48DEFMT_LOG=info cargo run --bin blinky --release
49----
50
51IMPORTANT: The DEFMT_LOG environment variable controls the example log verbosity. If you do not specify it, you will not see anything logged to the console.
52
53== Whats next?
54
55Congratulations, you have your first Embassy application running! Here are some alternatives on where to go from here:
56
57* Read more about the xref:runtime.adoc[runtime].
58* Read more about the xref:hal.adoc[HAL].
59* Start xref:basic_application.adoc[writing your application].
diff --git a/docs/modules/ROOT/pages/hal.adoc b/docs/modules/ROOT/pages/hal.adoc
new file mode 100644
index 000000000..8e7fb8dba
--- /dev/null
+++ b/docs/modules/ROOT/pages/hal.adoc
@@ -0,0 +1,9 @@
1= Hardware Abstraction Layer (HAL)
2
3Embassy provides HAL's for several microcontroller families:
4
5* `embassy-nrf` for the nRF microcontroller sfrom Nordic Semiconductor
6* `embassy-stm32` for STM32 microcontrollers from ST Microelectronics
7* `embassy-rp` for the Raspberry Pi RP2040 microcontrollers
8
9These HALs implement async/await functionality for most peripherals while also implementing the async traits in Embassy.
diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc
new file mode 100644
index 000000000..9a14e465d
--- /dev/null
+++ b/docs/modules/ROOT/pages/index.adoc
@@ -0,0 +1,20 @@
1= Embassy
2
3Embassy is a project to make async/await a first-class option for embedded development.
4
5== What is async?
6
7Software written without async may block on I/O operations. In an std environment, such as a PC, software can handle this either by using threads or non-blocking operations.
8
9With threads, one thread blocks on an I/O operation, another is able to take its place. However, even on a PC, threads are relatively heavy, and therefore some programming languages, such as Go, have implemented a concept called coroutines or 'goroutines' that are much lighter and less-intensive than threads.
10
11The other way to handle blocking I/O operations is to support polling the state of the underlying peripherals to check whether it is available to perform the requested operation. In programming languages without builtin async support,
12this requires building a complex loop checking for events.
13
14In Rust, non-blocking operations can be implemented using async-await. Async-await works by transforming each async function into an object called a future. When a future blocks on I/O the future yields, and the scheduler, called an executor, can select a different future to execute. Compared to alternatives such as an RTOS, async can yield better performance and lower power consumption because the executor doesn't have to guess when a future is ready to execute. However, program size may be higher than other alternatives, which may be a problem for certain space-constrained devices with very low memory. On the devices Embassy supports, such as stm32 and nrf, memory is generally large enough to accommodate the modestly-increased program size.
15
16== What is Embassy?
17
18Embassy is an executor and a Hardware Access Layer (HAL). The executor is a scheduler that generally executes a fixed number of tasks, allocated at startup, though more can be added later. The HAL is an API that you can use to access peripherals, such as USART, UART, I2C, SPI, CAN, and USB. Embassy provides implementations of both async and blocking APIs where it makes sense. DMA (Direct Memory Access) is an example where async is a good fit, whereas GPIO states are a better fit for a blocking API.
19
20Embassy may also provide a system timer that you can use for both async and blocking delays. For less than one microsecond, blocking delays should be used because the cost of context-switching is too high and the executor will be unable to provide accurate timing.
diff --git a/docs/modules/ROOT/pages/nrf.adoc b/docs/modules/ROOT/pages/nrf.adoc
new file mode 100644
index 000000000..10fe54b47
--- /dev/null
+++ b/docs/modules/ROOT/pages/nrf.adoc
@@ -0,0 +1,25 @@
1= Embassy nRF HAL
2
3The link:https://github.com/embassy-rs/embassy/tree/master/embassy-nrf[Embassy nRF HAL] is based on the PACs (Peripheral Access Crate) from link:https://github.com/nrf-rs/[nrf-rs].
4
5== Timer driver
6
7The nRF timer driver operates at 32768 Hz by default.
8
9== Peripherals
10
11The following peripherals have a HAL implementation at present:
12
13* PWM
14* SPIM
15* QSPI
16* NVMC
17* GPIOTE
18* RNG
19* TIMER
20* WDT
21* TEMP
22* PPI
23* UARTE
24* TWIM
25* SAADC
diff --git a/docs/modules/ROOT/pages/runtime.adoc b/docs/modules/ROOT/pages/runtime.adoc
new file mode 100644
index 000000000..25feb9c29
--- /dev/null
+++ b/docs/modules/ROOT/pages/runtime.adoc
@@ -0,0 +1,46 @@
1= Embassy runtime
2
3The Embassy runtime is an async/await executor designed for embedded usage along with support functionality for interrupts and timers.
4
5== Features
6
7* No `alloc`, no heap needed. Task are statically allocated.
8* No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning.
9* Integrated timer queue: sleeping is easy, just do `Timer::after(Duration::from_secs(1)).await;`.
10* No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`.
11* Efficient polling: a wake will only poll the woken task, not all of them.
12* Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time.
13* Creating multiple executor instances is supported, to run tasks with multiple priority levels. This allows higher-priority tasks to preempt lower-priority tasks.
14
15== Executor
16
17The executor function is described below. The executor keeps a queue of tasks that it should poll. When a task is created, it is polled (1). The task will attempt to make progress until reaches a point where it would be blocked. This may happen whenever a task is .await'ing an async function. When that happens, the task yields execution by (2) returning `Poll::Pending`. Once a task yields, the executor enqueues the task at the end of the run queue, and proceeds to (3) poll the next task in the queue. If a task returns `Poll::Ready` it essentially means that the task is finished and will not be enqueued again.
18
19IMPORTANT: The executor relies on tasks not blocking indefinitely, as this prevents the executor to regain control and schedule another task.
20
21image::embassy_executor.png[Executor model]
22
23If you use the `#[embassy::main]` macro in your application, it creates the `Executor` for you and spawns the main entry point as the first task. You can also create the Executor manually, and you can in fact create multiple Executors.
24
25
26== Interrupts
27
28Interrupts are a common way for peripherals to signal completion of some operation and fits well with the async execution model. The following diagram describes a typical application flow where (1) a task is polled and is attempting to make progress. The task then (2) instructs the peripheral to perform some operation, and awaits. After some time has passede, (3) an interrupt is raised, marking the completion of the operation.
29
30The peripheral HAL then (4) ensures that interrupt signals are routed to to the peripheral and updating the peripheral state with the results of the operation. The executor is then (5) notified that the task should be polled, which it will do.
31
32image::embassy_irq.png[Interrupt handling]
33
34NOTE: There exists a special executor named `InterruptExecutor` which can be driven by an interrupt. This can be used to drive tasks at different priority levels by creating multiple `InterruptExecutor` instances.
35
36== Time
37
38Embassy features an internal timer queue enabled by the `time` feature flag. When enabled, Embassy assumes a time `Driver` implementation existing for the platform. Embassy provides time drivers for the nRF, STM32, RPi Pico, WASM and Std platforms.
39
40The timer driver implementations for the embedded platforms might support only a fixed number of alarms that can be set. Make sure the number of tasks you expect wanting to use the timer at the same time do not exceed this limit.
41
42The timer speed is configurable at compile time using the `time-tick-<frequency>`. At present, the the timer may be configured to run at 1000 Hz, 32768 Hz, or 1 MHz. Before changing the defaults, make sure the target HAL supports the particular frequency setting.
43
44
45
46NOTE: If you do not require timers in your application, not enabling the `time` feature can save some CPU cycles and reduce power usage.
diff --git a/docs/modules/ROOT/pages/stm32.adoc b/docs/modules/ROOT/pages/stm32.adoc
new file mode 100644
index 000000000..3d1fbfc8f
--- /dev/null
+++ b/docs/modules/ROOT/pages/stm32.adoc
@@ -0,0 +1,24 @@
1= Embassy STM32 HAL
2
3The link:https://github.com/embassy-rs/embassy/tree/master/embassy-stm32[Embassy STM32 HAL] is based on the `stm32-metapac` project.
4
5== The infinite variant problem
6
7STM32 microcontrollers comes in many families and flavors, and supporting all of them is a big undertaking. Embassy has taken advantage of the fact
8that the STM32 peripheral versions are shared across chip families. Instead of re-implementing the SPI
9peripheral for every STM32 chip family, embassy have a single SPI implementation that depends on
10code-generated register types that are identical for STM32 families with the same version of a given peripheral.
11
12=== The metapac
13
14The `stm32-metapac` module uses pre-generated chip and register definitions for STM32 chip families to generate register types. This is done at compile time based on Cargo feataure flags.
15
16The chip and register definitions are located in a separate module, `stm32-data`, which is modified whenever a bug is found in the definitions, or when adding support for new chip families.
17
18=== The HAL
19
20The `embassy-stm32` module contains the HAL implementation for all STM32 families. The implementation uses automatically derived feature flags to support the correct version of a given peripheral for a given chip family.
21
22== Timer driver
23
24The STM32 timer driver operates at 32768 Hz by default.
diff --git a/docs/modules/ROOT/pages/traits.adoc b/docs/modules/ROOT/pages/traits.adoc
new file mode 100644
index 000000000..96f3e88bb
--- /dev/null
+++ b/docs/modules/ROOT/pages/traits.adoc
@@ -0,0 +1,9 @@
1= Embassy Traits
2
3Embassy provides a set of traits and types specifically designed for `async` usage. Many of these futures will be upstreamed to the `embedded-hal` crate at some point in the future, probably when the required GAT (Generic Associated Types) feature is stabilized in Rust.
4
5* `embassy::io`: `AsyncBufRead`, `AsyncWrite`. Traits for byte-stream IO, essentially `no_std` compatible versions of `futures::io`. The primary reason for re-defining these traits is that the `futures::io` variant requires `std::io::Error`, which does not work in the `no_std` environment.
6* `embassy::traits`: Async traits for Flash, SPI, I2C, UART, RNG, GPIO and more.
7* `embassy::time`: Time `Driver` trait that is implemented for different platforms. Time in Embassy is represented using the `Duration` and `Instant` types.
8
9These traits are implemented by the platform-specific crates, such as `embassy-nrf` or `embassy-stm32`.