diff options
| author | jrmoulton <[email protected]> | 2025-06-10 15:47:54 -0600 |
|---|---|---|
| committer | jrmoulton <[email protected]> | 2025-06-10 15:48:36 -0600 |
| commit | cfad9798ff99d4de0571a512d156b5fe1ef1d427 (patch) | |
| tree | fc3bf670f82d139de19466cddad1e909db7f3d2e /docs | |
| parent | fc342915e6155dec7bafa3e135da7f37a9a07f5c (diff) | |
| parent | 6186d111a5c150946ee5b7e9e68d987a38c1a463 (diff) | |
merge new embassy changes
Diffstat (limited to 'docs')
22 files changed, 223 insertions, 124 deletions
diff --git a/docs/examples/basic/.cargo/config.toml b/docs/examples/basic/.cargo/config.toml index 8ca28df39..17616a054 100644 --- a/docs/examples/basic/.cargo/config.toml +++ b/docs/examples/basic/.cargo/config.toml | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | # replace nRF82840_xxAA with your chip as listed in `probe-run --list-chips` | 2 | # replace nRF82840_xxAA with your chip as listed in `probe-rs chip list` |
| 3 | runner = "probe-run --chip nRF52840_xxAA" | 3 | runner = "probe-rs run --chip nRF52840_xxAA" |
| 4 | 4 | ||
| 5 | [build] | 5 | [build] |
| 6 | target = "thumbv7em-none-eabi" | 6 | target = "thumbv7em-none-eabi" |
diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index 5d391adf3..f5cf2b231 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml | |||
| @@ -6,13 +6,13 @@ version = "0.1.0" | |||
| 6 | license = "MIT OR Apache-2.0" | 6 | license = "MIT OR Apache-2.0" |
| 7 | 7 | ||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | embassy-executor = { version = "0.6.0", path = "../../../embassy-executor", features = ["defmt", "integrated-timers", "arch-cortex-m", "executor-thread"] } | 9 | embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.3.2", path = "../../../embassy-time", features = ["defmt"] } | 10 | embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } |
| 11 | embassy-nrf = { version = "0.2.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } | 11 | embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } |
| 12 | 12 | ||
| 13 | defmt = "0.3" | 13 | defmt = "1.0.1" |
| 14 | defmt-rtt = "0.3" | 14 | defmt-rtt = "1.0.0" |
| 15 | 15 | ||
| 16 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 16 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 17 | cortex-m-rt = "0.7.0" | 17 | cortex-m-rt = "0.7.0" |
| 18 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
diff --git a/docs/examples/layer-by-layer/.cargo/config.toml b/docs/examples/layer-by-layer/.cargo/config.toml index 3012f05dc..f30d9e446 100644 --- a/docs/examples/layer-by-layer/.cargo/config.toml +++ b/docs/examples/layer-by-layer/.cargo/config.toml | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | runner = "probe-run --chip STM32L475VG" | 2 | # replace your chip as listed in `probe-rs chip list` |
| 3 | runner = "probe-rs run --chip STM32L475VG" | ||
| 3 | 4 | ||
| 4 | rustflags = [ | 5 | rustflags = [ |
| 5 | "-C", "link-arg=--nmagic", | 6 | "-C", "link-arg=--nmagic", |
diff --git a/docs/examples/layer-by-layer/Cargo.toml b/docs/examples/layer-by-layer/Cargo.toml index 0f233eae5..01666ec6e 100644 --- a/docs/examples/layer-by-layer/Cargo.toml +++ b/docs/examples/layer-by-layer/Cargo.toml | |||
| @@ -3,14 +3,9 @@ resolver = "2" | |||
| 3 | members = [ | 3 | members = [ |
| 4 | "blinky-pac", | 4 | "blinky-pac", |
| 5 | "blinky-hal", | 5 | "blinky-hal", |
| 6 | "blinky-irq", | ||
| 7 | "blinky-async", | 6 | "blinky-async", |
| 8 | ] | 7 | ] |
| 9 | 8 | ||
| 10 | [patch.crates-io] | ||
| 11 | embassy-executor = { path = "../../../embassy-executor" } | ||
| 12 | embassy-stm32 = { path = "../../../embassy-stm32" } | ||
| 13 | |||
| 14 | [profile.release] | 9 | [profile.release] |
| 15 | codegen-units = 1 | 10 | codegen-units = 1 |
| 16 | debug = 2 | 11 | debug = 2 |
diff --git a/docs/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/examples/layer-by-layer/blinky-async/Cargo.toml index 7f8d8af3e..2a6741b33 100644 --- a/docs/examples/layer-by-layer/blinky-async/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-async/Cargo.toml | |||
| @@ -5,11 +5,11 @@ edition = "2021" | |||
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | cortex-m = "0.7" | 8 | cortex-m = { version = "0.7", features = ["critical-section-single-core"] } |
| 9 | cortex-m-rt = "0.7" | 9 | cortex-m-rt = "0.7" |
| 10 | embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] } | 10 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "exti"] } |
| 11 | embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", "executor-thread"] } | 11 | embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 12 | 12 | ||
| 13 | defmt = "0.3.0" | 13 | defmt = "1.0.1" |
| 14 | defmt-rtt = "0.3.0" | 14 | defmt-rtt = "1.0.0" |
| 15 | panic-probe = { version = "0.3.0", features = ["print-defmt"] } | 15 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
diff --git a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml index c15de2db2..9a261f804 100644 --- a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml | |||
| @@ -5,10 +5,10 @@ edition = "2021" | |||
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | cortex-m = "0.7" | ||
| 9 | cortex-m-rt = "0.7" | 8 | cortex-m-rt = "0.7" |
| 10 | embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x"] } | 9 | cortex-m = { version = "0.7", features = ["critical-section-single-core"] } |
| 10 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x"] } | ||
| 11 | 11 | ||
| 12 | defmt = "0.3.0" | 12 | defmt = "1.0.1" |
| 13 | defmt-rtt = "0.3.0" | 13 | defmt-rtt = "1.0.0" |
| 14 | panic-probe = { version = "0.3.0", features = ["print-defmt"] } | 14 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
diff --git a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml index 9733658b6..c3ec9ad1a 100644 --- a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | [workspace] | ||
| 2 | |||
| 1 | [package] | 3 | [package] |
| 2 | name = "blinky-irq" | 4 | name = "blinky-irq" |
| 3 | version = "0.1.0" | 5 | version = "0.1.0" |
| @@ -5,10 +7,10 @@ edition = "2021" | |||
| 5 | license = "MIT OR Apache-2.0" | 7 | license = "MIT OR Apache-2.0" |
| 6 | 8 | ||
| 7 | [dependencies] | 9 | [dependencies] |
| 8 | cortex-m = "0.7" | 10 | cortex-m = { version = "0.7", features = ["critical-section-single-core"] } |
| 9 | cortex-m-rt = { version = "0.7" } | 11 | cortex-m-rt = { version = "0.7" } |
| 10 | embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "unstable-pac"] } | 12 | embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "unstable-pac"] } |
| 11 | 13 | ||
| 12 | defmt = "0.3.0" | 14 | defmt = "1.0.1" |
| 13 | defmt-rtt = "0.3.0" | 15 | defmt-rtt = "1.0.0" |
| 14 | panic-probe = { version = "0.3.0", features = ["print-defmt"] } | 16 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
diff --git a/docs/examples/layer-by-layer/blinky-pac/Cargo.toml b/docs/examples/layer-by-layer/blinky-pac/Cargo.toml index f872b94cb..4e7e2f2ff 100644 --- a/docs/examples/layer-by-layer/blinky-pac/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-pac/Cargo.toml | |||
| @@ -5,10 +5,10 @@ edition = "2021" | |||
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | cortex-m = "0.7" | 8 | cortex-m = { version = "0.7", features = ["critical-section-single-core"] } |
| 9 | cortex-m-rt = "0.7" | 9 | cortex-m-rt = "0.7" |
| 10 | stm32-metapac = { version = "1", features = ["stm32l475vg", "memory-x"] } | 10 | stm32-metapac = { version = "16", features = ["stm32l475vg"] } |
| 11 | 11 | ||
| 12 | defmt = "0.3.0" | 12 | defmt = "1.0.1" |
| 13 | defmt-rtt = "0.3.0" | 13 | defmt-rtt = "1.0.0" |
| 14 | panic-probe = { version = "0.3.0", features = ["print-defmt"] } | 14 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
diff --git a/docs/examples/layer-by-layer/blinky-pac/src/main.rs b/docs/examples/layer-by-layer/blinky-pac/src/main.rs index 990d46cb6..cfbd91306 100644 --- a/docs/examples/layer-by-layer/blinky-pac/src/main.rs +++ b/docs/examples/layer-by-layer/blinky-pac/src/main.rs | |||
| @@ -8,46 +8,38 @@ use {defmt_rtt as _, panic_probe as _, stm32_metapac as pac}; | |||
| 8 | fn main() -> ! { | 8 | fn main() -> ! { |
| 9 | // Enable GPIO clock | 9 | // Enable GPIO clock |
| 10 | let rcc = pac::RCC; | 10 | let rcc = pac::RCC; |
| 11 | unsafe { | 11 | rcc.ahb2enr().modify(|w| { |
| 12 | rcc.ahb2enr().modify(|w| { | 12 | w.set_gpioben(true); |
| 13 | w.set_gpioben(true); | 13 | w.set_gpiocen(true); |
| 14 | w.set_gpiocen(true); | 14 | }); |
| 15 | }); | ||
| 16 | 15 | ||
| 17 | rcc.ahb2rstr().modify(|w| { | 16 | rcc.ahb2rstr().modify(|w| { |
| 18 | w.set_gpiobrst(true); | 17 | w.set_gpiobrst(true); |
| 19 | w.set_gpiocrst(true); | 18 | w.set_gpiocrst(true); |
| 20 | w.set_gpiobrst(false); | 19 | w.set_gpiobrst(false); |
| 21 | w.set_gpiocrst(false); | 20 | w.set_gpiocrst(false); |
| 22 | }); | 21 | }); |
| 23 | } | ||
| 24 | 22 | ||
| 25 | // Setup button | 23 | // Setup button |
| 26 | let gpioc = pac::GPIOC; | 24 | let gpioc = pac::GPIOC; |
| 27 | const BUTTON_PIN: usize = 13; | 25 | const BUTTON_PIN: usize = 13; |
| 28 | unsafe { | 26 | gpioc.pupdr().modify(|w| w.set_pupdr(BUTTON_PIN, vals::Pupdr::PULL_UP)); |
| 29 | gpioc.pupdr().modify(|w| w.set_pupdr(BUTTON_PIN, vals::Pupdr::PULLUP)); | 27 | gpioc.otyper().modify(|w| w.set_ot(BUTTON_PIN, vals::Ot::PUSH_PULL)); |
| 30 | gpioc.otyper().modify(|w| w.set_ot(BUTTON_PIN, vals::Ot::PUSHPULL)); | 28 | gpioc.moder().modify(|w| w.set_moder(BUTTON_PIN, vals::Moder::INPUT)); |
| 31 | gpioc.moder().modify(|w| w.set_moder(BUTTON_PIN, vals::Moder::INPUT)); | ||
| 32 | } | ||
| 33 | 29 | ||
| 34 | // Setup LED | 30 | // Setup LED |
| 35 | let gpiob = pac::GPIOB; | 31 | let gpiob = pac::GPIOB; |
| 36 | const LED_PIN: usize = 14; | 32 | const LED_PIN: usize = 14; |
| 37 | unsafe { | 33 | gpiob.pupdr().modify(|w| w.set_pupdr(LED_PIN, vals::Pupdr::FLOATING)); |
| 38 | gpiob.pupdr().modify(|w| w.set_pupdr(LED_PIN, vals::Pupdr::FLOATING)); | 34 | gpiob.otyper().modify(|w| w.set_ot(LED_PIN, vals::Ot::PUSH_PULL)); |
| 39 | gpiob.otyper().modify(|w| w.set_ot(LED_PIN, vals::Ot::PUSHPULL)); | 35 | gpiob.moder().modify(|w| w.set_moder(LED_PIN, vals::Moder::OUTPUT)); |
| 40 | gpiob.moder().modify(|w| w.set_moder(LED_PIN, vals::Moder::OUTPUT)); | ||
| 41 | } | ||
| 42 | 36 | ||
| 43 | // Main loop | 37 | // Main loop |
| 44 | loop { | 38 | loop { |
| 45 | unsafe { | 39 | if gpioc.idr().read().idr(BUTTON_PIN) == vals::Idr::LOW { |
| 46 | if gpioc.idr().read().idr(BUTTON_PIN) == vals::Idr::LOW { | 40 | gpiob.bsrr().write(|w| w.set_bs(LED_PIN, true)); |
| 47 | gpiob.bsrr().write(|w| w.set_bs(LED_PIN, true)); | 41 | } else { |
| 48 | } else { | 42 | gpiob.bsrr().write(|w| w.set_br(LED_PIN, true)); |
| 49 | gpiob.bsrr().write(|w| w.set_br(LED_PIN, true)); | ||
| 50 | } | ||
| 51 | } | 43 | } |
| 52 | } | 44 | } |
| 53 | } | 45 | } |
diff --git a/docs/examples/layer-by-layer/memory.x b/docs/examples/layer-by-layer/memory.x new file mode 100644 index 000000000..69f5b28a1 --- /dev/null +++ b/docs/examples/layer-by-layer/memory.x | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x08000000, LENGTH = 2048K /* BANK_1 */ | ||
| 4 | RAM : ORIGIN = 0x20000000, LENGTH = 640K /* SRAM */ | ||
| 5 | } | ||
diff --git a/docs/pages/best_practices.adoc b/docs/pages/best_practices.adoc index bfcedec06..eabaa9eb9 100644 --- a/docs/pages/best_practices.adoc +++ b/docs/pages/best_practices.adoc | |||
| @@ -35,7 +35,7 @@ After the processing, another 1024 byte buffer will be placed on the stack to be | |||
| 35 | 35 | ||
| 36 | Pass the data by reference and not by value on both, the way in and the way out. | 36 | Pass the data by reference and not by value on both, the way in and the way out. |
| 37 | For example, you could return a slice of the input buffer as the output. | 37 | For example, you could return a slice of the input buffer as the output. |
| 38 | Requiring the lifetime of the input slice and the output slice to be the same, the memory safetly of this procedure will be enforced by the compiler. | 38 | Requiring the lifetime of the input slice and the output slice to be the same, the memory safety of this procedure will be enforced by the compiler. |
| 39 | 39 | ||
| 40 | [,rust] | 40 | [,rust] |
| 41 | ---- | 41 | ---- |
diff --git a/docs/pages/bootloader.adoc b/docs/pages/bootloader.adoc index 3b0cdb182..b0f0331aa 100644 --- a/docs/pages/bootloader.adoc +++ b/docs/pages/bootloader.adoc | |||
| @@ -2,6 +2,13 @@ | |||
| 2 | 2 | ||
| 3 | `embassy-boot` a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks. | 3 | `embassy-boot` a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks. |
| 4 | 4 | ||
| 5 | The update method used is referred to as an A/B partition update scheme. | ||
| 6 | |||
| 7 | With a general-purpose OS, A/B partition update is accomplished by directly booting either the A or B partition depending on the update state. | ||
| 8 | To accomplish the same goal in a way that is portable across all microcontrollers, `embassy-boot` swaps data page by page (in both directions) between the DFU and the Active partition when a firmware update is triggered. + | ||
| 9 | Because the original Active application is moved into the DFU partition during this update, the operation can be reversed if the update is interrupted or the new firmware does not flag that it booted successfully. + | ||
| 10 | See the design section for more details on how this is implemented. | ||
| 11 | |||
| 5 | The bootloader can be used either as a library or be flashed directly if you are happy with the default configuration and capabilities. | 12 | The bootloader can be used either as a library or be flashed directly if you are happy with the default configuration and capabilities. |
| 6 | 13 | ||
| 7 | By design, the bootloader does not provide any network capabilities. Networking capabilities for fetching new firmware can be provided by the user application, using the bootloader as a library for updating the firmware, or by using the bootloader as a library and adding this capability yourself. | 14 | By design, the bootloader does not provide any network capabilities. Networking capabilities for fetching new firmware can be provided by the user application, using the bootloader as a library for updating the firmware, or by using the bootloader as a library and adding this capability yourself. |
| @@ -19,6 +26,8 @@ The bootloader supports | |||
| 19 | 26 | ||
| 20 | In general, the bootloader works on any platform that implements the `embedded-storage` traits for its internal flash, but may require custom initialization code to work. | 27 | In general, the bootloader works on any platform that implements the `embedded-storage` traits for its internal flash, but may require custom initialization code to work. |
| 21 | 28 | ||
| 29 | STM32L0x1 devices require the `flash-erase-zero` feature to be enabled. | ||
| 30 | |||
| 22 | == Design | 31 | == Design |
| 23 | 32 | ||
| 24 | image::bootloader_flash.png[Bootloader flash layout] | 33 | image::bootloader_flash.png[Bootloader flash layout] |
| @@ -86,8 +95,7 @@ Then, to sign your firmware given a declaration of `FIRMWARE_DIR` and a firmware | |||
| 86 | 95 | ||
| 87 | [source, bash] | 96 | [source, bash] |
| 88 | ---- | 97 | ---- |
| 89 | shasum -a 512 -b $FIRMWARE_DIR/myfirmware > $SECRETS_DIR/message.txt | 98 | shasum -a 512 -b $FIRMWARE_DIR/myfirmware | head -c128 | xxd -p -r > $SECRETS_DIR/message.txt |
| 90 | cat $SECRETS_DIR/message.txt | dd ibs=128 count=1 | xxd -p -r > $SECRETS_DIR/message.txt | ||
| 91 | signify -S -s $SECRETS_DIR/key.sec -m $SECRETS_DIR/message.txt -x $SECRETS_DIR/message.txt.sig | 99 | signify -S -s $SECRETS_DIR/key.sec -m $SECRETS_DIR/message.txt -x $SECRETS_DIR/message.txt.sig |
| 92 | cp $FIRMWARE_DIR/myfirmware $FIRMWARE_DIR/myfirmware+signed | 100 | cp $FIRMWARE_DIR/myfirmware $FIRMWARE_DIR/myfirmware+signed |
| 93 | tail -n1 $SECRETS_DIR/message.txt.sig | base64 -d -i - | dd ibs=10 skip=1 >> $FIRMWARE_DIR/myfirmware+signed | 101 | tail -n1 $SECRETS_DIR/message.txt.sig | base64 -d -i - | dd ibs=10 skip=1 >> $FIRMWARE_DIR/myfirmware+signed |
diff --git a/docs/pages/embassy_in_the_wild.adoc b/docs/pages/embassy_in_the_wild.adoc index 76b1169bd..620794c31 100644 --- a/docs/pages/embassy_in_the_wild.adoc +++ b/docs/pages/embassy_in_the_wild.adoc | |||
| @@ -2,6 +2,10 @@ | |||
| 2 | 2 | ||
| 3 | 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]! | 3 | 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]! |
| 4 | 4 | ||
| 5 | * link:https://github.com/1-rafael-1/simple-robot[A simple tracked robot based on Raspberry Pi Pico 2] | ||
| 6 | ** A hobbyist project building a tracked robot with basic autonomous and manual drive mode. | ||
| 7 | * link:https://github.com/1-rafael-1/pi-pico-alarmclock-rust[A Raspberry Pi Pico W Alarmclock] | ||
| 8 | ** A hobbyist project building an alarm clock around a Pi Pico W complete with code, components list and enclosure design files. | ||
| 5 | * link:https://github.com/haobogu/rmk/[RMK: A feature-rich Rust keyboard firmware] | 9 | * link:https://github.com/haobogu/rmk/[RMK: A feature-rich Rust keyboard firmware] |
| 6 | ** RMK has built-in layer support, wireless(BLE) support, real-time key editing support using vial, and more! | 10 | ** RMK has built-in layer support, wireless(BLE) support, real-time key editing support using vial, and more! |
| 7 | ** Targets STM32, RP2040, nRF52 and ESP32 MCUs | 11 | ** Targets STM32, RP2040, nRF52 and ESP32 MCUs |
diff --git a/docs/pages/faq.adoc b/docs/pages/faq.adoc index 4ab04e2a1..b21be9a30 100644 --- a/docs/pages/faq.adoc +++ b/docs/pages/faq.adoc | |||
| @@ -4,7 +4,7 @@ These are a list of unsorted, commonly asked questions and answers. | |||
| 4 | 4 | ||
| 5 | Please feel free to add items to link:https://github.com/embassy-rs/embassy/edit/main/docs/pages/faq.adoc[this page], especially if someone in the chat answered a question for you! | 5 | Please feel free to add items to link:https://github.com/embassy-rs/embassy/edit/main/docs/pages/faq.adoc[this page], especially if someone in the chat answered a question for you! |
| 6 | 6 | ||
| 7 | == How to deploy to RP2040 without a debugging probe. | 7 | == How to deploy to RP2040 or RP235x without a debugging probe. |
| 8 | 8 | ||
| 9 | Install link:https://github.com/JoNil/elf2uf2-rs[elf2uf2-rs] for converting the generated elf binary into a uf2 file. | 9 | Install link:https://github.com/JoNil/elf2uf2-rs[elf2uf2-rs] for converting the generated elf binary into a uf2 file. |
| 10 | 10 | ||
| @@ -92,17 +92,9 @@ If you see linker error like this: | |||
| 92 | >>> referenced by driver.rs:127 (src/driver.rs:127) | 92 | >>> referenced by driver.rs:127 (src/driver.rs:127) |
| 93 | >>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::now::hefb1f99d6e069842) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib | 93 | >>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::now::hefb1f99d6e069842) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib |
| 94 | 94 | ||
| 95 | rust-lld: error: undefined symbol: _embassy_time_allocate_alarm | 95 | rust-lld: error: undefined symbol: _embassy_time_schedule_wake |
| 96 | >>> referenced by driver.rs:134 (src/driver.rs:134) | ||
| 97 | >>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::allocate_alarm::hf5145b6bd46706b2) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib | ||
| 98 | |||
| 99 | rust-lld: error: undefined symbol: _embassy_time_set_alarm_callback | ||
| 100 | >>> referenced by driver.rs:139 (src/driver.rs:139) | ||
| 101 | >>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::set_alarm_callback::h24f92388d96eafd2) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib | ||
| 102 | |||
| 103 | rust-lld: error: undefined symbol: _embassy_time_set_alarm | ||
| 104 | >>> referenced by driver.rs:144 (src/driver.rs:144) | 96 | >>> referenced by driver.rs:144 (src/driver.rs:144) |
| 105 | >>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::set_alarm::h530a5b1f444a6d5b) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib | 97 | >>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::schedule_wake::h530a5b1f444a6d5b) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib |
| 106 | ---- | 98 | ---- |
| 107 | 99 | ||
| 108 | You probably need to enable a time driver for your HAL (not in `embassy-time`!). For example with `embassy-stm32`, you might need to enable `time-driver-any`: | 100 | You probably need to enable a time driver for your HAL (not in `embassy-time`!). For example with `embassy-stm32`, you might need to enable `time-driver-any`: |
| @@ -125,6 +117,20 @@ If you are in the early project setup phase and not using anything from the HAL, | |||
| 125 | use embassy_stm32 as _; | 117 | use embassy_stm32 as _; |
| 126 | ---- | 118 | ---- |
| 127 | 119 | ||
| 120 | Another common error you may experience is: | ||
| 121 | |||
| 122 | [source,text] | ||
| 123 | ---- | ||
| 124 | = note: rust-lld: error: undefined symbol: __pender | ||
| 125 | >>> referenced by mod.rs:373 (src/raw/mod.rs:373) | ||
| 126 | >>> embassy_executor-e78174e249bca7f4.embassy_executor.1e9d60fc90940543-cgu.0.rcgu.o:(embassy_executor::raw::Pender::pend::h0f19b6e01762e4cd) in archive [...]libembassy_executor-e78174e249bca7f4.rlib | ||
| 127 | ---- | ||
| 128 | |||
| 129 | There are two possible causes to this error: | ||
| 130 | |||
| 131 | * You are using `embassy-executor` withuout enabling one of the architecture-specific features, but you are using a HAL that does not bring its own executors. For example, for Cortex-M (like the RP2040), you need to enable the `arch-cortex-m` feature of `embassy-executor`. | ||
| 132 | * You are not using `embassy-executor`. In this case, you need to enable the one of the `generic-queue-X` features of `embassy-time`. | ||
| 133 | |||
| 128 | == Error: `Only one package in the dependency graph may specify the same links value.` | 134 | == Error: `Only one package in the dependency graph may specify the same links value.` |
| 129 | 135 | ||
| 130 | You have multiple versions of the same crate in your dependency tree. This means that some of your | 136 | You have multiple versions of the same crate in your dependency tree. This means that some of your |
| @@ -140,9 +146,9 @@ Example: | |||
| 140 | [source,toml] | 146 | [source,toml] |
| 141 | ---- | 147 | ---- |
| 142 | [patch.crates-io] | 148 | [patch.crates-io] |
| 143 | embassy-time-queue-driver = { git = "https://github.com/embassy-rs/embassy.git", rev = "e5fdd35" } | 149 | embassy-time-queue-utils = { git = "https://github.com/embassy-rs/embassy.git", rev = "7f8af8a" } |
| 144 | embassy-time-driver = { git = "https://github.com/embassy-rs/embassy.git", rev = "e5fdd35" } | 150 | embassy-time-driver = { git = "https://github.com/embassy-rs/embassy.git", rev = "7f8af8a" } |
| 145 | # embassy-time = { git = "https://github.com/embassy-rs/embassy.git", rev = "e5fdd35" } | 151 | # embassy-time = { git = "https://github.com/embassy-rs/embassy.git", rev = "7f8af8a" } |
| 146 | ---- | 152 | ---- |
| 147 | 153 | ||
| 148 | Note that the git revision should match any other embassy patches or git dependencies that you are using! | 154 | Note that the git revision should match any other embassy patches or git dependencies that you are using! |
| @@ -158,35 +164,11 @@ Note that the git revision should match any other embassy patches or git depende | |||
| 158 | * Set the following keys in the `[unstable]` section of your `.cargo/config.toml` | 164 | * Set the following keys in the `[unstable]` section of your `.cargo/config.toml` |
| 159 | ** `build-std = ["core"]` | 165 | ** `build-std = ["core"]` |
| 160 | ** `build-std-features = ["panic_immediate_abort"]` | 166 | ** `build-std-features = ["panic_immediate_abort"]` |
| 161 | * Enable feature `embassy-time/generic-queue`, disable feature `embassy-executor/integrated-timers` | ||
| 162 | * When using `InterruptExecutor`: | 167 | * When using `InterruptExecutor`: |
| 163 | ** disable `executor-thread` | 168 | ** disable `executor-thread` |
| 164 | ** make `main`` spawn everything, then enable link:https://docs.rs/cortex-m/latest/cortex_m/peripheral/struct.SCB.html#method.set_sleeponexit[SCB.SLEEPONEXIT] and `loop { cortex_m::asm::wfi() }` | 169 | ** make `main` spawn everything, then enable link:https://docs.rs/cortex-m/latest/cortex_m/peripheral/struct.SCB.html#method.set_sleeponexit[SCB.SLEEPONEXIT] and `loop { cortex_m::asm::wfi() }` |
| 165 | ** *Note:* If you need 2 priority levels, using 2 interrupt executors is better than 1 thread executor + 1 interrupt executor. | 170 | ** *Note:* If you need 2 priority levels, using 2 interrupt executors is better than 1 thread executor + 1 interrupt executor. |
| 166 | 171 | ||
| 167 | == How do I set up the task arenas on stable? | ||
| 168 | |||
| 169 | When you aren't using the `nightly` feature of `embassy-executor`, the executor uses a bump allocator, which may require configuration. | ||
| 170 | |||
| 171 | Something like this error will occur at **compile time** if the task arena is *too large* for the target's RAM: | ||
| 172 | |||
| 173 | [source,plain] | ||
| 174 | ---- | ||
| 175 | rust-lld: error: section '.bss' will not fit in region 'RAM': overflowed by _ bytes | ||
| 176 | rust-lld: error: section '.uninit' will not fit in region 'RAM': overflowed by _ bytes | ||
| 177 | ---- | ||
| 178 | |||
| 179 | And this message will appear at **runtime** if the task arena is *too small* for the tasks running: | ||
| 180 | |||
| 181 | [source,plain] | ||
| 182 | ---- | ||
| 183 | ERROR panicked at 'embassy-executor: task arena is full. You must increase the arena size, see the documentation for details: https://docs.embassy.dev/embassy-executor/' | ||
| 184 | ---- | ||
| 185 | |||
| 186 | NOTE: If all tasks are spawned at startup, this panic will occur immediately. | ||
| 187 | |||
| 188 | Check out link:https://docs.embassy.dev/embassy-executor/git/cortex-m/index.html#task-arena[Task Arena Documentation] for more details. | ||
| 189 | |||
| 190 | == Can I use manual ISRs alongside Embassy? | 172 | == Can I use manual ISRs alongside Embassy? |
| 191 | 173 | ||
| 192 | Yes! This can be useful if you need to respond to an event as fast as possible, and the latency caused by the usual “ISR, wake, return from ISR, context switch to woken task” flow is too much for your application. Simply define a `#[interrupt] fn INTERRUPT_NAME() {}` handler as you would link:https://docs.rust-embedded.org/book/start/interrupts.html[in any other embedded rust project]. | 174 | Yes! This can be useful if you need to respond to an event as fast as possible, and the latency caused by the usual “ISR, wake, return from ISR, context switch to woken task” flow is too much for your application. Simply define a `#[interrupt] fn INTERRUPT_NAME() {}` handler as you would link:https://docs.rust-embedded.org/book/start/interrupts.html[in any other embedded rust project]. |
| @@ -230,7 +212,7 @@ _stack_start = ORIGIN(RAM) + LENGTH(RAM); | |||
| 230 | Please refer to the STM32 documentation for the specific values suitable for your board and setup. The STM32 Cube examples often contain a linker script `.ld` file. | 212 | Please refer to the STM32 documentation for the specific values suitable for your board and setup. The STM32 Cube examples often contain a linker script `.ld` file. |
| 231 | Look for the `MEMORY` section and try to determine the FLASH and RAM sizes and section start. | 213 | Look for the `MEMORY` section and try to determine the FLASH and RAM sizes and section start. |
| 232 | 214 | ||
| 233 | If you find a case where the memory.x is wrong, please report it on [this Github issue](https://github.com/embassy-rs/stm32-data/issues/301) so other users are not caught by surprise. | 215 | If you find a case where the memory.x is wrong, please report it on link:https://github.com/embassy-rs/stm32-data/issues/301[this Github issue] so other users are not caught by surprise. |
| 234 | 216 | ||
| 235 | == The USB examples are not working on my board, is there anything else I need to configure? | 217 | == The USB examples are not working on my board, is there anything else I need to configure? |
| 236 | 218 | ||
| @@ -286,7 +268,7 @@ General steps: | |||
| 286 | 1. Find out which memory region BDMA has access to. You can get this information from the bus matrix and the memory mapping table in the STM32 datasheet. | 268 | 1. Find out which memory region BDMA has access to. You can get this information from the bus matrix and the memory mapping table in the STM32 datasheet. |
| 287 | 2. Add the memory region to `memory.x`, you can modify the generated one from https://github.com/embassy-rs/stm32-data-generated/tree/main/data/chips. | 269 | 2. Add the memory region to `memory.x`, you can modify the generated one from https://github.com/embassy-rs/stm32-data-generated/tree/main/data/chips. |
| 288 | 3. You might need to modify `build.rs` to make cargo pick up the modified `memory.x`. | 270 | 3. You might need to modify `build.rs` to make cargo pick up the modified `memory.x`. |
| 289 | 4. In your code, access the defined memory region using `#[link_section = ".xxx"]` | 271 | 4. In your code, access the defined memory region using `#[unsafe(link_section = ".xxx")]` |
| 290 | 5. Copy data to that region before using BDMA. | 272 | 5. Copy data to that region before using BDMA. |
| 291 | 273 | ||
| 292 | See link:https://github.com/embassy-rs/embassy/blob/main/examples/stm32h7/src/bin/spi_bdma.rs[SMT32H7 SPI BDMA example] for more details. | 274 | See link:https://github.com/embassy-rs/embassy/blob/main/examples/stm32h7/src/bin/spi_bdma.rs[SMT32H7 SPI BDMA example] for more details. |
| @@ -361,4 +343,73 @@ Practically, there's not a LOT of difference either way - so go with what makes | |||
| 361 | 343 | ||
| 362 | == splitting peripherals resources between tasks | 344 | == splitting peripherals resources between tasks |
| 363 | 345 | ||
| 364 | There are two ways to split resources between tasks, either manually assigned or by a convenient macro. See link:https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/assign_resources.rs[this example] \ No newline at end of file | 346 | There are two ways to split resources between tasks, either manually assigned or by a convenient macro. See link:https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/assign_resources.rs[this example] |
| 347 | |||
| 348 | == My code/driver works in debug mode, but not release mode (or with LTO) | ||
| 349 | |||
| 350 | Issues like these while implementing drivers often fall into one of the following general causes, which are a good list of common errors to check for: | ||
| 351 | |||
| 352 | 1. Some kind of race condition - the faster code means you miss an interrupt or something | ||
| 353 | 2. Some kind of UB, if you have unsafe code, or something like DMA with fences missing | ||
| 354 | 3. Some kind of hardware errata, or some hardware misconfiguration like wrong clock speeds | ||
| 355 | 4. Some issue with an interrupt handler, either enabling, disabling, or re-enabling of interrupts when necessary | ||
| 356 | 5. Some kind of async issue, like not registering wakers fully before checking flags, or not registering or pending wakers at the right time | ||
| 357 | |||
| 358 | == How can I prevent the thread-mode executor from going to sleep? == | ||
| 359 | |||
| 360 | In some cases you might want to prevent the thread-mode executor from going to sleep, for example when doing so would result in current spikes that reduce analog performance. | ||
| 361 | As a workaround, you can spawn a task that yields in a loop, preventing the executor from going to sleep. Note that this may increase power consumption. | ||
| 362 | |||
| 363 | [source,rust] | ||
| 364 | ---- | ||
| 365 | #[embassy_executor::task] | ||
| 366 | async fn idle() { | ||
| 367 | loop { embassy_futures::yield_now().await; } | ||
| 368 | } | ||
| 369 | ---- | ||
| 370 | |||
| 371 | == Why is my bootloader restarting in loop? | ||
| 372 | |||
| 373 | == Troubleshooting Bootloader Restart Loops | ||
| 374 | |||
| 375 | If your bootloader restarts in a loop, there could be multiple reasons. Here are some things to check: | ||
| 376 | |||
| 377 | === Validate the `memory.x` File | ||
| 378 | The bootloader performs critical checks when creating partitions using the addresses defined in `memory.x`. Ensure the following assertions hold true: | ||
| 379 | |||
| 380 | [source,rust] | ||
| 381 | ---- | ||
| 382 | const { | ||
| 383 | core::assert!(Self::PAGE_SIZE % ACTIVE::WRITE_SIZE as u32 == 0); | ||
| 384 | core::assert!(Self::PAGE_SIZE % ACTIVE::ERASE_SIZE as u32 == 0); | ||
| 385 | core::assert!(Self::PAGE_SIZE % DFU::WRITE_SIZE as u32 == 0); | ||
| 386 | core::assert!(Self::PAGE_SIZE % DFU::ERASE_SIZE as u32 == 0); | ||
| 387 | } | ||
| 388 | |||
| 389 | // Ensure enough progress pages to store copy progress | ||
| 390 | assert_eq!(0, Self::PAGE_SIZE % aligned_buf.len() as u32); | ||
| 391 | assert!(aligned_buf.len() >= STATE::WRITE_SIZE); | ||
| 392 | assert_eq!(0, aligned_buf.len() % ACTIVE::WRITE_SIZE); | ||
| 393 | assert_eq!(0, aligned_buf.len() % DFU::WRITE_SIZE); | ||
| 394 | ---- | ||
| 395 | |||
| 396 | If any of these assertions fail, the bootloader will likely restart in a loop. This failure might not log any messages (e.g., when using `defmt`). Confirm that your `memory.x` file and flash memory align with these requirements. | ||
| 397 | |||
| 398 | === Handling Panic Logging | ||
| 399 | Some panic errors might log messages, but certain microcontrollers reset before the message is fully printed. To ensure panic messages are logged, add a delay using no-operation (NOP) instructions before the reset: | ||
| 400 | |||
| 401 | [source,rust] | ||
| 402 | ---- | ||
| 403 | #[panic_handler] | ||
| 404 | fn panic(_info: &core::panic::PanicInfo) -> ! { | ||
| 405 | for _ in 0..10_000_000 { | ||
| 406 | cortex_m::asm::nop(); | ||
| 407 | } | ||
| 408 | cortex_m::asm::udf(); | ||
| 409 | } | ||
| 410 | ---- | ||
| 411 | |||
| 412 | === Feed the watchdog | ||
| 413 | |||
| 414 | |||
| 415 | Some `embassy-boot` implementations (like `embassy-boot-nrf` and `embassy-boot-rp`) rely on a watchdog timer to detect application failure. The bootloader will restart if your application code does not properly feed the watchdog timer. Make sure to feed it correctly. | ||
diff --git a/docs/pages/getting_started.adoc b/docs/pages/getting_started.adoc index 017409018..d1f65a885 100644 --- a/docs/pages/getting_started.adoc +++ b/docs/pages/getting_started.adoc | |||
| @@ -66,7 +66,7 @@ If everything worked correctly, you should see a blinking LED on your board, and | |||
| 66 | [source] | 66 | [source] |
| 67 | ---- | 67 | ---- |
| 68 | Finished dev [unoptimized + debuginfo] target(s) in 1m 56s | 68 | Finished dev [unoptimized + debuginfo] target(s) in 1m 56s |
| 69 | Running `probe-run --chip STM32F407VGTx target/thumbv7em-none-eabi/debug/blinky` | 69 | Running `probe-rs run --chip STM32F407VGTx target/thumbv7em-none-eabi/debug/blinky` |
| 70 | (HOST) INFO flashing program (71.36 KiB) | 70 | (HOST) INFO flashing program (71.36 KiB) |
| 71 | (HOST) INFO success! | 71 | (HOST) INFO success! |
| 72 | ──────────────────────────────────────────────────────────────────────────────── | 72 | ──────────────────────────────────────────────────────────────────────────────── |
| @@ -86,7 +86,7 @@ NOTE: How does the `+cargo run+` command know how to connect to our board and pr | |||
| 86 | 86 | ||
| 87 | === It didn’t work! | 87 | === It didn’t work! |
| 88 | 88 | ||
| 89 | If you hare having issues when running `+cargo run --release+`, please check the following: | 89 | If you are having issues when running `+cargo run --release+`, please check the following: |
| 90 | 90 | ||
| 91 | * You are specifying the correct `+--chip+` on the command line, OR | 91 | * You are specifying the correct `+--chip+` on the command line, OR |
| 92 | * You have set `+.cargo/config.toml+`’s run line to the correct chip, AND | 92 | * You have set `+.cargo/config.toml+`’s run line to the correct chip, AND |
diff --git a/docs/pages/hal.adoc b/docs/pages/hal.adoc index 14b85e1f1..3bbe94e02 100644 --- a/docs/pages/hal.adoc +++ b/docs/pages/hal.adoc | |||
| @@ -4,7 +4,7 @@ Embassy provides HALs for several microcontroller families: | |||
| 4 | 4 | ||
| 5 | * `embassy-nrf` for the nRF microcontrollers from Nordic Semiconductor | 5 | * `embassy-nrf` for the nRF microcontrollers from Nordic Semiconductor |
| 6 | * `embassy-stm32` for STM32 microcontrollers from ST Microelectronics | 6 | * `embassy-stm32` for STM32 microcontrollers from ST Microelectronics |
| 7 | * `embassy-rp` for the Raspberry Pi RP2040 microcontrollers | 7 | * `embassy-rp` for the Raspberry Pi RP2040 and RP235x microcontrollers |
| 8 | 8 | ||
| 9 | These HALs implement async/await functionality for most peripherals while also implementing the | 9 | These HALs implement async/await functionality for most peripherals while also implementing the |
| 10 | async traits in `embedded-hal` and `embedded-hal-async`. You can also use these HALs with another executor. | 10 | async traits in `embedded-hal` and `embedded-hal-async`. You can also use these HALs with another executor. |
| @@ -12,3 +12,7 @@ async traits in `embedded-hal` and `embedded-hal-async`. You can also use these | |||
| 12 | For the ESP32 series, there is an link:https://github.com/esp-rs/esp-hal[esp-hal] which you can use. | 12 | For the ESP32 series, there is an link:https://github.com/esp-rs/esp-hal[esp-hal] which you can use. |
| 13 | 13 | ||
| 14 | For the WCH 32-bit RISC-V series, there is an link:https://github.com/ch32-rs/ch32-hal[ch32-hal], which you can use. | 14 | For the WCH 32-bit RISC-V series, there is an link:https://github.com/ch32-rs/ch32-hal[ch32-hal], which you can use. |
| 15 | |||
| 16 | For the Microchip PolarFire SoC, there is link:https://github.com/AlexCharlton/mpfs-hal[mpfs-hal]. | ||
| 17 | |||
| 18 | For the Puya Semiconductor PY32 series, there is link:https://github.com/py32-rs/py32-hal[py32-hal]. \ No newline at end of file | ||
diff --git a/docs/pages/imxrt.adoc b/docs/pages/imxrt.adoc new file mode 100644 index 000000000..87867e1e0 --- /dev/null +++ b/docs/pages/imxrt.adoc | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | = Embassy iMXRT HAL | ||
| 2 | |||
| 3 | The link: link:https://github.com/embassy-rs/embassy/tree/main/embassy-imxrt[Embassy iMXRT HAL] is based on the following PACs (Peripheral Access Crate): | ||
| 4 | |||
| 5 | * link:https://github.com/OpenDevicePartnership/mimxrt685s-pac[mimxrt685s-pac] | ||
| 6 | * link:https://github.com/OpenDevicePartnership/mimxrt633s-pac[mimxrt633s-pac] | ||
| 7 | |||
| 8 | == Peripherals | ||
| 9 | |||
| 10 | The following peripherals have a HAL implementation at present | ||
| 11 | |||
| 12 | * CRC | ||
| 13 | * DMA | ||
| 14 | * GPIO | ||
| 15 | * RNG | ||
| 16 | * UART | ||
diff --git a/docs/pages/layer_by_layer.adoc b/docs/pages/layer_by_layer.adoc index 7852d27b7..7dba11b5e 100644 --- a/docs/pages/layer_by_layer.adoc +++ b/docs/pages/layer_by_layer.adoc | |||
| @@ -76,7 +76,7 @@ The async version looks very similar to the HAL version, apart from a few minor | |||
| 76 | * The peripheral initialization is done by the main macro, and is handed to the main task. | 76 | * The peripheral initialization is done by the main macro, and is handed to the main task. |
| 77 | * Before checking the button state, the application is awaiting a transition in the pin state (low -> high or high -> low). | 77 | * Before checking the button state, the application is awaiting a transition in the pin state (low -> high or high -> low). |
| 78 | 78 | ||
| 79 | When `button.await_for_any_edge().await` is called, the executor will pause the main task and put the microcontroller in sleep mode, unless there are other tasks that can run. Internally, the Embassy HAL has configured the interrupt handler for the button (in `ExtiInput`), so that whenever an interrupt is raised, the task awaiting the button will be woken up. | 79 | When `button.wait_for_any_edge().await` is called, the executor will pause the main task and put the microcontroller in sleep mode, unless there are other tasks that can run. Internally, the Embassy HAL has configured the interrupt handler for the button (in `ExtiInput`), so that whenever an interrupt is raised, the task awaiting the button will be woken up. |
| 80 | 80 | ||
| 81 | The minimal overhead of the executor and the ability to run multiple tasks "concurrently" combined with the enormous simplification of the application, makes `async` a great fit for embedded. | 81 | The minimal overhead of the executor and the ability to run multiple tasks "concurrently" combined with the enormous simplification of the application, makes `async` a great fit for embedded. |
| 82 | 82 | ||
diff --git a/docs/pages/new_project.adoc b/docs/pages/new_project.adoc index 821bcbd27..cd943b4f6 100644 --- a/docs/pages/new_project.adoc +++ b/docs/pages/new_project.adoc | |||
| @@ -73,22 +73,34 @@ Now that cargo knows what target to compile for (and probe-rs knows what chip to | |||
| 73 | 73 | ||
| 74 | Looking in `examples/stm32g4/Cargo.toml`, we can see that the examples require a number of embassy crates. For blinky, we’ll only need three of them: `embassy-stm32`, `embassy-executor` and `embassy-time`. | 74 | Looking in `examples/stm32g4/Cargo.toml`, we can see that the examples require a number of embassy crates. For blinky, we’ll only need three of them: `embassy-stm32`, `embassy-executor` and `embassy-time`. |
| 75 | 75 | ||
| 76 | At the time of writing, the latest version of embassy isn‘t available on crates.io, so we need to install it straight from the git repository. The recommended way of doing so is as follows: | 76 | |
| 77 | At the time of writing, embassy is already published to crates.io. Therefore, dependencies can easily added via Cargo.toml. | ||
| 78 | |||
| 79 | [source,toml] | ||
| 80 | ---- | ||
| 81 | [dependencies] | ||
| 82 | embassy-stm32 = { version = "0.1.0", features = ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"] } | ||
| 83 | embassy-executor = { version = "0.6.3", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt"] } | ||
| 84 | embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||
| 85 | ---- | ||
| 86 | |||
| 87 | 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. | ||
| 88 | The recommended way of doing so is as follows: | ||
| 77 | 89 | ||
| 78 | * Copy the required `embassy-*` lines from the example `Cargo.toml` | 90 | * Copy the required `embassy-*` lines from the example `Cargo.toml` |
| 79 | * Make any necessary changes to `features`, e.g. requiring the `stm32g474re` feature of `embassy-stm32` | 91 | * Make any necessary changes to `features`, e.g. requiring the `stm32g474re` feature of `embassy-stm32` |
| 80 | * Remove the `path = ""` keys in the `embassy-*` entries | 92 | * Remove the `path = ""` keys in the `embassy-*` entries |
| 81 | * 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 we’re 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` | 93 | * 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 we’re 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` |
| 82 | 94 | ||
| 83 | NOTE: When using this method, it’s necessary that the `version` keys in `[dependencies]` match up with the versions defined in each crate’s `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. Hopefully this will no longer be necessary once embassy is released on crates.io! | 95 | NOTE: When using this method, it’s necessary that the `version` keys in `[dependencies]` match up with the versions defined in each crate’s `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. |
| 84 | 96 | ||
| 85 | At the time of writing, this method produces the following results: | 97 | An example Cargo.toml file might look as follows: |
| 86 | 98 | ||
| 87 | [source,toml] | 99 | [source,toml] |
| 88 | ---- | 100 | ---- |
| 89 | [dependencies] | 101 | [dependencies] |
| 90 | embassy-stm32 = {version = "0.1.0", features = ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"]} | 102 | embassy-stm32 = {version = "0.1.0", features = ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"]} |
| 91 | embassy-executor = { version = "0.3.3", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 103 | embassy-executor = { version = "0.3.3", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt"] } |
| 92 | embassy-time = { version = "0.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 104 | embassy-time = { version = "0.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 93 | 105 | ||
| 94 | [patch.crates-io] | 106 | [patch.crates-io] |
| @@ -97,7 +109,7 @@ embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "7703f | |||
| 97 | embassy-stm32 = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" } | 109 | embassy-stm32 = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" } |
| 98 | ---- | 110 | ---- |
| 99 | 111 | ||
| 100 | There are a few other dependencies we need to build the project, but fortunately they’re much simpler to install. Copy their lines from the example `Cargo.toml` to the the `[dependencies]` section in the new `Cargo.toml`: | 112 | There are a few other dependencies we need to build the project, but fortunately they’re much simpler to install. Copy their lines from the example `Cargo.toml` to the `[dependencies]` section in the new `Cargo.toml`: |
| 101 | 113 | ||
| 102 | [source,toml] | 114 | [source,toml] |
| 103 | ---- | 115 | ---- |
| @@ -138,7 +150,7 @@ stm32g474-example | |||
| 138 | # Before upgrading check that everything is available on all tier1 targets here: | 150 | # Before upgrading check that everything is available on all tier1 targets here: |
| 139 | # https://rust-lang.github.io/rustup-components-history | 151 | # https://rust-lang.github.io/rustup-components-history |
| 140 | [toolchain] | 152 | [toolchain] |
| 141 | channel = "nightly-2023-11-01" | 153 | channel = "1.85" |
| 142 | components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ] | 154 | components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ] |
| 143 | targets = ["thumbv7em-none-eabi"] | 155 | targets = ["thumbv7em-none-eabi"] |
| 144 | ---- | 156 | ---- |
diff --git a/docs/pages/overview.adoc b/docs/pages/overview.adoc index 7d59d5521..acd757795 100644 --- a/docs/pages/overview.adoc +++ b/docs/pages/overview.adoc | |||
| @@ -6,7 +6,7 @@ Embassy is a project to make async/await a first-class option for embedded devel | |||
| 6 | 6 | ||
| 7 | When handling I/O, software must call functions that block program execution until the I/O operation completes. When running inside of an OS such as Linux, such functions generally transfer control to the kernel so that another task (known as a “thread”) can be executed if available, or the CPU can be put to sleep until another task is ready. | 7 | When handling I/O, software must call functions that block program execution until the I/O operation completes. When running inside of an OS such as Linux, such functions generally transfer control to the kernel so that another task (known as a “thread”) can be executed if available, or the CPU can be put to sleep until another task is ready. |
| 8 | 8 | ||
| 9 | Because an OS cannot presume that threads will behave cooperatively, threads are relatively resource-intensive, and may be forcibly interrupted they do not transfer control back to the kernel within an allotted time. If tasks could be presumed to behave cooperatively, or at least not maliciously, it would be possible to create tasks that appear to be almost free when compared to a traditional OS thread. | 9 | Because an OS cannot presume that threads will behave cooperatively, threads are relatively resource-intensive, and may be forcibly interrupted if they do not transfer control back to the kernel within an allotted time. If tasks could be presumed to behave cooperatively, or at least not maliciously, it would be possible to create tasks that appear to be almost free when compared to a traditional OS thread. |
| 10 | 10 | ||
| 11 | In other programming languages, these lightweight tasks are known as “coroutines” or ”goroutines”. In Rust, they are implemented with async. 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. | 11 | In other programming languages, these lightweight tasks are known as “coroutines” or ”goroutines”. In Rust, they are implemented with async. 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. |
| 12 | 12 | ||
| @@ -28,9 +28,12 @@ The Embassy project maintains HALs for select hardware, but you can still use HA | |||
| 28 | 28 | ||
| 29 | * link:https://docs.embassy.dev/embassy-stm32/[embassy-stm32], for all STM32 microcontroller families. | 29 | * link:https://docs.embassy.dev/embassy-stm32/[embassy-stm32], for all STM32 microcontroller families. |
| 30 | * link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF91 series. | 30 | * link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF91 series. |
| 31 | * link:https://docs.embassy.dev/embassy-rp/[embassy-rp], for the Raspberry Pi RP2040 microcontroller. | 31 | * link:https://docs.embassy.dev/embassy-rp/[embassy-rp], for the Raspberry Pi RP2040 as well as RP235x microcontroller. |
| 32 | * link:https://docs.embassy.dev/embassy-mspm0/[embassy-mspm0], for the Texas Instruments MSPM0 microcontrollers. | ||
| 32 | * link:https://github.com/esp-rs[esp-rs], for the Espressif Systems ESP32 series of chips. | 33 | * link:https://github.com/esp-rs[esp-rs], for the Espressif Systems ESP32 series of chips. |
| 33 | * link:https://github.com/ch32-rs/ch32-hal[ch32-hal], for the WCH 32-bit RISC-V(CH32V) series of chips. | 34 | * link:https://github.com/ch32-rs/ch32-hal[ch32-hal], for the WCH 32-bit RISC-V(CH32V) series of chips. |
| 35 | * link:https://github.com/AlexCharlton/mpfs-hal[mpfs-hal], for the Microchip PolarFire SoC. | ||
| 36 | * link:https://github.com/py32-rs/py32-hal[py32-hal], for the Puya Semiconductor PY32 series of chips. | ||
| 34 | 37 | ||
| 35 | NOTE: A common question is if one can use the Embassy HALs standalone. Yes, it is possible! There are no dependency on the executor within the HALs. You can even use them without async, | 38 | NOTE: A common question is if one can use the Embassy HALs standalone. Yes, it is possible! There are no dependency on the executor within the HALs. You can even use them without async, |
| 36 | as they implement both the link:https://github.com/rust-embedded/embedded-hal[Embedded HAL] blocking and async traits. | 39 | as they implement both the link:https://github.com/rust-embedded/embedded-hal[Embedded HAL] blocking and async traits. |
| @@ -52,7 +55,7 @@ link:https://github.com/embassy-rs/embassy/tree/main/embassy-boot[embassy-boot] | |||
| 52 | 55 | ||
| 53 | == What is DMA? | 56 | == What is DMA? |
| 54 | 57 | ||
| 55 | For most I/O in embedded devices, the peripheral doesn't directly support the transmission of multiple bits at once, with CAN being a notable exception. Instead, the MCU must write each byte, one at a time, and then wait until the peripheral is ready to send the next. For high I/O rates, this can pose a problem if the MCU must devote an increasing portion of its time handling each byte. The solution to this problem is to use the Direct Memory Access controller. | 58 | For most I/O in embedded devices, the peripheral doesn't directly support the transmission of multiple bytes at once, with CAN being a notable exception. Instead, the MCU must write each byte, one at a time, and then wait until the peripheral is ready to send the next. For high I/O rates, this can pose a problem if the MCU must devote an increasing portion of its time handling each byte. The solution to this problem is to use the Direct Memory Access controller. |
| 56 | 59 | ||
| 57 | The Direct Memory Access controller (DMA) is a controller that is present in MCUs that Embassy supports, including stm32 and nrf. The DMA allows the MCU to set up a transfer, either send or receive, and then wait for the transfer to complete. With DMA, once started, no MCU intervention is required until the transfer is complete, meaning that the MCU can perform other computation, or set up other I/O while the transfer is in progress. For high I/O rates, DMA can cut the time that the MCU spends handling I/O by over half. However, because DMA is more complex to set-up, it is less widely used in the embedded community. Embassy aims to change that by making DMA the first choice rather than the last. Using Embassy, there's no additional tuning required once I/O rates increase because your application is already set-up to handle them. | 60 | The Direct Memory Access controller (DMA) is a controller that is present in MCUs that Embassy supports, including stm32 and nrf. The DMA allows the MCU to set up a transfer, either send or receive, and then wait for the transfer to complete. With DMA, once started, no MCU intervention is required until the transfer is complete, meaning that the MCU can perform other computation, or set up other I/O while the transfer is in progress. For high I/O rates, DMA can cut the time that the MCU spends handling I/O by over half. However, because DMA is more complex to set-up, it is less widely used in the embedded community. Embassy aims to change that by making DMA the first choice rather than the last. Using Embassy, there's no additional tuning required once I/O rates increase because your application is already set-up to handle them. |
| 58 | 61 | ||
| @@ -74,6 +77,11 @@ include::embassy_in_the_wild.adoc[leveloffset = 2] | |||
| 74 | 77 | ||
| 75 | For more reading material on async Rust and Embassy: | 78 | For more reading material on async Rust and Embassy: |
| 76 | 79 | ||
| 77 | * link:https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown[Comparsion of FreeRTOS and Embassy] | 80 | * link:https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown[Comparison of FreeRTOS and Embassy] |
| 78 | * link:https://dev.to/apollolabsbin/series/20707[Tutorials] | 81 | * link:https://dev.to/apollolabsbin/series/20707[Tutorials] |
| 79 | * link:https://blog.drogue.io/firmware-updates-part-1/[Firmware Updates with Embassy] | 82 | * link:https://blog.drogue.io/firmware-updates-part-1/[Firmware Updates with Embassy] |
| 83 | |||
| 84 | Videos: | ||
| 85 | |||
| 86 | * link:https://www.youtube.com/watch?v=pDd5mXBF4tY[Intro to Embassy] | ||
| 87 | * link:https://www.youtube.com/watch?v=wni5h5vIPhU[From Zero to Async in Embedded Rust] | ||
diff --git a/docs/pages/project_structure.adoc b/docs/pages/project_structure.adoc index 722ec8d9d..227508b97 100644 --- a/docs/pages/project_structure.adoc +++ b/docs/pages/project_structure.adoc | |||
| @@ -85,9 +85,9 @@ A minimal example: | |||
| 85 | [source,toml] | 85 | [source,toml] |
| 86 | ---- | 86 | ---- |
| 87 | [toolchain] | 87 | [toolchain] |
| 88 | channel = "nightly-2023-08-19" # <- as of writing, this is the exact rust version embassy uses | 88 | channel = "1.85" # <- as of writing, this is the exact rust version embassy uses |
| 89 | components = [ "rust-src", "rustfmt" ] # <- optionally add "llvm-tools-preview" for some extra features like "cargo size" | 89 | components = [ "rust-src", "rustfmt" ] # <- optionally add "llvm-tools-preview" for some extra features like "cargo size" |
| 90 | targets = [ | 90 | targets = [ |
| 91 | "thumbv6m-none-eabi" # <-change for your platform | 91 | "thumbv6m-none-eabi" # <- change for your platform |
| 92 | ] | 92 | ] |
| 93 | ---- | 93 | ---- |
diff --git a/docs/pages/system.adoc b/docs/pages/system.adoc index 985f92b18..09241a8df 100644 --- a/docs/pages/system.adoc +++ b/docs/pages/system.adoc | |||
| @@ -6,6 +6,7 @@ include::runtime.adoc[leveloffset = 2] | |||
| 6 | include::bootloader.adoc[leveloffset = 2] | 6 | include::bootloader.adoc[leveloffset = 2] |
| 7 | include::time_keeping.adoc[leveloffset = 2] | 7 | include::time_keeping.adoc[leveloffset = 2] |
| 8 | include::hal.adoc[leveloffset = 2] | 8 | include::hal.adoc[leveloffset = 2] |
| 9 | include::imxrt.adoc[leveloffset = 2] | ||
| 9 | include::nrf.adoc[leveloffset = 2] | 10 | include::nrf.adoc[leveloffset = 2] |
| 10 | include::stm32.adoc[leveloffset = 2] | 11 | include::stm32.adoc[leveloffset = 2] |
| 11 | include::sharing_peripherals.adoc[leveloffset = 2] | 12 | include::sharing_peripherals.adoc[leveloffset = 2] |
